数学建模社区-数学中国

标题: Lu基于系统内置对象创建扩展数据类型,小矩阵乘效率测试 [打印本页]

作者: forcal    时间: 2011-10-23 09:37
标题: Lu基于系统内置对象创建扩展数据类型,小矩阵乘效率测试
    本例中,我们将基于系统内置实数数组创建矩阵(matrix)类型,即:基本类型为luDynData_realarray(标识实数数组),扩展类型为matrix(标识矩阵)。为了简单,我们仅处理二维实数数组即矩阵类型。, E/ ~6 b3 u# O4 J3 C# ?
+ I* x( @. g1 w% k1 a
    基本要点:% y% ^" G: [  K$ P

- c* H6 [- g4 L, W; @9 ^, g) f9 Z    (1)为扩展类型matrix编写运算符重载函数OpMatrix。) H) }# n0 C$ q0 @

, M8 X( U  ^) i, B7 k& }    (2)用函数LockKey将重载函数OpMatrix注册到Lu,锁定的键的类型即为matrix,要注册为常量,以便于使用。$ f! ~' x& l, G" Q6 `- x
+ J$ w9 Y' O- D7 w. O8 q
    (3)为扩展类型matrix编写其他操作函数(本例未提供)。5 P- B/ e$ E, j0 \- ]
