数学建模社区-数学中国

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

作者: forcal    时间: 2011-10-23 09:37
标题: Lu基于系统内置对象创建扩展数据类型,小矩阵乘效率测试
    本例中,我们将基于系统内置实数数组创建矩阵(matrix)类型,即:基本类型为luDynData_realarray(标识实数数组),扩展类型为matrix(标识矩阵)。为了简单,我们仅处理二维实数数组即矩阵类型。
( l! _5 m; r$ o7 f! Q0 B& W  ?$ e6 O4 G& X7 G" J
    基本要点:
3 G# b9 n9 k1 [2 ^4 _' |7 K; ~" C: m% t* l) A
    (1)为扩展类型matrix编写运算符重载函数OpMatrix。9 _1 |9 ]' @# B! @6 j1 G8 W

3 G4 E  A* ]8 c  }5 Y4 S    (2)用函数LockKey将重载函数OpMatrix注册到Lu,锁定的键的类型即为matrix,要注册为常量,以便于使用。2 X% k) w5 N/ u: d% H# I1 K
, x6 u  i. b' l4 j! \
    (3)为扩展类型matrix编写其他操作函数(本例未提供)。
9 ^9 o' h) a+ Q, y8 N8 X) ~$ u2 `9 a" v
    (4)用函数LockKey解锁键matrix(本例中,程序退出时会自动解锁,故可以不用)。
  1. #include <windows.h>6 H) B$ n% G5 j+ y
  2. #include <iostream>/ X- r1 q6 ?( u8 t4 e
  3. #include <math.h>1 N6 }& Q/ z6 S! O3 ]" U, t7 W- P
  4. #include "lu32.h"5 v* l7 T4 @% V0 T

  5. ! M! T( v3 L4 z0 J6 a/ I4 ^
  6. #pragma comment( lib, "lu32.lib" )
    # B- y6 Z4 R6 V1 t
  7. % X- T/ r$ M& W
  8. using namespace std;
    , ^1 E) V1 a+ B2 R
  9. ! n. R8 B, R4 ]8 n, j2 b1 u7 d
  10. luKEY Matrix=-1000;        //标识矩阵类型,最终的Matrix由LockKey决定1 K& `+ y2 z1 h% O1 B" f
  11. / q0 t) P6 Z" F; K4 I+ X
  12. void _stdcall LuMessage(wchar_t *pch)//输出动态库信息,该函数注册到Lu,由Lu二级函数调用 / J6 G; y. G1 W$ z; @% ]% S4 g+ M  H, C
  13. {
    $ A2 \8 p3 n- O1 J6 F) Z" q; e
  14.         wcout<<pch;
    5 p$ U+ H* M4 V
  15. }. I" ~" z/ V6 z+ w, ?( {7 J  o
  16. void _stdcall DelMatrix(void *me)        //用于LockKey函数,因为是基于系统内置实数数组创建矩阵,故该函数什么也不做3 e" h: K1 O7 @. u* |% l) w" u! A
  17. {
    / N: Z/ Y! a! K; t9 R5 k3 B( y/ }# T% q
  18. }: N; e9 c4 Y0 }8 _+ d! F4 E
  19. LuData _stdcall OpMatrix(luINT mm,LuData *xx,void *hFor,int theOperator)        //运算符重载函数,用于LockKey函数
      @. G6 Q4 e7 h) c' E/ N+ T
  20. {4 K6 O3 \& c' p
  21.         LuData a;
    . {9 W; s" L  n+ |9 p. i
  22.         luRealArray *pRealArray1,*pRealArray2,*pRealArray3;5 f6 n* ^5 ?8 |2 M# {
  23.         luVOID i,j,k,m,n,u,v;
    . I! ]3 M6 g. D& _' X: D: u
  24.         double *pa,*pb,*pc;
    3 r. H2 B9 M- G" U
  25.         luMessage pMessage;' W5 W, M- }, ^" j( W8 J# w# X
  26.         wchar_t wchNum[32];
    2 e+ X  x/ e) n# v1 ^2 o3 C& c) ~
  27.         char chNum[32];
    4 x2 d" }2 L/ ^* I6 E# `5 c+ t# d
  28.         a.BType=luStaData_nil; a.VType=luStaData_nil; a.x=0;
    " A9 L  R5 ^/ d
  29.         switch(theOperator)
    ) @( L  Q# }5 i# \6 j
  30.         {0 z1 G, B" H3 @* e/ c
  31.         case 2:        //重载运算符*
    + y0 Y  U9 \# v$ s- O
  32.                 pRealArray1=(luRealArray *)SearchKey((char *)&(xx->x),sizeof(luVOID),luDynData_realarray);
    + S8 Y4 v3 Z7 o) F; l. r  M
  33.                 pRealArray2=(luRealArray *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),luDynData_realarray);
    % e* {0 t, M7 b3 g- ^9 E# G
  34.                 if(!pRealArray1 || !pRealArray2) break;        //对象句柄无效,不是实数数组
    6 r4 B: ]4 C# S7 m2 \* W
  35.                 if(pRealArray1->DimLen!=2 || pRealArray2->DimLen!=2) break;        //不是二维实数数组(矩阵). U8 V# P0 J4 H8 l* B$ M# Z9 g
  36.                 if(pRealArray1->Dim[1]!=pRealArray2->Dim[0]) break;        //维数不匹配5 [: }2 k% E# y. R
  37.                 pRealArray3=(luRealArray *)NewSysObj(luDynData_realarray,pRealArray1->Dim[0]*pRealArray2->Dim[1],2);        //创建矩阵对象% G/ T0 i" T( a* X6 C
  38.                 if(!pRealArray3) break;
    $ ~( j% _% b0 O0 V# z
  39.                 pRealArray3->Dim[0]=pRealArray1->Dim[0]; pRealArray3->Dim[1]=pRealArray2->Dim[1];        //设置矩阵维数大小
    , O! k- h/ V# f7 |1 h
  40.                 pa=pRealArray1->Array; pb=pRealArray2->Array; pc=pRealArray3->Array;
    9 x! r! ^6 g+ ]" h" t
  41.                 m=pRealArray1->Dim[0]; n=pRealArray1->Dim[1]; k=pRealArray2->Dim[1];
    5 a* G; S% z5 A  t& k
  42.                 for(i=0; i<m; i++)        //矩阵乘
    1 b+ J8 k( _8 M7 {7 \, u6 a
  43.                 {
    $ d) p+ Z, d3 S" e+ [6 `! Y- S
  44.                         for(j=0; j<k; j++)
    1 H8 f+ ]- m7 v7 @* |) d% a; a
  45.                         {
    + E  {0 w( U& f: A6 N- @
  46.                                 u=i*k+j; pc[u]=0.0;( H6 U0 R0 m" D/ r+ L
  47.                                 for (v=0; v<n; v++): T4 [3 Z8 t6 L2 P
  48.                                 {/ q" a5 q) f' A: f0 h
  49.                                         pc[u]=pc[u]+pa[i*n+v]*pb[v*k+j];
    ( u) B6 H1 j3 Y" k5 j, a
  50.                                 }
    & @+ _2 y3 j5 t1 [- P+ c
  51.                         }  W% ?% \1 L8 i
  52.                 }
    2 A! e# k) Q! U. F/ @1 O
  53.                 FunReObj(hFor);        //告诉Lu,返回一个动态对象
    ( c0 d; g; m# q: @, D
  54.                 a.BType=luDynData_realarray; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pRealArray3;
    * ~: U3 m; o8 B. d3 n
  55.                 break;
    " \$ e0 ~0 H1 C2 }
  56.         case 25:        //重载运算符.*
    4 }- y0 n/ G; u! z; E
  57.                 pRealArray1=(luRealArray *)SearchKey((char *)&(xx->x),sizeof(luVOID),luDynData_realarray);
    9 ~, @2 y/ Z9 v) h  ]
  58.                 pRealArray2=(luRealArray *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),luDynData_realarray);, `( L1 d( q/ n4 a# L) ?# G1 a6 Z
  59.                 if(!pRealArray1 || !pRealArray2) break;        //对象句柄无效,不是实数数组: A. f, v0 t" c, T) J- `  f
  60.                 if(pRealArray1->DimLen!=2 || pRealArray2->DimLen!=2) break;        //不是二维实数数组(矩阵); Q" o: @4 L: M8 i5 j( V+ r
  61.                 if(pRealArray1->Dim[0]!=pRealArray2->Dim[0] || pRealArray1->Dim[1]!=pRealArray2->Dim[1]) break;        //维数不相同0 u1 h+ \8 f# T# q. Y
  62.                 pRealArray3=(luRealArray *)NewSysObj(luDynData_realarray,pRealArray1->ArrayLen,2);        //创建矩阵对象* t5 k* ~# S2 d, R% ^
  63.                 if(!pRealArray3) break;
    ; M8 a2 k3 ^3 Q! k
  64.                 pRealArray3->Dim[0]=pRealArray1->Dim[0]; pRealArray3->Dim[1]=pRealArray1->Dim[1];        //设置矩阵维数大小* R- u4 d8 u" K6 i/ Q- L& i' M$ m% d
  65.                 for(i=0;i<pRealArray1->ArrayLen;i++) pRealArray3->Array[i]=pRealArray1->Array[i]*pRealArray2->Array[i];//矩阵点乘6 [' I* v, t5 ~. ]& V7 v/ h
  66.                 FunReObj(hFor);        //告诉Lu,返回一个动态对象. b5 f$ V- k8 P1 o- A3 F, W( @/ b6 A, K
  67.                 a.BType=luDynData_realarray; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pRealArray3;
    . }) p! P- L+ j, g6 L0 H
  68.                 break;
    ! P. T' K: I  A( |
  69.         case 46:        //重载函数new9 N3 [) m9 p' d) U
  70.                 a=ExeOperator(mm,xx,hFor,theOperator,luDynData_realarray);        //直接调用基本类型luDynData_realarray的new函数' m5 a" k& ]! J
  71.                 if(a.VType==luDynData_realarray) a.VType=Matrix;        //设置扩展类型为自定义的Matrix类型8 |, m0 Z  d: Y9 x. b# S
  72.                 break;8 S; e' `6 L4 l0 @" l
  73.         case 49:        //重载函数o8 h/ I* b0 }  {- N3 b! w: a; f/ j( j
  74.                 pMessage=(luMessage)SearchKey("\0\0\0\0",sizeof(luVOID),luPubKey_User);0 E# o( O6 H0 s7 K5 g7 c
  75.                 if(!pMessage) break;- L' W. L, {/ `- p; m
  76.                 pRealArray1=(luRealArray *)SearchKey((char *)&(xx->x),sizeof(luVOID),luDynData_realarray);
    " _5 @5 v: Q: F) H; g8 D
  77.                 if(!pRealArray1) break;        //对象句柄无效,不是实数数组
    , i& P" G+ }1 [
  78.                 if(pRealArray1->DimLen!=2) break;        //不是二维实数数组(矩阵)1 S* k8 T; _6 f; H  Q& O4 V7 w
  79.                 pa=pRealArray1->Array;
    $ T( Q3 U& W5 v4 L( M/ j
  80.                 m=pRealArray1->Dim[0]; n=pRealArray1->Dim[1]; k=0;1 u, U6 @* z% J$ X2 t+ a1 I
  81.                 for(i=0; i<m; i++)        //输出矩阵
    - n8 u9 A0 o& f9 d+ `& W# o1 G
  82.                 {
    # ?2 o& Y& w& K; N5 ~
  83.                         pMessage(L"\r\n"); k+=2;, f, V) B+ @- g5 V
  84.                         for(j=0; j<n; j++)9 K, z4 g$ `; b+ X' P8 U: g7 M
  85.                         {3 l+ x/ e- x; ]1 D/ V0 E4 N/ Y* C
  86.                                 _gcvt_s(chNum,pa[i*n+j],16);8 ^4 Z5 N8 S& x& Y/ H( B$ F+ X
  87.                                 for(u=0;chNum[u];u++) {wchNum[u]=chNum[u]; k++;}
    4 @1 N1 h8 Y) s0 T+ J
  88.                                 wchNum[u]='\0';* ~/ ~. i. m9 z* a3 t5 O! T
  89.                                 pMessage(wchNum); pMessage(L"  "); k+=2;
    2 J' B% P4 Z( \& z3 q! H" {
  90.                         }
    1 x, u- G% a% }8 \" f' I7 H" N" k' c" p* u
  91.                 }
    ; V! n( x4 N% M6 s. d+ W+ R+ V, F% _
  92.                 pMessage(L"\r\n"); k+=2;- C9 Q; K0 a3 F( i4 _+ q) U$ ^
  93.                 a.BType=luStaData_int64; a.VType=luStaData_int64; a.x=k;        //按函数o的要求,返回输出的字符总数
    8 j4 M0 y$ H0 y# E
  94.                 break;; s/ K/ h% y8 ^
  95.         default:
    3 _( _3 t; u0 _: K' R
  96.                 break;/ j- p# @7 T# @* B  ^! i( w
  97.         }
    " Q1 R% F$ w4 \' v
  98.         return a;8 G; |: }, w1 h1 m  P+ |6 i6 N
  99. }6 D( ]! ^+ V* @6 J9 ]( d& q
  100. void main(void)4 E% G. h4 S. @/ x+ c' P" K2 e! @- S% N& B
  101. {
    # [% c: w1 }5 v
  102.         void *hFor;                //表达式句柄
    # R. S, I* R& s3 X7 A' N) j# j2 B
  103.         luINT nPara;                //存放表达式的自变量个数
    ' L' {7 n2 N" ]# c3 T
  104.         LuData *pPara;                //存放输入自变量的数组指针3 Z& {% m2 Q4 G5 a( a+ k8 t& T
  105.         luINT ErrBegin,ErrEnd;        //表达式编译出错的初始位置和结束位置
    8 I  A: K, O& g1 c# O
  106.         int ErrCode;                //错误代码
    " T! S$ l3 n& j& @1 Q+ O. m& L
  107.         void *v;
    5 e, B/ @6 k9 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.]}";//字符串表达式,矩阵乘
    + P5 }: _8 G" r6 Y" o
  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.]}";//字符串表达式,矩阵点乘
    - C& f* b! c( u% y  _
  110.         LuData Val;0 x: U, l7 ~/ t3 k- U# t) h
  111.         if(!InitLu()) return;        //初始化Lu+ [6 p* ~; [' f- W% ?3 d2 \! C
  112.         while(LockKey(Matrix,DelMatrix,OpMatrix)){Matrix++;}        //锁定一个键,用于存储矩阵扩展类型$ x  Q. h- `9 B' W  k' J
  113. 7 H7 v1 F& U- r6 p: w9 D
  114.         Val.BType=luStaData_int64; Val.VType=luStaData_int64; Val.x=Matrix;        //定义整数常量
    + U  O% N7 B; n; d( u; z$ D# f3 B
  115.         SetConst(L"matrix",&Val);        //设置整数常量
    ( O' f% T6 Y2 @5 s. m) _8 F
  116.         InsertKey("\0\0\0\0",4,luPubKey_User,LuMessage,NULL,NULL,1,v); //使Lu运行时可输出函数信息
    1 O5 p( ^. C; e4 L
  117.         wcout.imbue(locale("chs"));        //设置输出的locale为中文
    4 T/ H  B% V% O- l; w4 Z5 z
  118.   % o) x0 [  a3 b2 ^1 ~" e1 O2 b
  119.         ErrCode=LuCom(ForStr,0,0,0,hFor,nPara,pPara,ErrBegin,ErrEnd); //编译表达式9 O3 |" _) d; ]1 m* U% a
  120.         if(ErrCode)
    , ^/ B4 d0 {% `* A8 z4 `" F8 {
  121.         {" R: E" a2 I! I! c+ p  ~# t7 T
  122.                 wcout<<L"表达式有错误!错误代码:"<<ErrCode<<endl;
    5 e2 y+ P" J' f" U/ `2 w3 O- F% c
  123.         }# G: i) a# M$ a: j) l
  124.         else+ y6 a  c- J' u/ d2 X1 W$ S5 t( ?  K
  125.         {
    ( v3 h7 @' R* u- L( D
  126.                 LuCal(hFor,pPara);        //计算表达式的值, O0 o1 N$ M" s) H0 |. b7 [
  127.         }4 h$ ^) w+ f  v+ g# @% |
  128.         LockKey(Matrix,NULL,OpMatrix);//解锁键Matrix,本例中,该函数可以不用1 Z6 t- s& H  C8 y( _
  129.         FreeLu();                        //释放Lu- \3 r8 b$ ]# [6 P  W; {: P. G% y, o
  130. }
复制代码
习题:
& s7 Y! `8 v% p0 d2 [( Q& A+ S# K- H9 @( n
    (1)自定义矩阵的加、减、左除、右除、点左除等运算,自编测试字符串代码,重新编译运行程序,观察计算结果。 7 k' e+ B4 x+ G: F$ K0 K3 n
$ ^: n9 @" \( Z- t! v4 o/ i
    (2)小矩阵乘效率测试。编译运行以下Lu字符串代码:
  1. main(:a,b,c,d,t,i)=( `! m/ \+ Z( Z. y3 R
  2.     a=new[matrix,2,2,data:1.,2.,2.,1.],. M* j& ~: v1 S; a! r" i
  3.     b=new[matrix,2,2,data:2.,1.,1.,2.],  k. o9 Q) ?; ^; F% U( p" Z9 K8 \
  4.     c=new[matrix,2,2,data:2/3.,-1/3.,-1/3.,2/3.],4 g& n; ]0 J- {# ]0 ]
  5.     t=clock(),8 D- d- }, f- u# }" L
  6.     d=a*b, i=0, while{i<1000000, d=d*c*b, i++},
    ; `8 b* G; _- O& n
  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.
    : q0 T+ H9 `. h7 n# |9 R
  2. 5. 4.
    , e7 _6 O; Y( J7 U* G" a
  3. time=0.875 seconds.
    * Z6 V! A/ X& X# _& T9 b6 d0 f
  4. 请按任意键继续. . .
复制代码
Matlab 2009a 代码:
  1. a=[1.,2.;2.,1.];
    : S- X; C0 P- e4 y- }
  2. b=[2.,1.;1.,2.];8 z! Q4 q& }) P, i9 |- d7 @
  3. c=[2/3.,-1/3.;-1/3.,2/3.];& z2 S/ {7 \% ^' f4 J
  4. tic,; K$ C; J/ ]( C: s1 P0 P9 l/ F
  5. d=a*b;
    9 L7 ~: P4 F# f( S3 C8 Y& o6 j
  6. for i=1:1000000
    % M2 e. ~* }- M
  7.     d=d*c*b;" d" W4 a) t7 {5 `: C- Q: k
  8. end
    - [7 Y% E6 L1 H3 y: r) s
  9. d,9 z/ o; x" L  S( Z3 m0 W  i
  10. toc
复制代码
结果:
  1. d =2 N" M9 T) W8 V! r5 c& A% a6 v+ O
  2.      4     5. @3 t0 |# a! ~" O9 |$ Q& O
  3.      5     4
    ) D3 H9 a6 O9 J" u
  4. Elapsed time is 2.903034 seconds.
复制代码
本例矩阵乘效率测试,Lu的速度超过了Matlab,主要在于Lu有更高的动态对象管理效率。' r( I- M/ [- e' x





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