数学建模社区-数学中国

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

作者: forcal    时间: 2011-10-23 09:37
标题: Lu基于系统内置对象创建扩展数据类型,小矩阵乘效率测试
    本例中,我们将基于系统内置实数数组创建矩阵(matrix)类型,即:基本类型为luDynData_realarray(标识实数数组),扩展类型为matrix(标识矩阵)。为了简单,我们仅处理二维实数数组即矩阵类型。
- [2 W0 d! \: J2 Z
# j  B) G$ l+ t- C    基本要点:5 u% e9 W5 x" z; f5 Z% q! p/ m

% G) ~( o. L, Q1 l: h    (1)为扩展类型matrix编写运算符重载函数OpMatrix。
3 w; e; r- J# ?& {3 a$ s1 U6 a6 I4 S4 F
    (2)用函数LockKey将重载函数OpMatrix注册到Lu,锁定的键的类型即为matrix,要注册为常量,以便于使用。( z" u# w6 q) S; e
' F9 p, {) b3 |  b, M: [
    (3)为扩展类型matrix编写其他操作函数(本例未提供)。
6 ^5 B* l7 m! b5 d2 N
" v5 Y5 O& c) z' L( B; Q3 c! f7 e    (4)用函数LockKey解锁键matrix(本例中,程序退出时会自动解锁,故可以不用)。
  1. #include <windows.h>% ~% v" ~( n/ h
  2. #include <iostream>. C: d) ^0 a" }( k/ \6 a5 Y
  3. #include <math.h>5 r3 ?2 e/ M+ G* a8 H
  4. #include "lu32.h"
    , f* u$ [% o3 J$ l3 N
  5. 7 r& a7 e6 k: Q4 i3 ?5 m6 ^) h
  6. #pragma comment( lib, "lu32.lib" )
    9 y: K5 Z$ e6 E9 v

  7. 8 o  c% c: {  |1 T1 a
  8. using namespace std;
    1 h  H( ]2 Q$ Z! Y* Y5 }

  9. . E! M, c( w; ^6 v4 t  h
  10. luKEY Matrix=-1000;        //标识矩阵类型,最终的Matrix由LockKey决定( B% I& p/ i: U4 U2 X

  11. * z: j( U9 r4 u/ f2 u3 w+ l
  12. void _stdcall LuMessage(wchar_t *pch)//输出动态库信息,该函数注册到Lu,由Lu二级函数调用 + \& Y  f; _' i; X' J  u3 M
  13. {5 }4 M2 B3 {# P% y
  14.         wcout<<pch;8 [0 a' n) y8 [$ y
  15. }8 D1 e1 G' f, t8 J6 L: k
  16. void _stdcall DelMatrix(void *me)        //用于LockKey函数,因为是基于系统内置实数数组创建矩阵,故该函数什么也不做
    9 i) J+ O9 s/ f* q% Y! W( T0 Q
  17. {
    . Y8 H; o) O. G" G9 z' Y8 _7 |) Y
  18. }
    ) w, ^/ h1 s( o' u+ U
  19. LuData _stdcall OpMatrix(luINT mm,LuData *xx,void *hFor,int theOperator)        //运算符重载函数,用于LockKey函数1 d2 c% `- U7 D, M
  20. {$ m# Z8 t  i. y+ |5 v) q* A
  21.         LuData a;" o" q! @) W. n0 N; T6 @
  22.         luRealArray *pRealArray1,*pRealArray2,*pRealArray3;+ W* l8 q$ [5 o6 I5 l) T# k
  23.         luVOID i,j,k,m,n,u,v;# c1 P8 o; W) S8 s6 k' C0 T
  24.         double *pa,*pb,*pc;
    0 {6 ]9 ~- u9 ~; {3 L
  25.         luMessage pMessage;
    & z# l* W& r2 D7 F
  26.         wchar_t wchNum[32];
    ! N, E0 K0 [; u4 V+ ?8 R" b. q
  27.         char chNum[32];" i9 `9 r5 Z, @. P. g2 {: q
  28.         a.BType=luStaData_nil; a.VType=luStaData_nil; a.x=0;
    ) Y2 _9 R5 d& o, V' E
  29.         switch(theOperator)
    / _! J, C# Q) I7 b
  30.         {
    2 X8 r* ~! Q; h. |: _: m
  31.         case 2:        //重载运算符*
    # ~' D' d# s7 \; J, K1 ~7 {7 m
  32.                 pRealArray1=(luRealArray *)SearchKey((char *)&(xx->x),sizeof(luVOID),luDynData_realarray);/ W4 [2 r3 s' |+ _: V) R7 f
  33.                 pRealArray2=(luRealArray *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),luDynData_realarray);0 ?) |+ D& I9 E; e! f, D
  34.                 if(!pRealArray1 || !pRealArray2) break;        //对象句柄无效,不是实数数组  z7 i/ b+ Y( N# e' u
  35.                 if(pRealArray1->DimLen!=2 || pRealArray2->DimLen!=2) break;        //不是二维实数数组(矩阵)
    6 D1 j- Z# g4 ]; F* y
  36.                 if(pRealArray1->Dim[1]!=pRealArray2->Dim[0]) break;        //维数不匹配
    1 t8 ?; C  c/ s! f: _8 }
  37.                 pRealArray3=(luRealArray *)NewSysObj(luDynData_realarray,pRealArray1->Dim[0]*pRealArray2->Dim[1],2);        //创建矩阵对象$ q5 j* q7 K2 B/ v% T/ l3 L/ [
  38.                 if(!pRealArray3) break;
    7 r# s3 h* u  k. `, g  u
  39.                 pRealArray3->Dim[0]=pRealArray1->Dim[0]; pRealArray3->Dim[1]=pRealArray2->Dim[1];        //设置矩阵维数大小
    1 a$ \; |) K* f- c$ b
  40.                 pa=pRealArray1->Array; pb=pRealArray2->Array; pc=pRealArray3->Array;
    9 O4 C. W% A3 Z
  41.                 m=pRealArray1->Dim[0]; n=pRealArray1->Dim[1]; k=pRealArray2->Dim[1];
    8 W" a  B. Q& l9 J0 ]4 M
  42.                 for(i=0; i<m; i++)        //矩阵乘
    8 i9 h0 q& v; X+ V" o+ n, K& Q& n& A
  43.                 {& B, c1 V1 C. j, y2 I
  44.                         for(j=0; j<k; j++)
    / l6 _; f1 V# V" |! X- ~" W
  45.                         {: }6 ^6 v) ]& X) h
  46.                                 u=i*k+j; pc[u]=0.0;: B. O# f/ m' s5 h7 |6 [% m* F% u
  47.                                 for (v=0; v<n; v++)
    * `# R/ Y, l" s$ L
  48.                                 {" T# S$ |- L# A% k
  49.                                         pc[u]=pc[u]+pa[i*n+v]*pb[v*k+j];
    4 y1 y& E; K2 g6 c2 z: n
  50.                                 }
    : G4 N% l( |1 ?/ A
  51.                         }, @9 b; S1 @0 N; I8 R
  52.                 }$ y! g, Q, O7 l+ p0 b" r
  53.                 FunReObj(hFor);        //告诉Lu,返回一个动态对象. E1 Y4 l) Y1 S9 o0 s
  54.                 a.BType=luDynData_realarray; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pRealArray3;
    % |3 `4 g! Y9 l9 E3 v
  55.                 break;
    / P* f( B' _+ m5 `+ I8 q+ M
  56.         case 25:        //重载运算符.*
    4 M/ r% ~7 U' J4 E- s+ }* U
  57.                 pRealArray1=(luRealArray *)SearchKey((char *)&(xx->x),sizeof(luVOID),luDynData_realarray);  P: ?- R6 ]' ?. ]5 I4 e
  58.                 pRealArray2=(luRealArray *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),luDynData_realarray);- s4 O" T/ t* c" R+ O- f" R) J
  59.                 if(!pRealArray1 || !pRealArray2) break;        //对象句柄无效,不是实数数组
    / ]1 s1 B& W) ?, r8 F5 p  X0 w
  60.                 if(pRealArray1->DimLen!=2 || pRealArray2->DimLen!=2) break;        //不是二维实数数组(矩阵)
    ; D0 {6 [6 e) u" g7 x3 m
  61.                 if(pRealArray1->Dim[0]!=pRealArray2->Dim[0] || pRealArray1->Dim[1]!=pRealArray2->Dim[1]) break;        //维数不相同
    * k( B1 F9 p8 ?% W( i, [$ j
  62.                 pRealArray3=(luRealArray *)NewSysObj(luDynData_realarray,pRealArray1->ArrayLen,2);        //创建矩阵对象
    " J+ K3 R( k' V7 a, U' E' ~0 z: ^
  63.                 if(!pRealArray3) break;7 U, G5 Z* H+ C0 A) ~  q9 t, D
  64.                 pRealArray3->Dim[0]=pRealArray1->Dim[0]; pRealArray3->Dim[1]=pRealArray1->Dim[1];        //设置矩阵维数大小
    : p, ]) ^- Y; O
  65.                 for(i=0;i<pRealArray1->ArrayLen;i++) pRealArray3->Array[i]=pRealArray1->Array[i]*pRealArray2->Array[i];//矩阵点乘: `" ~' t8 H4 j2 s  q- H
  66.                 FunReObj(hFor);        //告诉Lu,返回一个动态对象( z0 o- E4 u" j7 R1 u
  67.                 a.BType=luDynData_realarray; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pRealArray3;/ W" x  M& W3 q! z2 S
  68.                 break;
    3 s" A$ D; f. b1 ?) ~7 W( M
  69.         case 46:        //重载函数new: p  R" R3 s, [% j# ?7 j+ }
  70.                 a=ExeOperator(mm,xx,hFor,theOperator,luDynData_realarray);        //直接调用基本类型luDynData_realarray的new函数
    2 T3 u, f* e% V3 x# O
  71.                 if(a.VType==luDynData_realarray) a.VType=Matrix;        //设置扩展类型为自定义的Matrix类型
    2 _3 a2 x5 E  U" Y* H+ A0 O
  72.                 break;" a0 w) q8 {) J: Z4 ^2 t
  73.         case 49:        //重载函数o6 x/ p. F; s2 I7 S3 M2 s
  74.                 pMessage=(luMessage)SearchKey("\0\0\0\0",sizeof(luVOID),luPubKey_User);0 R0 q( v: n7 V9 h- _& i
  75.                 if(!pMessage) break;$ s3 j& Q( }3 ?. X3 J, c  g- F. U
  76.                 pRealArray1=(luRealArray *)SearchKey((char *)&(xx->x),sizeof(luVOID),luDynData_realarray);
    * \9 z# W" M. t- a, k) m
  77.                 if(!pRealArray1) break;        //对象句柄无效,不是实数数组
    ! B1 i) F7 g% h
  78.                 if(pRealArray1->DimLen!=2) break;        //不是二维实数数组(矩阵)
    4 c' f3 h6 K: i8 \( a
  79.                 pa=pRealArray1->Array;% H0 H' o6 D/ [, U' R1 {7 T1 P
  80.                 m=pRealArray1->Dim[0]; n=pRealArray1->Dim[1]; k=0;$ I7 x5 @/ d" X. g  ?* j
  81.                 for(i=0; i<m; i++)        //输出矩阵
    + h3 B5 P5 b& x7 U7 w* Z, M
  82.                 {; ?8 ~4 c: }: E2 f2 n5 d5 ~$ t
  83.                         pMessage(L"\r\n"); k+=2;! r+ Z5 r; x* `
  84.                         for(j=0; j<n; j++)& D; g% q7 y4 A: _( E. h
  85.                         {3 \" Z# z* ~# k3 }
  86.                                 _gcvt_s(chNum,pa[i*n+j],16);9 h' X* l! b5 |$ T
  87.                                 for(u=0;chNum[u];u++) {wchNum[u]=chNum[u]; k++;}  \1 M$ A, e6 c' K, m* M1 N
  88.                                 wchNum[u]='\0';: R; L& B, i7 M# `2 Z5 M: W. H( P
  89.                                 pMessage(wchNum); pMessage(L"  "); k+=2;1 b" p* T/ M+ }
  90.                         }
    1 t0 O" @; P% K7 |% v6 v( \
  91.                 }
    8 L4 H5 o6 O4 l. j) a
  92.                 pMessage(L"\r\n"); k+=2;/ u$ o4 D5 L% o
  93.                 a.BType=luStaData_int64; a.VType=luStaData_int64; a.x=k;        //按函数o的要求,返回输出的字符总数
    6 A4 X& W/ r2 ]3 l) F2 Z1 z
  94.                 break;+ p$ ~( q4 m- v" `6 f
  95.         default:
    ; G$ Q1 s; G6 u: V
  96.                 break;4 g& H+ J$ i* d! u
  97.         }: B. Y1 Z5 P- ~- e
  98.         return a;2 [& n5 w1 a( `1 `- \7 Q, ~! q( V
  99. }
    0 A+ ]9 |* s9 q6 ^8 j; B4 |2 c
  100. void main(void)
    2 A! i. ~1 Z9 r
  101. {
    , B* I; L; S& w
  102.         void *hFor;                //表达式句柄- q& J5 r" A" Z! E: _
  103.         luINT nPara;                //存放表达式的自变量个数/ u' i4 i, A! E/ X. F
  104.         LuData *pPara;                //存放输入自变量的数组指针3 [3 i# u% G- x! _- j! K' L% ]
  105.         luINT ErrBegin,ErrEnd;        //表达式编译出错的初始位置和结束位置( x$ O2 Z; A* J: D8 v
  106.         int ErrCode;                //错误代码
    , \/ w5 q2 ^9 T  N
  107.         void *v;
    # r9 v+ A/ y3 [& p
  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.]}";//字符串表达式,矩阵乘
    : c" ~/ W4 o% ~& n& y! R
  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.]}";//字符串表达式,矩阵点乘! r/ k1 t/ f5 U, Z
  110.         LuData Val;+ I, ]7 I4 D9 w  b6 `$ U1 a
  111.         if(!InitLu()) return;        //初始化Lu  o& ]9 j6 U# z  ~8 S: e! Y
  112.         while(LockKey(Matrix,DelMatrix,OpMatrix)){Matrix++;}        //锁定一个键,用于存储矩阵扩展类型
    8 f6 ^& Y! Q, @- H& z( C
  113. 3 Q9 y- i- Q1 s' Q- i6 Z
  114.         Val.BType=luStaData_int64; Val.VType=luStaData_int64; Val.x=Matrix;        //定义整数常量, q6 Z1 c- t) p: Z/ L; t5 p
  115.         SetConst(L"matrix",&Val);        //设置整数常量6 Z: u, I  ?/ ^
  116.         InsertKey("\0\0\0\0",4,luPubKey_User,LuMessage,NULL,NULL,1,v); //使Lu运行时可输出函数信息) @2 M: M4 P8 E$ D7 D+ Y
  117.         wcout.imbue(locale("chs"));        //设置输出的locale为中文
    ' K" |- W9 q5 w
  118.   
    - ]2 g6 Y0 m/ C, x& g, V( K
  119.         ErrCode=LuCom(ForStr,0,0,0,hFor,nPara,pPara,ErrBegin,ErrEnd); //编译表达式
    # _4 `, N4 Q3 q5 U0 f9 O
  120.         if(ErrCode)5 A8 L& ^; d/ B: K$ |% M; O+ w
  121.         {7 J5 n( J  g& ]6 V( v3 v7 r
  122.                 wcout<<L"表达式有错误!错误代码:"<<ErrCode<<endl;
    $ r) i* S( F& ]) I) b) ?
  123.         }2 Q4 M2 ?' |$ ^8 `1 M) ]: s
  124.         else7 Z' p, Q6 y; L( {$ P5 n
  125.         {
    & ?4 J9 ~& S) X; E' I0 o
  126.                 LuCal(hFor,pPara);        //计算表达式的值1 _) {1 N/ [9 _0 R0 a$ s
  127.         }
    6 ]9 t  o/ o$ Z& S
  128.         LockKey(Matrix,NULL,OpMatrix);//解锁键Matrix,本例中,该函数可以不用
    0 Z* c- v' c' j; N
  129.         FreeLu();                        //释放Lu9 m" q( c& u8 l! I  b! I! t1 t9 G2 X
  130. }
