数学建模社区-数学中国

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

作者: forcal    时间: 2011-10-23 09:37
标题: Lu基于系统内置对象创建扩展数据类型,小矩阵乘效率测试
    本例中,我们将基于系统内置实数数组创建矩阵(matrix)类型,即:基本类型为luDynData_realarray(标识实数数组),扩展类型为matrix(标识矩阵)。为了简单,我们仅处理二维实数数组即矩阵类型。
4 q8 Z3 T) a! Q  A, E# I& r2 N! `
. t+ ^" n" q- q; v* H$ T    基本要点:: U3 g6 m6 ~1 @  W( x+ G
3 n6 z0 n: u; U4 H/ U' G4 {
    (1)为扩展类型matrix编写运算符重载函数OpMatrix。; l- G$ O8 T9 w3 q
/ c* `" w7 i6 G! ~6 F
    (2)用函数LockKey将重载函数OpMatrix注册到Lu,锁定的键的类型即为matrix,要注册为常量,以便于使用。7 P! D$ s" d0 u  q/ I1 ~0 e4 O

- G; v$ ?0 [0 x: @% B4 A    (3)为扩展类型matrix编写其他操作函数(本例未提供)。0 v7 ]* X. V7 A4 M; c
$ F. e7 n4 n2 S' l  C
    (4)用函数LockKey解锁键matrix(本例中,程序退出时会自动解锁,故可以不用)。
  1. #include <windows.h>8 L' P( h9 l; W" k  t
  2. #include <iostream>
    3 N* @% a3 l- b* d/ Q. K1 Y
  3. #include <math.h>/ C' }3 R+ T4 J& p& X
  4. #include "lu32.h"1 r9 u4 K) A$ N2 x
  5. # H, D3 ^& W* U- K/ U% X
  6. #pragma comment( lib, "lu32.lib" )
    8 h7 ^) C7 X4 |4 j+ [! J0 a
  7. 0 u6 q+ Z+ m) G5 U2 d2 P1 V7 \# r
  8. using namespace std;
    2 q) E2 V4 z' v

  9. 5 u8 S$ S; P) k/ t( r5 Z
  10. luKEY Matrix=-1000;        //标识矩阵类型,最终的Matrix由LockKey决定- D' g! Y7 j( h4 ^8 N' D0 n9 e

  11. 3 O6 {$ ~% n# B
  12. void _stdcall LuMessage(wchar_t *pch)//输出动态库信息,该函数注册到Lu,由Lu二级函数调用
    - n3 K2 f$ ^$ _/ o) x# e
  13. {5 Q3 D5 d  _) c. b/ r  c1 o4 \  W
  14.         wcout<<pch;9 y, s+ ^  J, y3 W6 f6 O2 |5 f8 p1 h
  15. }
    7 M4 _$ y# m, I- Z% p  o
  16. void _stdcall DelMatrix(void *me)        //用于LockKey函数,因为是基于系统内置实数数组创建矩阵,故该函数什么也不做
    ; `4 e2 p0 h2 U8 q. \9 R
  17. {
    . E0 p0 X; k4 y6 ~' R0 {* \
  18. }
    5 u5 g- g% ^+ I  l& E
  19. LuData _stdcall OpMatrix(luINT mm,LuData *xx,void *hFor,int theOperator)        //运算符重载函数,用于LockKey函数; V" K' {# J- x$ c% k9 V& D; @# C6 l
  20. {# E* R* i. o% Y; k( ?9 p  I% `
  21.         LuData a;
    ; \3 S. R8 U1 s8 Q6 q
  22.         luRealArray *pRealArray1,*pRealArray2,*pRealArray3;! V2 t+ f8 t6 x, X
  23.         luVOID i,j,k,m,n,u,v;
    5 f4 Z" I8 }. R
  24.         double *pa,*pb,*pc;0 `2 t' Z7 n3 E/ t
  25.         luMessage pMessage;! {! L5 a" I7 m+ K) G- ~: ^
  26.         wchar_t wchNum[32];- f4 j" y+ u" l) E& A2 i" |
  27.         char chNum[32];
    : B: m- I& d; U' X: S
  28.         a.BType=luStaData_nil; a.VType=luStaData_nil; a.x=0;
    / J0 t* [$ L$ @5 l- [- @" e- ^: D4 l7 _
  29.         switch(theOperator)
    ) {. k7 N1 v- P+ y/ z
  30.         {
    + T+ x$ m' _) v3 T1 p$ m
  31.         case 2:        //重载运算符*$ B, e5 M1 F- ~5 F6 T
  32.                 pRealArray1=(luRealArray *)SearchKey((char *)&(xx->x),sizeof(luVOID),luDynData_realarray);# Z( F1 ^0 ~; r
  33.                 pRealArray2=(luRealArray *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),luDynData_realarray);/ w+ E% g1 Y! F8 ]; o/ y! s
  34.                 if(!pRealArray1 || !pRealArray2) break;        //对象句柄无效,不是实数数组
    : q$ g# z% d, Z; ]% M- l& D9 t9 Y/ c
  35.                 if(pRealArray1->DimLen!=2 || pRealArray2->DimLen!=2) break;        //不是二维实数数组(矩阵)% K! F9 I6 s1 I, i' T: Y, S- t4 D
  36.                 if(pRealArray1->Dim[1]!=pRealArray2->Dim[0]) break;        //维数不匹配9 G5 O! U  b4 G& J* s5 w6 G
  37.                 pRealArray3=(luRealArray *)NewSysObj(luDynData_realarray,pRealArray1->Dim[0]*pRealArray2->Dim[1],2);        //创建矩阵对象
    9 f8 e& `$ H$ M# Q% }
  38.                 if(!pRealArray3) break;
    & O8 P% N  i  v: N6 k  R
  39.                 pRealArray3->Dim[0]=pRealArray1->Dim[0]; pRealArray3->Dim[1]=pRealArray2->Dim[1];        //设置矩阵维数大小
    " E0 S# V% D4 h: e: b- X0 H; Z
  40.                 pa=pRealArray1->Array; pb=pRealArray2->Array; pc=pRealArray3->Array;
    : N# H4 k* s% u( J! m/ g/ i
  41.                 m=pRealArray1->Dim[0]; n=pRealArray1->Dim[1]; k=pRealArray2->Dim[1];# P* }& A! g, @5 @, K6 h! {
  42.                 for(i=0; i<m; i++)        //矩阵乘: M6 a7 L: p- J2 H% E
  43.                 {
    ) k3 K* q; r0 m, {# v
  44.                         for(j=0; j<k; j++)
    ( u" C4 E0 l% }6 w' [2 e
  45.                         {& H9 {% a1 R" R' k3 ]: s6 [4 b! r, S
  46.                                 u=i*k+j; pc[u]=0.0;
    # h' `$ R. a8 F) [# N
  47.                                 for (v=0; v<n; v++)6 L4 a* |7 `8 W7 ]! d
  48.                                 {4 ?. H6 @6 W3 J$ Y
  49.                                         pc[u]=pc[u]+pa[i*n+v]*pb[v*k+j];2 V! C1 j; I+ n6 l! `* b  A: D
  50.                                 }
    & J8 e) b' Y0 c: w9 r
  51.                         }8 ]. g. A: M* _) L
  52.                 }
    * ?1 [1 y5 \8 p6 G- m5 A/ z& |- n5 O
  53.                 FunReObj(hFor);        //告诉Lu,返回一个动态对象
    2 m' O4 V1 P+ s3 z
  54.                 a.BType=luDynData_realarray; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pRealArray3;& f7 L5 h0 o# @# e$ \
  55.                 break;
    . R' d3 Z4 m- @& X' d6 o
  56.         case 25:        //重载运算符.*4 A6 q% U; S1 m( ~5 f
  57.                 pRealArray1=(luRealArray *)SearchKey((char *)&(xx->x),sizeof(luVOID),luDynData_realarray);1 y' ^8 u  k: R/ D; ?: M
  58.                 pRealArray2=(luRealArray *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),luDynData_realarray);4 w, |2 n/ M* S& D
  59.                 if(!pRealArray1 || !pRealArray2) break;        //对象句柄无效,不是实数数组
    7 a7 J4 w# O; L0 D& H# e2 e
  60.                 if(pRealArray1->DimLen!=2 || pRealArray2->DimLen!=2) break;        //不是二维实数数组(矩阵)
    8 V) [6 m- @) E! A: E
  61.                 if(pRealArray1->Dim[0]!=pRealArray2->Dim[0] || pRealArray1->Dim[1]!=pRealArray2->Dim[1]) break;        //维数不相同
    ( t% z  B* \% H0 M& o7 L
  62.                 pRealArray3=(luRealArray *)NewSysObj(luDynData_realarray,pRealArray1->ArrayLen,2);        //创建矩阵对象
    / A6 n, C7 k$ ~( t- |
  63.                 if(!pRealArray3) break;, I7 D# I1 o* O2 }( ~5 r
  64.                 pRealArray3->Dim[0]=pRealArray1->Dim[0]; pRealArray3->Dim[1]=pRealArray1->Dim[1];        //设置矩阵维数大小4 m3 o% ^5 S8 F6 e6 `  X5 p# v0 t
  65.                 for(i=0;i<pRealArray1->ArrayLen;i++) pRealArray3->Array[i]=pRealArray1->Array[i]*pRealArray2->Array[i];//矩阵点乘: J0 p2 [6 A' b, Z4 v6 W( e
  66.                 FunReObj(hFor);        //告诉Lu,返回一个动态对象2 g& y; U" y& X) h9 h$ ^, Z
  67.                 a.BType=luDynData_realarray; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pRealArray3;
    ; S8 J6 E" ^' x$ h( \/ Z  a5 P  U# h* a
  68.                 break;/ u) N& W8 e" G4 o5 q  t4 R
  69.         case 46:        //重载函数new' y6 R) c1 K$ t5 A4 E- g  _  u
  70.                 a=ExeOperator(mm,xx,hFor,theOperator,luDynData_realarray);        //直接调用基本类型luDynData_realarray的new函数1 B8 ~  U" i# X7 ]0 a, x
  71.                 if(a.VType==luDynData_realarray) a.VType=Matrix;        //设置扩展类型为自定义的Matrix类型
    ' Z3 }) P- I) p1 l. g+ E
  72.                 break;
    ! |1 H& v6 ^' h! |' M! H0 ^
  73.         case 49:        //重载函数o% S$ j# Q' s( t5 i3 r
  74.                 pMessage=(luMessage)SearchKey("\0\0\0\0",sizeof(luVOID),luPubKey_User);% S1 {* H3 Z5 H3 W
  75.                 if(!pMessage) break;
    9 F* y! j, s, J; C; Q
  76.                 pRealArray1=(luRealArray *)SearchKey((char *)&(xx->x),sizeof(luVOID),luDynData_realarray);/ O& ~5 S; E+ r( g
  77.                 if(!pRealArray1) break;        //对象句柄无效,不是实数数组
    ; ^$ v8 _( R8 T$ i" i
  78.                 if(pRealArray1->DimLen!=2) break;        //不是二维实数数组(矩阵)
      e$ h% }4 S" m& f
  79.                 pa=pRealArray1->Array;
    ! V% Y! \& Z) w; b
  80.                 m=pRealArray1->Dim[0]; n=pRealArray1->Dim[1]; k=0;# y7 x8 c5 u0 s* n* A7 h
  81.                 for(i=0; i<m; i++)        //输出矩阵4 Q. H/ h: i0 O. s1 _, P
  82.                 {" X) t# G# P7 z4 `# U4 R/ d
  83.                         pMessage(L"\r\n"); k+=2;1 |8 d' A! g( L
  84.                         for(j=0; j<n; j++)# N' \! W' H6 j6 P. v/ h! }
  85.                         {2 S% B# v# O, a, w# V* n
  86.                                 _gcvt_s(chNum,pa[i*n+j],16);7 a- R0 O7 I& P. \
  87.                                 for(u=0;chNum[u];u++) {wchNum[u]=chNum[u]; k++;}
    + J9 Z1 a7 i9 y& K
  88.                                 wchNum[u]='\0';
    ( O7 [8 D) Y) y' N# h
  89.                                 pMessage(wchNum); pMessage(L"  "); k+=2;: j& |( H% H% {* {& l1 F' k
  90.                         }
    # E  [- T, P: Z$ ~; t$ B' ]/ N, N
  91.                 }& l, C; ^1 Q- p8 `+ n
  92.                 pMessage(L"\r\n"); k+=2;) ~% p5 f/ j' ^/ H3 E
  93.                 a.BType=luStaData_int64; a.VType=luStaData_int64; a.x=k;        //按函数o的要求,返回输出的字符总数/ I& u: S) I. K9 V2 r
  94.                 break;1 g, g2 y# r+ E) e+ s) c9 @, Q
  95.         default:
    $ F- ?6 z" i4 L9 _2 c& i) Y# X
  96.                 break;
    4 i. M' T1 b/ M# W
  97.         }
    4 _$ W7 ]9 T0 Z! o$ e+ c
  98.         return a;' {1 D& E2 d3 y( q4 Y& u# r
  99. }
    ; L4 X0 ?$ A  R- ~, ^0 ~9 i
  100. void main(void)% H2 Q0 W0 E) A) ~4 Q. K; r
  101. {# p% N# \% t. S. W' T4 H: e
  102.         void *hFor;                //表达式句柄
    + }/ C; Z9 M, @- R9 s
  103.         luINT nPara;                //存放表达式的自变量个数# B1 m  U' s! f+ `3 K2 I. d4 Q
  104.         LuData *pPara;                //存放输入自变量的数组指针9 `9 w) P' Y$ Q
  105.         luINT ErrBegin,ErrEnd;        //表达式编译出错的初始位置和结束位置, D3 R, \$ n4 O0 k
  106.         int ErrCode;                //错误代码1 m) q& y! L: B! v
  107.         void *v;
    ' D0 M. k5 T; t1 x* v
  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.]}";//字符串表达式,矩阵乘
    - s8 u4 S! F+ A' i+ N& w3 }
  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.]}";//字符串表达式,矩阵点乘8 B( F" I0 W6 t3 C
  110.         LuData Val;& O4 E& H" s8 t: x
  111.         if(!InitLu()) return;        //初始化Lu
    - O6 N8 B7 m- e
  112.         while(LockKey(Matrix,DelMatrix,OpMatrix)){Matrix++;}        //锁定一个键,用于存储矩阵扩展类型. D* L- k1 M' k) M3 M/ J" B  s8 k

  113. $ k0 L/ C! r  ~- j/ _/ _! K
  114.         Val.BType=luStaData_int64; Val.VType=luStaData_int64; Val.x=Matrix;        //定义整数常量
    # j3 U' W1 \& {7 h! z+ j' t9 r
  115.         SetConst(L"matrix",&Val);        //设置整数常量
    . r% I5 A) Z: V1 G8 _0 D
  116.         InsertKey("\0\0\0\0",4,luPubKey_User,LuMessage,NULL,NULL,1,v); //使Lu运行时可输出函数信息
    $ p! S  C$ T. f- d3 t$ X9 j3 F. o9 G
  117.         wcout.imbue(locale("chs"));        //设置输出的locale为中文
    ) \" k. B0 k! l" p2 _6 Q- \
  118.   + t0 Y; M1 N1 e9 S' |  S
  119.         ErrCode=LuCom(ForStr,0,0,0,hFor,nPara,pPara,ErrBegin,ErrEnd); //编译表达式5 }2 S+ S( c/ Q& w+ ?  h5 L7 F
  120.         if(ErrCode)
    . P" ?  Z6 k" k  P/ ~+ `
  121.         {3 ]3 ^  k4 K) Q6 f5 F
  122.                 wcout<<L"表达式有错误!错误代码:"<<ErrCode<<endl;  \: k+ I- _  p/ N4 U! q% \0 V, U
  123.         }/ F# z8 F7 n5 T9 u$ {/ u6 a
  124.         else
    : e3 [2 a% J8 x# |2 g  F/ b3 p
  125.         {
    ) Y3 M/ E) J1 P9 k- X  t! b- m
  126.                 LuCal(hFor,pPara);        //计算表达式的值4 a" T! U2 T! b
  127.         }
    5 b5 L# q6 W9 T% i' N0 x* h: z9 B
  128.         LockKey(Matrix,NULL,OpMatrix);//解锁键Matrix,本例中,该函数可以不用
    - }: _  T- x4 {7 L
  129.         FreeLu();                        //释放Lu
    # n) t' G7 _$ K3 Y  {
  130. }
复制代码
习题:
- H  E7 }( o- x8 |# W2 e% [8 o: W: u0 k( |, {9 j2 T7 L
    (1)自定义矩阵的加、减、左除、右除、点左除等运算,自编测试字符串代码,重新编译运行程序,观察计算结果。 * [) S# l: Q4 Q4 s6 t2 W

2 s. F! o6 @4 C    (2)小矩阵乘效率测试。编译运行以下Lu字符串代码:
  1. main(:a,b,c,d,t,i)=
      y+ c- N7 d" V
  2.     a=new[matrix,2,2,data:1.,2.,2.,1.],+ s& w0 j% v- z- ^% ~  M( l6 A
  3.     b=new[matrix,2,2,data:2.,1.,1.,2.],+ T( k2 x# [* L) ?5 M
  4.     c=new[matrix,2,2,data:2/3.,-1/3.,-1/3.,2/3.],; W6 c5 J  g8 e% F! `4 A& @
  5.     t=clock(),; c7 s" C+ ^/ s
  6.     d=a*b, i=0, while{i<1000000, d=d*c*b, i++},6 x; H2 U; j) e( q. c$ ]* B! @0 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.
    8 g6 i1 P9 f3 O' ]6 ~6 Z
  2. 5. 4.$ K9 j0 u. H) Y: F2 f  W
  3. time=0.875 seconds.
    5 K) Z% O0 ?; v# |! H- c
  4. 请按任意键继续. . .
