数学建模社区-数学中国

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

作者: forcal    时间: 2011-10-23 09:37
标题: Lu基于系统内置对象创建扩展数据类型,小矩阵乘效率测试
    本例中,我们将基于系统内置实数数组创建矩阵(matrix)类型,即:基本类型为luDynData_realarray(标识实数数组),扩展类型为matrix(标识矩阵)。为了简单,我们仅处理二维实数数组即矩阵类型。
" n, e+ P! P5 [3 M: q. C  X% ~
" r/ b& H1 R" c# b9 l    基本要点:
$ o$ c+ u. z9 J
- K2 A; Y) i! v) B    (1)为扩展类型matrix编写运算符重载函数OpMatrix。; I( D1 d, b, y3 b3 [) H' e6 i6 W, E
: j) W6 i" n. ~: E( x$ ^6 [
    (2)用函数LockKey将重载函数OpMatrix注册到Lu,锁定的键的类型即为matrix,要注册为常量,以便于使用。6 O7 \* A8 L$ M3 L

4 t% r5 K, \7 R% Q: L+ V    (3)为扩展类型matrix编写其他操作函数(本例未提供)。
5 E5 N: ]3 k$ Z1 N9 v7 i! z
' P% Z3 {, x2 C& P& e    (4)用函数LockKey解锁键matrix(本例中,程序退出时会自动解锁,故可以不用)。
  1. #include <windows.h>* c, {3 x0 u6 c) a; J
  2. #include <iostream>3 F+ k# z7 D* [3 q* E! `* x
  3. #include <math.h>
    : ]! v) K" ^6 ~% E6 ?
  4. #include "lu32.h"9 A# F; u. w% `3 a4 b" {, V
  5. / t7 {/ `! o0 v$ T7 q9 J
  6. #pragma comment( lib, "lu32.lib" )
    : ~1 |; j$ l/ J- U$ D( \

  7. + E; j6 z  k* h, `: i
  8. using namespace std;5 a9 E) ~& m' E; [) t

  9. 6 j' F; h% ?! Y- f3 ?
  10. luKEY Matrix=-1000;        //标识矩阵类型,最终的Matrix由LockKey决定/ n/ L  |. L: o6 N3 o
  11.   `8 y" E9 A+ Y/ J% q3 R
  12. void _stdcall LuMessage(wchar_t *pch)//输出动态库信息,该函数注册到Lu,由Lu二级函数调用
    , }' M% p6 L* ~3 i# k, |1 ^0 G
  13. {
    4 y4 m1 v2 t" ]% |
  14.         wcout<<pch;$ ^' g' j9 m8 l2 G, |$ f4 t
  15. }
    + w( Q- g3 P/ i( i2 `
  16. void _stdcall DelMatrix(void *me)        //用于LockKey函数,因为是基于系统内置实数数组创建矩阵,故该函数什么也不做
    0 _0 S: O! x* U, U
  17. {
    ( q: j- C  Z+ l- |# d  F  [% i" l
  18. }3 b5 h$ X- q& t  c0 u- o
  19. LuData _stdcall OpMatrix(luINT mm,LuData *xx,void *hFor,int theOperator)        //运算符重载函数,用于LockKey函数
    7 x% O1 v! x& {- I6 S7 I
  20. {/ S8 ^3 _4 g3 k/ \
  21.         LuData a;
    & ^$ N0 s: Y( w; n. Q/ A+ o
  22.         luRealArray *pRealArray1,*pRealArray2,*pRealArray3;
    3 u4 \5 A( V$ W5 U, i% D
  23.         luVOID i,j,k,m,n,u,v;
    6 D% V6 p9 }1 H
  24.         double *pa,*pb,*pc;
    / e" S3 S) p5 p( Z6 t9 N( L
  25.         luMessage pMessage;
    + n; K! e2 w# \7 D) K" x
  26.         wchar_t wchNum[32];
    8 q4 l; D* R( I+ f; V( x  o& u" A
  27.         char chNum[32];
    3 r* U, X( a; H7 d9 ~
  28.         a.BType=luStaData_nil; a.VType=luStaData_nil; a.x=0;
    ' I% k) J8 @2 s+ O, T
  29.         switch(theOperator)
    . T5 U/ Y) r6 f; ?( A% v
  30.         {
    5 P; @* s. l5 W# t8 B) v- p
  31.         case 2:        //重载运算符*9 A; J4 X- i- ~( E2 B; g
  32.                 pRealArray1=(luRealArray *)SearchKey((char *)&(xx->x),sizeof(luVOID),luDynData_realarray);" l+ z5 w2 X# Z0 Z' W- k
  33.                 pRealArray2=(luRealArray *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),luDynData_realarray);
    " H8 \- }1 |% K. G5 n" T
  34.                 if(!pRealArray1 || !pRealArray2) break;        //对象句柄无效,不是实数数组4 [7 j$ Y1 Z- W, y1 g- o
  35.                 if(pRealArray1->DimLen!=2 || pRealArray2->DimLen!=2) break;        //不是二维实数数组(矩阵)0 S7 \8 z' s' R# |2 @( E
  36.                 if(pRealArray1->Dim[1]!=pRealArray2->Dim[0]) break;        //维数不匹配6 S- ?5 i! R- b$ J+ C. S
  37.                 pRealArray3=(luRealArray *)NewSysObj(luDynData_realarray,pRealArray1->Dim[0]*pRealArray2->Dim[1],2);        //创建矩阵对象3 }+ z* G* r, Q, Q8 M9 U
  38.                 if(!pRealArray3) break;
    " C: K/ d5 L3 q* M3 J+ r* T
  39.                 pRealArray3->Dim[0]=pRealArray1->Dim[0]; pRealArray3->Dim[1]=pRealArray2->Dim[1];        //设置矩阵维数大小
    / P2 [$ p" V# D9 M6 p4 m: \
  40.                 pa=pRealArray1->Array; pb=pRealArray2->Array; pc=pRealArray3->Array;
    ) y) m. P& Q2 {# B
  41.                 m=pRealArray1->Dim[0]; n=pRealArray1->Dim[1]; k=pRealArray2->Dim[1];9 X# Q) S1 I. U$ Y
  42.                 for(i=0; i<m; i++)        //矩阵乘. u& F5 [9 w* F* z# \1 W" F
  43.                 {
    8 R7 }+ \; Y" I' J3 i9 l* A
  44.                         for(j=0; j<k; j++)
    6 j8 N+ \0 Q& c) @2 r
  45.                         {& U) k. F9 b; W4 G
  46.                                 u=i*k+j; pc[u]=0.0;
    " C9 p- B' b) }) O2 I# p
  47.                                 for (v=0; v<n; v++); J+ u6 U# F$ o5 m7 Q$ Z$ F; I
  48.                                 {
    4 C8 c: L6 S+ g% n2 t6 u5 w3 ?
  49.                                         pc[u]=pc[u]+pa[i*n+v]*pb[v*k+j];
    : R: [4 z7 ]: P! d( w4 o
  50.                                 }8 i& R$ o* p$ M# ?  _+ D
  51.                         }
    2 q% s4 m/ }- _' ]6 \- X
  52.                 }
    4 O) E" B, ~; w& L- u
  53.                 FunReObj(hFor);        //告诉Lu,返回一个动态对象
    , D2 T  z1 q2 x9 A
  54.                 a.BType=luDynData_realarray; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pRealArray3;$ H' u. J8 l* D: T* |
  55.                 break;
    " N6 `1 w* }# D! {4 Y
  56.         case 25:        //重载运算符.*( r# z3 Q8 Q( I4 s. [( y4 I
  57.                 pRealArray1=(luRealArray *)SearchKey((char *)&(xx->x),sizeof(luVOID),luDynData_realarray);
    # c. `; m8 Y1 y$ B6 i$ K: F2 h1 w
  58.                 pRealArray2=(luRealArray *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),luDynData_realarray);5 L$ ^% E) A9 d* x
  59.                 if(!pRealArray1 || !pRealArray2) break;        //对象句柄无效,不是实数数组: {7 ^7 C7 b1 \! w0 y+ X- D& Y! c
  60.                 if(pRealArray1->DimLen!=2 || pRealArray2->DimLen!=2) break;        //不是二维实数数组(矩阵)' w/ F6 u7 U! @# s
  61.                 if(pRealArray1->Dim[0]!=pRealArray2->Dim[0] || pRealArray1->Dim[1]!=pRealArray2->Dim[1]) break;        //维数不相同
    ' j3 D. ~8 x7 @  j
  62.                 pRealArray3=(luRealArray *)NewSysObj(luDynData_realarray,pRealArray1->ArrayLen,2);        //创建矩阵对象% Z' a! Y0 _1 r! L" O- H0 R/ K
  63.                 if(!pRealArray3) break;
    8 j: n5 S) A4 p4 q
  64.                 pRealArray3->Dim[0]=pRealArray1->Dim[0]; pRealArray3->Dim[1]=pRealArray1->Dim[1];        //设置矩阵维数大小
    / r( T9 U" W9 x" `
  65.                 for(i=0;i<pRealArray1->ArrayLen;i++) pRealArray3->Array[i]=pRealArray1->Array[i]*pRealArray2->Array[i];//矩阵点乘
    , I2 l+ A8 _* h' ?% q1 g
  66.                 FunReObj(hFor);        //告诉Lu,返回一个动态对象5 O* q: y! J2 v0 w- D" r8 K2 v
  67.                 a.BType=luDynData_realarray; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pRealArray3;
    + b' s& @7 I6 ^! e$ [5 f& s. c
  68.                 break;
    , `6 K( K% p& y' B
  69.         case 46:        //重载函数new0 u4 \+ H, z; v2 }  A
  70.                 a=ExeOperator(mm,xx,hFor,theOperator,luDynData_realarray);        //直接调用基本类型luDynData_realarray的new函数
    # h/ R$ x6 n% e& m+ ?
  71.                 if(a.VType==luDynData_realarray) a.VType=Matrix;        //设置扩展类型为自定义的Matrix类型0 H5 J+ \) n8 w$ D
  72.                 break;' E: P. f: ]% \5 @2 W( C" J
  73.         case 49:        //重载函数o) Q' n9 D) S; V/ G- k  t: L' D
  74.                 pMessage=(luMessage)SearchKey("\0\0\0\0",sizeof(luVOID),luPubKey_User);5 R! i+ s2 p1 k0 ~9 @
  75.                 if(!pMessage) break;
    ' h& a  c* U3 [* T6 `' p/ u
  76.                 pRealArray1=(luRealArray *)SearchKey((char *)&(xx->x),sizeof(luVOID),luDynData_realarray);
    ! V8 b2 J7 Y) \& G4 U. t( _% j
  77.                 if(!pRealArray1) break;        //对象句柄无效,不是实数数组: m9 q* j% m3 k) f* N, S
  78.                 if(pRealArray1->DimLen!=2) break;        //不是二维实数数组(矩阵)+ m- F. }! C9 j7 J6 L6 X
  79.                 pa=pRealArray1->Array;+ H  X/ j" `2 g1 m4 q9 |" G
  80.                 m=pRealArray1->Dim[0]; n=pRealArray1->Dim[1]; k=0;
    4 k" c0 D4 W5 R1 v1 q9 K9 \
  81.                 for(i=0; i<m; i++)        //输出矩阵7 ?: {& N/ P+ S2 ~  F. L0 [; I
  82.                 {
    ( y1 ?/ M8 r) n& v
  83.                         pMessage(L"\r\n"); k+=2;% f1 k- s$ c# P+ G5 @+ x9 O+ Z
  84.                         for(j=0; j<n; j++). V8 k: i% K8 S, D: d- Z
  85.                         {
    2 c% A, ]' E7 B( p; s2 X0 O
  86.                                 _gcvt_s(chNum,pa[i*n+j],16);
    0 u! A9 q& u5 |* l
  87.                                 for(u=0;chNum[u];u++) {wchNum[u]=chNum[u]; k++;}
    ; U7 L# J& |; j5 C; e4 I
  88.                                 wchNum[u]='\0';" A2 u! v$ J" {
  89.                                 pMessage(wchNum); pMessage(L"  "); k+=2;
    9 l* w* Z5 `5 I0 F5 D
  90.                         }
    # F. R' R% ?# g/ S4 w- |
  91.                 }: O+ ~6 D9 K' }, V, A
  92.                 pMessage(L"\r\n"); k+=2;- ?% v; Y1 K# j. c( ^
  93.                 a.BType=luStaData_int64; a.VType=luStaData_int64; a.x=k;        //按函数o的要求,返回输出的字符总数; V2 |  `: r( C- Z7 p; ?
  94.                 break;
    & s& {+ y* d/ O
  95.         default:) W* O  h6 |2 A6 r
  96.                 break;
    7 Q- w# z( G* F9 F9 \, f
  97.         }9 G0 |! t# c5 L% _. E
  98.         return a;! k  A% d; A: \# N/ h9 z' b
  99. }
    5 o1 `$ a8 l4 f6 Z9 v
  100. void main(void)5 C( N8 Q* R5 u9 W
  101. {; o& H% o3 E: q/ X- n0 X  u
  102.         void *hFor;                //表达式句柄
    9 a* C( W+ }5 K: G4 s+ y* }
  103.         luINT nPara;                //存放表达式的自变量个数
    5 N! K0 X6 L! n7 ^8 b2 ~4 {
  104.         LuData *pPara;                //存放输入自变量的数组指针. O! Z* U. s! b0 Q! Z( B- Z
  105.         luINT ErrBegin,ErrEnd;        //表达式编译出错的初始位置和结束位置4 O9 S$ d' {, a8 `+ x
  106.         int ErrCode;                //错误代码. w% H, ]1 y$ g- I
  107.         void *v;
    1 Q, m4 G/ C* ]6 @, t; R
  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.]}";//字符串表达式,矩阵乘
    ! I: L: D, ~2 V9 k  x' v
  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.]}";//字符串表达式,矩阵点乘( G# M5 o- j" I* h* S
  110.         LuData Val;
      S  w  l7 \! p  @/ ^, Q: ]
  111.         if(!InitLu()) return;        //初始化Lu
    5 C: ?6 e4 i- J8 W/ _; a$ O- h
  112.         while(LockKey(Matrix,DelMatrix,OpMatrix)){Matrix++;}        //锁定一个键,用于存储矩阵扩展类型4 z  ]. s7 l& u3 k0 \4 {
  113. 3 Q/ v6 }: S1 I
  114.         Val.BType=luStaData_int64; Val.VType=luStaData_int64; Val.x=Matrix;        //定义整数常量* N$ l" s8 ~& ^& o. u  j
  115.         SetConst(L"matrix",&Val);        //设置整数常量% h5 y5 ^2 o# t4 U3 p9 u! _
  116.         InsertKey("\0\0\0\0",4,luPubKey_User,LuMessage,NULL,NULL,1,v); //使Lu运行时可输出函数信息/ R7 c- @, O3 S; P% D" Y2 k
  117.         wcout.imbue(locale("chs"));        //设置输出的locale为中文
    & _" a9 z2 D1 `
  118.   
    3 H5 z9 I# g4 _1 Y
  119.         ErrCode=LuCom(ForStr,0,0,0,hFor,nPara,pPara,ErrBegin,ErrEnd); //编译表达式+ p, v" e% L2 L3 C1 b% ~( H3 A
  120.         if(ErrCode)* a; `' H  m5 b
  121.         {
    2 E4 {; N  j1 r5 w
  122.                 wcout<<L"表达式有错误!错误代码:"<<ErrCode<<endl;
    ' H! }: t9 ?! {/ [+ N
  123.         }$ S* b8 ]. d" J" A- A# G
  124.         else
    2 N& n. N/ M; `& I
  125.         {% C( l7 P( {7 O! |
  126.                 LuCal(hFor,pPara);        //计算表达式的值
    , t* E* Q2 D4 n1 H- R
  127.         }# l& ]9 v$ O$ x0 X. E. j
  128.         LockKey(Matrix,NULL,OpMatrix);//解锁键Matrix,本例中,该函数可以不用
    * ~# w! ~6 ^8 P2 a$ ^+ c) C% e+ F
  129.         FreeLu();                        //释放Lu
    6 W, V5 g6 x! [- |# d4 C9 U
  130. }
复制代码
习题:9 n8 j7 v6 K( `$ Z5 T
9 e+ V/ [" K& Q% L) a
    (1)自定义矩阵的加、减、左除、右除、点左除等运算,自编测试字符串代码,重新编译运行程序,观察计算结果。 5 j, f1 H; o, n5 y2 T
' z$ Q- S, v: T; Q$ E/ H
    (2)小矩阵乘效率测试。编译运行以下Lu字符串代码:
  1. main(:a,b,c,d,t,i)=& |6 |5 X7 ^4 M- E, K- N  l0 \; S
  2.     a=new[matrix,2,2,data:1.,2.,2.,1.],
    ; _# N6 {# k+ `% @. k* B
  3.     b=new[matrix,2,2,data:2.,1.,1.,2.],
    % x* V* s: m9 {0 ^9 }
  4.     c=new[matrix,2,2,data:2/3.,-1/3.,-1/3.,2/3.],# F: N% o, r+ {2 k! }8 u0 S
  5.     t=clock()," U- D* ?& S( D3 u! @. M$ d
  6.     d=a*b, i=0, while{i<1000000, d=d*c*b, i++},
    ; w, _1 W9 R$ T& w3 l
  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.
    7 s& ]% Q1 V' ]$ O: }
  2. 5. 4.
    / V2 ~! s! p: k' b  g( i
  3. time=0.875 seconds.1 I3 c+ h5 \" d! Q1 Z. ]5 Q7 b, x
  4. 请按任意键继续. . .
复制代码
Matlab 2009a 代码:
  1. a=[1.,2.;2.,1.];
    + U" V% V. p, \$ J: m0 e5 y
  2. b=[2.,1.;1.,2.];$ L1 k; j2 f: g0 |
  3. c=[2/3.,-1/3.;-1/3.,2/3.];
    : n& u3 U' u; w! J" l
  4. tic,$ a8 W9 }' }) Q- b- r* I
  5. d=a*b;
    " @7 i: G  q' }  N5 _( W
  6. for i=1:10000001 R; Z, o, g' s  B! M
  7.     d=d*c*b;5 W3 \2 m; C4 h" [( c( x1 |
  8. end7 a7 Z$ N1 z, @& U% x
  9. d,9 [. F- c. k) V% L! W
  10. toc
复制代码
结果:
  1. d =
    2 o2 n  F+ H3 h: X1 V
  2.      4     52 U: D5 C! q# _. Q' C
  3.      5     43 x, b! t% }! m: H0 \! `  j
  4. Elapsed time is 2.903034 seconds.
复制代码
本例矩阵乘效率测试,Lu的速度超过了Matlab,主要在于Lu有更高的动态对象管理效率。
- i  G4 j  y2 {9 O




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