复制代码
习题:7 o  u2 F; i3 D2 k1 W3 ~" q

& D8 W/ T! o# Z* [% y' n: |    (1)自定义矩阵的加、减、左除、右除、点左除等运算,自编测试字符串代码,重新编译运行程序,观察计算结果。 : P% R' M$ ~7 Y1 N' w

0 g+ B/ N2 S" |    (2)小矩阵乘效率测试。编译运行以下Lu字符串代码:
  1. main(:a,b,c,d,t,i)=
    7 I2 R) c' P' _
  2.     a=new[matrix,2,2,data:1.,2.,2.,1.],
    $ }- W# h4 f) e* |8 b
  3.     b=new[matrix,2,2,data:2.,1.,1.,2.],
    # S2 w/ b: E( ~! j) l
  4.     c=new[matrix,2,2,data:2/3.,-1/3.,-1/3.,2/3.],
      z1 j+ ]9 D) V% p
  5.     t=clock(),- s' a6 J8 \! B
  6.     d=a*b, i=0, while{i<1000000, d=d*c*b, i++},
    ; v& y0 G6 b- ~! m5 E0 Y
  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.' }3 L: w5 c* ~/ E, v7 U/ b  @
  2. 5. 4.$ f% Q2 ?9 K! E9 y$ c
  3. time=0.875 seconds./ O2 t6 y. B$ S0 p; r
  4. 请按任意键继续. . .
复制代码
Matlab 2009a 代码:
  1. a=[1.,2.;2.,1.];
    7 _+ b) C. |: Y3 [
  2. b=[2.,1.;1.,2.];, O+ u  _2 V3 M- r+ i$ s
  3. c=[2/3.,-1/3.;-1/3.,2/3.];9 k' t" I7 }. |( x, P' S
  4. tic,
    7 P+ L% \' P4 B- w
  5. d=a*b;
    + b+ q) h( \4 i: O
  6. for i=1:1000000  v' }. F2 ~% `  `% g9 U' A% N* V* `$ x
  7.     d=d*c*b;/ H# ~# {6 s' B  o  A
  8. end3 f( g8 a# B1 [! C, B
  9. d,
    + n. x& W6 ~, m
  10. toc
复制代码
结果:
  1. d =% X7 @' i" }9 X6 ~' E. @# B& U4 @
  2.      4     5- |  C& D2 m- [) f# e  C6 E
  3.      5     4
    6 R5 I; E3 r" ?1 z5 o
  4. Elapsed time is 2.903034 seconds.
复制代码
本例矩阵乘效率测试,Lu的速度超过了Matlab,主要在于Lu有更高的动态对象管理效率。' r0 P6 f* A7 d, e0 x9 e





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