" Z+ \% g* ?7 q/ \4 d+ [9 n. n
    (4)用函数LockKey解锁键matrix(本例中,程序退出时会自动解锁,故可以不用)。
  1. #include <windows.h>
    0 u/ j! @/ z2 r6 X6 t4 W3 b
  2. #include <iostream>7 M8 J! z% n$ \4 L) W
  3. #include <math.h>
    + F2 `; T1 _  h! W# v& D
  4. #include "lu32.h"
    - T* H/ y5 e7 G! r! }% h& q1 j: ]

  5. . `$ h2 z* Y$ m- T
  6. #pragma comment( lib, "lu32.lib" )
    * b1 u) _" F  K8 V$ J/ ~

  7. ; p+ ~$ }# q, I
  8. using namespace std;
    & y/ u) g8 X  O+ w
  9. " B9 W0 e" ~& m$ l9 l& e
  10. luKEY Matrix=-1000;        //标识矩阵类型,最终的Matrix由LockKey决定
    ! h0 v- O9 D- R- ]/ ~

  11. 3 I5 d2 A/ e* i, \- Z) H' o: x
  12. void _stdcall LuMessage(wchar_t *pch)//输出动态库信息,该函数注册到Lu,由Lu二级函数调用
    9 R1 V& O5 p% p
  13. {
    2 A6 N7 B  Z" a* T0 H" z) K; ^
  14.         wcout<<pch;% u7 V: \4 c4 x4 q6 d
  15. }
    & d( b& }$ w/ z0 ^
  16. void _stdcall DelMatrix(void *me)        //用于LockKey函数,因为是基于系统内置实数数组创建矩阵,故该函数什么也不做1 i0 i9 K8 x5 @6 o. n( O
  17. {) N6 n$ _8 @4 V7 ]! L
  18. }0 g) n9 n/ K- G. i- ^1 q2 {/ M) q( J: s/ M
  19. LuData _stdcall OpMatrix(luINT mm,LuData *xx,void *hFor,int theOperator)        //运算符重载函数,用于LockKey函数9 J/ i& S  s+ F0 y
  20. {1 v4 e, V: B! W3 N8 E" Q  r
  21.         LuData a;
    : B+ o: W; R) V% H6 y2 d4 n
  22.         luRealArray *pRealArray1,*pRealArray2,*pRealArray3;
    5 R% W2 S, h4 h4 `2 D+ }
  23.         luVOID i,j,k,m,n,u,v;& v8 I( S/ w9 y# g
  24.         double *pa,*pb,*pc;
    $ x, `; N+ h, A" `+ O2 }7 ~
  25.         luMessage pMessage;
    6 T- N( ]$ R& d: x/ \$ G5 E4 o
  26.         wchar_t wchNum[32];7 V- {" {5 [9 y- i8 q6 D
  27.         char chNum[32];0 I# I- Y+ ?4 R. Z) p3 F2 X
  28.         a.BType=luStaData_nil; a.VType=luStaData_nil; a.x=0;* W  ^1 H2 U  a. P
  29.         switch(theOperator)
    4 u# e1 h8 i9 F% O: `+ p' ?' u9 V
  30.         {' f8 a' {; ~& j% H2 J1 y
  31.         case 2:        //重载运算符*
    % V3 u' R2 j6 r/ R
  32.                 pRealArray1=(luRealArray *)SearchKey((char *)&(xx->x),sizeof(luVOID),luDynData_realarray);* F' K2 v- h  O- s
  33.                 pRealArray2=(luRealArray *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),luDynData_realarray);
    9 b9 K* i. H# c
  34.                 if(!pRealArray1 || !pRealArray2) break;        //对象句柄无效,不是实数数组
    5 _2 w3 w& @8 V0 n. ~! y9 N7 A- b
  35.                 if(pRealArray1->DimLen!=2 || pRealArray2->DimLen!=2) break;        //不是二维实数数组(矩阵)
    1 C, e" _+ s! ^3 X+ B( b
  36.                 if(pRealArray1->Dim[1]!=pRealArray2->Dim[0]) break;        //维数不匹配7 r4 a/ K2 \% W( @
  37.                 pRealArray3=(luRealArray *)NewSysObj(luDynData_realarray,pRealArray1->Dim[0]*pRealArray2->Dim[1],2);        //创建矩阵对象: y$ B- N8 V3 B. e2 o" H
  38.                 if(!pRealArray3) break;
    , A' J1 ^4 h4 f- a
  39.                 pRealArray3->Dim[0]=pRealArray1->Dim[0]; pRealArray3->Dim[1]=pRealArray2->Dim[1];        //设置矩阵维数大小6 |9 G% W7 E; b/ ~1 \8 x3 b
  40.                 pa=pRealArray1->Array; pb=pRealArray2->Array; pc=pRealArray3->Array;
    5 E, ~) t( |7 a$ P# i* F
  41.                 m=pRealArray1->Dim[0]; n=pRealArray1->Dim[1]; k=pRealArray2->Dim[1];) L! m+ u9 L6 G: F
  42.                 for(i=0; i<m; i++)        //矩阵乘; }0 ?4 l3 s3 m) B
  43.                 {
    5 s4 M+ ^0 N$ q
  44.                         for(j=0; j<k; j++)
    / U" W" \1 K) e* H7 e
  45.                         {9 g" o/ \% a5 i# ~) J
  46.                                 u=i*k+j; pc[u]=0.0;
    " W& M9 M: p7 c7 ~; g- S
  47.                                 for (v=0; v<n; v++)3 U1 e  O$ x/ e2 ?" B2 l7 D
  48.                                 {5 J4 Q0 f2 {; j, w
  49.                                         pc[u]=pc[u]+pa[i*n+v]*pb[v*k+j];9 L5 t) a/ i5 p: X4 b
  50.                                 }
    / x' J7 d! d( e( I, j& K3 _
  51.                         }
    6 x# k9 p! M, J, O, v6 c- S8 _, g
  52.                 }
    1 x: i& g! E* m# G1 F3 G
  53.                 FunReObj(hFor);        //告诉Lu,返回一个动态对象
    7 F! k0 J2 Y* i1 l" K& W5 O3 B- B( e7 x
  54.                 a.BType=luDynData_realarray; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pRealArray3;
    ' }% `; x0 T- M& j
  55.                 break;4 x2 k8 v# w7 M" C' _6 h. w
  56.         case 25:        //重载运算符.*; A# r5 ~# g: C2 B+ ^# c
  57.                 pRealArray1=(luRealArray *)SearchKey((char *)&(xx->x),sizeof(luVOID),luDynData_realarray);. S  `2 n  p" `9 E/ `) B4 ^
  58.                 pRealArray2=(luRealArray *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),luDynData_realarray);* Y: }& U$ H+ G4 s7 G
  59.                 if(!pRealArray1 || !pRealArray2) break;        //对象句柄无效,不是实数数组# J; W) }  W$ f* j
  60.                 if(pRealArray1->DimLen!=2 || pRealArray2->DimLen!=2) break;        //不是二维实数数组(矩阵)/ D( v; n* C, p1 v) ~; U5 x* t
  61.                 if(pRealArray1->Dim[0]!=pRealArray2->Dim[0] || pRealArray1->Dim[1]!=pRealArray2->Dim[1]) break;        //维数不相同. H1 |- n6 ]- K' U- `
  62.                 pRealArray3=(luRealArray *)NewSysObj(luDynData_realarray,pRealArray1->ArrayLen,2);        //创建矩阵对象
    " f& A: O; X5 Y' W, L+ S
  63.                 if(!pRealArray3) break;
    % ^$ Z' X3 q% Q
  64.                 pRealArray3->Dim[0]=pRealArray1->Dim[0]; pRealArray3->Dim[1]=pRealArray1->Dim[1];        //设置矩阵维数大小
    ' m" s" Y& j3 u
  65.                 for(i=0;i<pRealArray1->ArrayLen;i++) pRealArray3->Array[i]=pRealArray1->Array[i]*pRealArray2->Array[i];//矩阵点乘
    ; k( w: j" W# x/ h2 o7 ?6 V
  66.                 FunReObj(hFor);        //告诉Lu,返回一个动态对象  e4 h0 h  v3 W2 V
  67.                 a.BType=luDynData_realarray; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pRealArray3;; G' g& P4 G  [1 |4 k. f" }
  68.                 break;8 I% X; [) F0 K( C
  69.         case 46:        //重载函数new
    ! b+ R' T& _* p: }4 J$ X4 A# b
  70.                 a=ExeOperator(mm,xx,hFor,theOperator,luDynData_realarray);        //直接调用基本类型luDynData_realarray的new函数. W) P6 H$ v" |7 i
  71.                 if(a.VType==luDynData_realarray) a.VType=Matrix;        //设置扩展类型为自定义的Matrix类型- K5 O( ^- Y. {( r+ W( t4 U+ p
  72.                 break;
    ! Q$ g( Q4 e; S9 I' E
  73.         case 49:        //重载函数o
    9 Z- A: R& }6 u3 \6 N
  74.                 pMessage=(luMessage)SearchKey("\0\0\0\0",sizeof(luVOID),luPubKey_User);
    & }" v5 [4 v1 J% l' t* r3 |$ \
  75.                 if(!pMessage) break;( C9 `3 k% N* w& w% [: t) J4 e  K
  76.                 pRealArray1=(luRealArray *)SearchKey((char *)&(xx->x),sizeof(luVOID),luDynData_realarray);4 V$ K6 D+ C' ~* k' [
  77.                 if(!pRealArray1) break;        //对象句柄无效,不是实数数组" x; {5 d3 e' x) I6 O
  78.                 if(pRealArray1->DimLen!=2) break;        //不是二维实数数组(矩阵)
    : t- c9 I9 {, E4 q. c
  79.                 pa=pRealArray1->Array;7 m( h6 ]: m- L* H
  80.                 m=pRealArray1->Dim[0]; n=pRealArray1->Dim[1]; k=0;
    / R, P. a  [6 {# W# A( ], f
  81.                 for(i=0; i<m; i++)        //输出矩阵
    / _4 w+ [4 U/ d/ D
  82.                 {. q' i9 \( x4 ~
  83.                         pMessage(L"\r\n"); k+=2;6 s* R! L# v- H. {6 ^7 i: j0 h' n
  84.                         for(j=0; j<n; j++)
    9 M/ L+ D* N0 V2 G1 P
  85.                         {( J2 k8 N- `9 U0 u4 `1 q
  86.                                 _gcvt_s(chNum,pa[i*n+j],16);
    8 N% z0 `: O# a& H; G& ^) J
  87.                                 for(u=0;chNum[u];u++) {wchNum[u]=chNum[u]; k++;}/ t, S! e. Q3 q
  88.                                 wchNum[u]='\0';1 z7 q& S/ F  C% {# I/ q
  89.                                 pMessage(wchNum); pMessage(L"  "); k+=2;
    , f6 S( {/ `$ n) U
  90.                         }/ q0 T9 Q  w2 k7 L0 y! u
  91.                 }
    % Z: L5 W/ [* h6 O+ H7 W0 D6 v5 a
  92.                 pMessage(L"\r\n"); k+=2;& P3 c8 @0 f5 A" q" C  D
  93.                 a.BType=luStaData_int64; a.VType=luStaData_int64; a.x=k;        //按函数o的要求,返回输出的字符总数
    * k- z& m1 K* T
  94.                 break;! P- L" q* F$ j6 X% G( J. e9 d- u
  95.         default:
    7 R. {+ V% a: Q
  96.                 break;, E- v" J- {+ o  F
  97.         }
      n0 W. V9 n% d! W' _3 t
  98.         return a;" X) M, W& u- z# m% j
  99. }
    ) M* S* ]/ S9 K. E, \$ m7 o: x
  100. void main(void)$ Y3 l5 K4 [2 L9 H* r, J+ a% j/ U: j5 P
  101. {
    & N# a! `+ _" E( V2 Q5 ?
  102.         void *hFor;                //表达式句柄
    , ]% F( r& u& _- z" F1 g
  103.         luINT nPara;                //存放表达式的自变量个数; w% D; B0 f* h7 s2 ]6 d
  104.         LuData *pPara;                //存放输入自变量的数组指针
    " H2 \- T1 Q) ~$ t
  105.         luINT ErrBegin,ErrEnd;        //表达式编译出错的初始位置和结束位置1 x0 C6 X1 p# W1 s) T
  106.         int ErrCode;                //错误代码
    * I2 I, j- Y7 U
  107.         void *v;, w$ |* |; X3 @2 v, X
  108.         wchar_t ForStr[]=L"o{new[matrix,2,3,data: 0.,1.,2.;3.,4.,5.]*new[matrix,3,2,data: 1.,2.;3.,4.;5.,6.]}";//字符串表达式,矩阵乘
    & t. s! ^4 T. b; A" X3 K+ ^" k
  109.         //wchar_t ForStr[]=L"o{new[matrix,2,3,data: 0.,1.,2.;3.,4.,5.].*new[matrix,2,3,data: 1.,2.,3.;4.,5.,6.]}";//字符串表达式,矩阵点乘, [$ w# F0 b4 D) ^! p/ \: ]
  110.         LuData Val;
    4 M* @) }+ s8 O1 Q6 @6 l; ~
  111.         if(!InitLu()) return;        //初始化Lu
    ) y3 d& z1 @7 r. B' t# l, s) d3 @
  112.         while(LockKey(Matrix,DelMatrix,OpMatrix)){Matrix++;}        //锁定一个键,用于存储矩阵扩展类型9 ?( k% ~, k3 p

  113.   P' P# U9 U* [: L4 e9 i4 M
  114.         Val.BType=luStaData_int64; Val.VType=luStaData_int64; Val.x=Matrix;        //定义整数常量3 |  l3 p# H$ |  e4 D, Y
  115.         SetConst(L"matrix",&Val);        //设置整数常量
    / N5 O6 T' t" Y2 k5 o
  116.         InsertKey("\0\0\0\0",4,luPubKey_User,LuMessage,NULL,NULL,1,v); //使Lu运行时可输出函数信息
    & w1 l, |! l! T: k  n- h
  117.         wcout.imbue(locale("chs"));        //设置输出的locale为中文
    1 Z; p! U$ R( v
  118.   - f$ E: S5 B, i# e% K
  119.         ErrCode=LuCom(ForStr,0,0,0,hFor,nPara,pPara,ErrBegin,ErrEnd); //编译表达式. g7 b/ w% y+ a7 b
  120.         if(ErrCode)/ b3 h/ `3 j( c) L$ r' A5 V
  121.         {
    3 S- m8 k6 L# N" S: l
  122.                 wcout<<L"表达式有错误!错误代码:"<<ErrCode<<endl;, c; j, \5 n1 {2 s7 U2 D
  123.         }* |7 ~$ q) S# k& W. u
  124.         else
    $ X0 [$ d" G% K- Z% Z# {6 {8 V6 m
  125.         {9 H2 Y+ b# q' x" }- \4 c2 F* e
  126.                 LuCal(hFor,pPara);        //计算表达式的值1 M9 `8 ?8 M6 |( ?" i! _9 E8 `4 G' F
  127.         }
    1 Z! I. X( c; {
  128.         LockKey(Matrix,NULL,OpMatrix);//解锁键Matrix,本例中,该函数可以不用& W: P, g! K/ H7 [- B
  129.         FreeLu();                        //释放Lu
    5 m% e: }' {; v& U* T5 q: R
  130. }
复制代码
习题:8 x; U/ d2 }( q, I
8 @/ z5 O) p7 k
    (1)自定义矩阵的加、减、左除、右除、点左除等运算,自编测试字符串代码,重新编译运行程序,观察计算结果。
5 \4 T/ I7 Q" Z& d7 d" P( ^( Y
7 C4 W* u: c$ y* ?    (2)小矩阵乘效率测试。编译运行以下Lu字符串代码:
  1. main(:a,b,c,d,t,i)=
    7 c1 f5 g4 ^, m* F
  2.     a=new[matrix,2,2,data:1.,2.,2.,1.],
    ) }' o4 ?, ^, {, f6 t: ?) A' v
  3.     b=new[matrix,2,2,data:2.,1.,1.,2.],
    . c$ X4 J' V' N9 ]
  4.     c=new[matrix,2,2,data:2/3.,-1/3.,-1/3.,2/3.],
    - T: x  u5 R6 k/ V
  5.     t=clock(),% A/ R, a1 k/ q  b
  6.     d=a*b, i=0, while{i<1000000, d=d*c*b, i++},
    1 n) E/ l, ]3 C: c/ c" V
  7.     o{d, "time=",[clock()-t]/1000.," seconds.\r\n"}
复制代码
C/C++中的字符串定义为:
  1. wchar_t ForStr[]=L"main(:a,b,c,d,t,i)= a=new[matrix,2,2,data:1.1,2.,2.,1.], b=new[matrix,2,2,data:2.,1.,1.,2.], c=new[matrix,2,2,data:2/3.,-1/3.,-1/3.,2/3.], t=clock(), d=a*b, i=0, while{i<1000000, d=d*c*b, i++}, o{d, \"time=\",[clock()-t]/1000.,\" seconds.\r\n\"}";//字符串表达式
复制代码
结果:
  1. 4. 5.
    / r8 e8 |* R5 G2 e
  2. 5. 4.
    3 F- K2 K9 V! K6 c, N
  3. time=0.875 seconds.$ k# k! G( c8 o: N2 i
  4. 请按任意键继续. . .
复制代码
Matlab 2009a 代码:
  1. a=[1.,2.;2.,1.];3 X$ r2 C( L: T/ ]
  2. b=[2.,1.;1.,2.];
    8 w5 ~* m  f  [6 Q% j6 N
  3. c=[2/3.,-1/3.;-1/3.,2/3.];
    / L" ?$ K! y2 s/ z
  4. tic,
    $ R( f- N0 I9 r! ~$ Z4 ?
  5. d=a*b;2 F7 w/ d' {) o/ z& J4 I
  6. for i=1:10000005 f' Y) L5 u0 [) H  {
  7.     d=d*c*b;
    0 @3 v; C, w4 ]  R
  8. end
    5 @$ N$ o2 N3 D0 C
  9. d,- x7 O% t* e; }. _( A
  10. toc
复制代码
结果:
  1. d =
    5 ]6 g: P2 i4 a5 t4 @% w* v
  2.      4     5& d& P& y! k: C! C) C" K
  3.      5     4" b0 |$ q/ k: X) ?! z2 g; t( j9 N
  4. Elapsed time is 2.903034 seconds.
复制代码
本例矩阵乘效率测试,Lu的速度超过了Matlab,主要在于Lu有更高的动态对象管理效率。$ v# f9 k" P: I/ A$ i2 I





欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5