复制代码
Matlab 2009a 代码:
  1. a=[1.,2.;2.,1.];
    + l; U& P4 O& d1 T7 y! S3 M
  2. b=[2.,1.;1.,2.];
    ) r- b! m& _, R0 y6 x2 G
  3. c=[2/3.,-1/3.;-1/3.,2/3.];
    5 |8 C: M9 }1 S( ?0 N) W
  4. tic,
    - y6 F1 ]2 Y3 V0 }1 V: |
  5. d=a*b;2 {: ^2 J3 `* a3 |6 S
  6. for i=1:10000009 i; Z% D9 X, Q1 U1 j
  7.     d=d*c*b;- Q; _; f0 q- M" y% J/ o
  8. end
    1 _5 i5 ?1 Z0 X5 W2 l5 Z( T2 z/ n
  9. d,
    3 V4 w" K$ U  ?& @# y1 {% G
  10. toc
复制代码
结果:
  1. d =  W( Y( N. A0 Q8 a* H' k- ~
  2.      4     5; {. Y1 _- Y' L
  3.      5     4
    ) r# K; u5 K+ ^) v2 t8 e1 D
  4. Elapsed time is 2.903034 seconds.
复制代码
本例矩阵乘效率测试,Lu的速度超过了Matlab,主要在于Lu有更高的动态对象管理效率。
: I  g! e% w3 B




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