数学建模社区-数学中国

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

作者: forcal    时间: 2011-10-23 09:37
标题: Lu基于系统内置对象创建扩展数据类型,小矩阵乘效率测试
    本例中,我们将基于系统内置实数数组创建矩阵(matrix)类型,即:基本类型为luDynData_realarray(标识实数数组),扩展类型为matrix(标识矩阵)。为了简单,我们仅处理二维实数数组即矩阵类型。
) a! W1 [0 C  ?' S0 [4 [9 V) j, G  s8 m1 ^# i
    基本要点:' E" U- ]; k3 |$ w8 x0 t# V% y

% g$ U; @. c  @4 s0 ^% p+ ]    (1)为扩展类型matrix编写运算符重载函数OpMatrix。' P7 a. L, ~/ |* O* @
# H- |& C3 i+ l4 ?0 J
    (2)用函数LockKey将重载函数OpMatrix注册到Lu,锁定的键的类型即为matrix,要注册为常量,以便于使用。: p4 n# T8 p$ J( M) I

$ h# C* ^! W# ]8 o( P& F% {4 b    (3)为扩展类型matrix编写其他操作函数(本例未提供)。1 h6 U& ^" f* \

9 ], x0 `! {  w" b( I' N3 z+ B7 t    (4)用函数LockKey解锁键matrix(本例中,程序退出时会自动解锁,故可以不用)。
  1. #include <windows.h>
    - ?7 G& i- e) P- j/ J0 `3 Y9 I7 o7 m
  2. #include <iostream>& {* W$ F7 ]- Y0 Q1 z7 u
  3. #include <math.h>( M0 u  m7 _+ J7 S3 u) A( S, j. N
  4. #include "lu32.h"
    " v9 i, A  E. T+ Y; p* \. ^

  5. 3 P% m1 f& }7 ^
  6. #pragma comment( lib, "lu32.lib" )" e% x8 S, s. s% \; n4 `0 u

  7. 3 c) \1 l2 }+ q5 P9 K$ h. @
  8. using namespace std;
    , [+ b  B5 t% ~+ p/ D# U
  9. 0 q" i- u) g) v0 m* F/ y6 y
  10. luKEY Matrix=-1000;        //标识矩阵类型,最终的Matrix由LockKey决定
    / r7 ]0 Z0 d9 A
  11. ; e# f7 H2 K6 h1 L/ E* d5 d
  12. void _stdcall LuMessage(wchar_t *pch)//输出动态库信息,该函数注册到Lu,由Lu二级函数调用 2 ?( [8 |: a* j* f/ Y
  13. {
    7 f1 l1 ^: U/ Y6 C+ [
  14.         wcout<<pch;
    0 L* m( h& [9 }2 G% t: B
  15. }! X0 B$ o% u+ Y9 T. B1 ]
  16. void _stdcall DelMatrix(void *me)        //用于LockKey函数,因为是基于系统内置实数数组创建矩阵,故该函数什么也不做
    . G1 F& q  k- y, @0 v) c
  17. {4 L  X6 l. _6 T. g" C
  18. }; o3 ?1 |- r( N0 r: G. u6 }
  19. LuData _stdcall OpMatrix(luINT mm,LuData *xx,void *hFor,int theOperator)        //运算符重载函数,用于LockKey函数
    : W* M% t4 C  A8 J" X0 f
  20. {
    ( ~/ i4 y; d! T  |/ j1 ]
  21.         LuData a;/ f' g7 w1 m, j2 r/ L5 d. O( h
  22.         luRealArray *pRealArray1,*pRealArray2,*pRealArray3;6 A; z& Z6 L5 N2 \# Y( g& Y. E
  23.         luVOID i,j,k,m,n,u,v;
    $ o5 @# @: T3 Y1 t  w; @
  24.         double *pa,*pb,*pc;/ Z+ m& |8 L$ c
  25.         luMessage pMessage;2 J; Z) A- L% v! _" x% V
  26.         wchar_t wchNum[32];
    * [! ^) D% m, o6 a1 U
  27.         char chNum[32];1 b% X1 X" i' L  w( f, i3 S, F
  28.         a.BType=luStaData_nil; a.VType=luStaData_nil; a.x=0;: t, X. b9 y/ A! w- n9 i* Q! y
  29.         switch(theOperator)  Q" p) ]; e/ |% W5 t' l
  30.         {
    5 }3 E9 K" B' F" ]
  31.         case 2:        //重载运算符*
    + F+ |+ q& x' N7 W
  32.                 pRealArray1=(luRealArray *)SearchKey((char *)&(xx->x),sizeof(luVOID),luDynData_realarray);
    4 ?  ]6 J  x7 D, o* T
  33.                 pRealArray2=(luRealArray *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),luDynData_realarray);
    ( y! |$ g( K( i# m: H
  34.                 if(!pRealArray1 || !pRealArray2) break;        //对象句柄无效,不是实数数组
    ) E3 L& c; C( y; `8 q" t
  35.                 if(pRealArray1->DimLen!=2 || pRealArray2->DimLen!=2) break;        //不是二维实数数组(矩阵)
    ! R2 N  p1 ]; }+ G7 Y6 I  R
  36.                 if(pRealArray1->Dim[1]!=pRealArray2->Dim[0]) break;        //维数不匹配
    # z  }$ {& l! l; V2 z: j
  37.                 pRealArray3=(luRealArray *)NewSysObj(luDynData_realarray,pRealArray1->Dim[0]*pRealArray2->Dim[1],2);        //创建矩阵对象
    & ^$ ?6 D% z+ i+ W; h6 h8 a8 p
  38.                 if(!pRealArray3) break;
    ' f: [$ g" Z  @4 F0 c2 e
  39.                 pRealArray3->Dim[0]=pRealArray1->Dim[0]; pRealArray3->Dim[1]=pRealArray2->Dim[1];        //设置矩阵维数大小% P% ~8 \3 r7 i+ L0 z
  40.                 pa=pRealArray1->Array; pb=pRealArray2->Array; pc=pRealArray3->Array;
    2 Z' j: r1 t8 e+ o9 g+ t) n
  41.                 m=pRealArray1->Dim[0]; n=pRealArray1->Dim[1]; k=pRealArray2->Dim[1];& R7 ?* S4 k: M  F1 U! t, s/ P) [
  42.                 for(i=0; i<m; i++)        //矩阵乘
      n! o3 l1 B3 g! r
  43.                 {
    * I% \0 _0 U# F* b: R6 R; x
  44.                         for(j=0; j<k; j++)5 o5 |8 w, D& Y. U; F+ u) l
  45.                         {) M: ]5 n) g9 w2 ]0 J
  46.                                 u=i*k+j; pc[u]=0.0;& L- Q" ^+ F0 m& j
  47.                                 for (v=0; v<n; v++)
    + H1 d; W+ C- e/ A' s7 C
  48.                                 {7 W6 g( t. y6 t7 b, a
  49.                                         pc[u]=pc[u]+pa[i*n+v]*pb[v*k+j];
    0 U2 I" q6 D6 }" I
  50.                                 }% c" W% s% B, j
  51.                         }& C8 i$ S4 }  `7 P5 z4 Y- i
  52.                 }
    ' a! U7 }5 k/ a" q, F( L
  53.                 FunReObj(hFor);        //告诉Lu,返回一个动态对象
    ; E! ~. _2 ?3 U7 E  c" ^+ [
  54.                 a.BType=luDynData_realarray; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pRealArray3;
    % h+ N$ S/ T0 Q6 N. f/ I
  55.                 break;: g4 c- J8 _) O, [8 V
  56.         case 25:        //重载运算符.*
    6 W( P( U5 o( b
  57.                 pRealArray1=(luRealArray *)SearchKey((char *)&(xx->x),sizeof(luVOID),luDynData_realarray);7 g! |6 ~; [) U0 \$ F$ x. M7 L% ?, X
  58.                 pRealArray2=(luRealArray *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),luDynData_realarray);
    ( h( M3 S' T1 ^) ]9 J1 _9 N% ]
  59.                 if(!pRealArray1 || !pRealArray2) break;        //对象句柄无效,不是实数数组
    4 {/ A3 P/ `; E2 [& z
  60.                 if(pRealArray1->DimLen!=2 || pRealArray2->DimLen!=2) break;        //不是二维实数数组(矩阵)0 H  S, X- p7 G2 q3 N
  61.                 if(pRealArray1->Dim[0]!=pRealArray2->Dim[0] || pRealArray1->Dim[1]!=pRealArray2->Dim[1]) break;        //维数不相同7 j+ j& m6 F+ ]1 ]. \5 j% }
  62.                 pRealArray3=(luRealArray *)NewSysObj(luDynData_realarray,pRealArray1->ArrayLen,2);        //创建矩阵对象% C. }1 g, g; j- S+ g" H) w1 m: {+ D! N
  63.                 if(!pRealArray3) break;+ q% L0 p( i( @6 J
  64.                 pRealArray3->Dim[0]=pRealArray1->Dim[0]; pRealArray3->Dim[1]=pRealArray1->Dim[1];        //设置矩阵维数大小6 V, _% [2 M* M" G
  65.                 for(i=0;i<pRealArray1->ArrayLen;i++) pRealArray3->Array[i]=pRealArray1->Array[i]*pRealArray2->Array[i];//矩阵点乘0 V' j# A% M! q6 y' m/ }
  66.                 FunReObj(hFor);        //告诉Lu,返回一个动态对象. g/ f/ g; \* U) K9 g8 G
  67.                 a.BType=luDynData_realarray; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pRealArray3;
    , w) L& b6 ]9 M7 P
  68.                 break;2 _) }( ]+ A' T% {. g
  69.         case 46:        //重载函数new" }2 }  Q+ `2 I2 L5 q' P
  70.                 a=ExeOperator(mm,xx,hFor,theOperator,luDynData_realarray);        //直接调用基本类型luDynData_realarray的new函数' ~0 O3 m- b2 o% u
  71.                 if(a.VType==luDynData_realarray) a.VType=Matrix;        //设置扩展类型为自定义的Matrix类型0 Q3 V! d( [& d# U2 z1 q
  72.                 break;
    , d$ x5 `( u) `& @% A
  73.         case 49:        //重载函数o4 r* T0 S+ E# W' M' {5 l( Y% e
  74.                 pMessage=(luMessage)SearchKey("\0\0\0\0",sizeof(luVOID),luPubKey_User);
    : j0 G# r/ ~+ u6 H$ E
  75.                 if(!pMessage) break;
    6 K& F* m; A6 g3 }9 x0 v" n
  76.                 pRealArray1=(luRealArray *)SearchKey((char *)&(xx->x),sizeof(luVOID),luDynData_realarray);. [0 Z3 d5 ?) u* D
  77.                 if(!pRealArray1) break;        //对象句柄无效,不是实数数组
    / S) {5 X  u0 f6 `, B
  78.                 if(pRealArray1->DimLen!=2) break;        //不是二维实数数组(矩阵)- d' n8 W3 w  Y8 P; L9 g4 b6 |
  79.                 pa=pRealArray1->Array;0 O+ V+ q4 n* @3 R: `* x4 n
  80.                 m=pRealArray1->Dim[0]; n=pRealArray1->Dim[1]; k=0;
    ! e) g4 e" q0 ]; c' C! B  {
  81.                 for(i=0; i<m; i++)        //输出矩阵
      V5 M# `/ X; W# J4 |
  82.                 {
    5 Q8 v% }4 V7 S7 X- X* Z
  83.                         pMessage(L"\r\n"); k+=2;) l0 j1 T2 i9 O! l
  84.                         for(j=0; j<n; j++)0 z8 k/ W' G3 _6 ~  R
  85.                         {
    ! s( C( d% f/ O$ e
  86.                                 _gcvt_s(chNum,pa[i*n+j],16);$ @' T" ^: e+ z, N0 r7 I0 j
  87.                                 for(u=0;chNum[u];u++) {wchNum[u]=chNum[u]; k++;}
    ' A0 k2 v9 l) [" C! ~4 c, H& [
  88.                                 wchNum[u]='\0';
      _, y% M* W9 K: j4 S/ O0 Z6 s
  89.                                 pMessage(wchNum); pMessage(L"  "); k+=2;6 [# V6 I5 V, G( f" U  C: {& z
  90.                         }. ~; E- s( ]; A
  91.                 }" m$ f0 O. C+ k3 G* g) M
  92.                 pMessage(L"\r\n"); k+=2;
    ; l- i3 J* t/ t# x$ U7 G1 b
  93.                 a.BType=luStaData_int64; a.VType=luStaData_int64; a.x=k;        //按函数o的要求,返回输出的字符总数
    ! o! G! \; E) }# N7 I
  94.                 break;
    % e% b, O# _1 T3 h/ R' S
  95.         default:
    $ a% g' k  U, c" S) `. A( Y2 P
  96.                 break;
    / {; ]1 p; v! r& e0 x
  97.         }
    ! X5 s' F$ `& A& x0 j! g
  98.         return a;/ r7 ]5 X2 Q# ^; F% `: [" n
  99. }5 L: h7 g+ }0 J. M, g5 [; \
  100. void main(void)$ F3 H" Y/ r, O. }7 O  P5 ^
  101. {  n# L' Y2 K7 Q7 w- c+ K* ^
  102.         void *hFor;                //表达式句柄, U4 c% l* f2 Z5 ]9 i
  103.         luINT nPara;                //存放表达式的自变量个数6 W2 _% ^4 A8 X: d9 u
  104.         LuData *pPara;                //存放输入自变量的数组指针
    : d( T7 D" U+ L" x# w
  105.         luINT ErrBegin,ErrEnd;        //表达式编译出错的初始位置和结束位置& G4 l) H4 }) Q$ l, K; m
  106.         int ErrCode;                //错误代码
    / r, {0 b% N+ n$ w9 d
  107.         void *v;
    , P- H/ g4 L" t) T2 A9 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.]}";//字符串表达式,矩阵乘6 _! A# S2 F( m4 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.]}";//字符串表达式,矩阵点乘3 O0 H- k  I0 T
  110.         LuData Val;
    ' @2 c) c8 e) l' K
  111.         if(!InitLu()) return;        //初始化Lu
    + Y- _$ B. w8 p' o4 c- U/ y* n
  112.         while(LockKey(Matrix,DelMatrix,OpMatrix)){Matrix++;}        //锁定一个键,用于存储矩阵扩展类型
    6 e7 l0 g0 u6 z1 s( l% q. t- w: N4 J. |

  113. ! k  ~4 U: U6 T% A" ?) Z/ ?8 w" V
  114.         Val.BType=luStaData_int64; Val.VType=luStaData_int64; Val.x=Matrix;        //定义整数常量
    6 s! Y1 _! V! _. G* k0 y
  115.         SetConst(L"matrix",&Val);        //设置整数常量$ |2 O9 X" U( `- v% V2 o9 Z; f* P
  116.         InsertKey("\0\0\0\0",4,luPubKey_User,LuMessage,NULL,NULL,1,v); //使Lu运行时可输出函数信息
    1 b) Q7 X- j2 }$ v
  117.         wcout.imbue(locale("chs"));        //设置输出的locale为中文4 T6 k' {; t+ F/ i& u
  118.   # E+ ]) W  K! ^) @, W
  119.         ErrCode=LuCom(ForStr,0,0,0,hFor,nPara,pPara,ErrBegin,ErrEnd); //编译表达式
    $ n, o/ l: c/ C* Z* U+ l% ?) P
  120.         if(ErrCode)
    6 j- S: w6 v  Y/ N- f0 h
  121.         {
    ' Q" M% e8 T2 _
  122.                 wcout<<L"表达式有错误!错误代码:"<<ErrCode<<endl;
    ( X! q2 q7 ~0 A% P
  123.         }  n2 H3 u' ]4 d6 W
  124.         else; F9 g, [( h5 k- A3 E! ]
  125.         {( V8 t$ U5 _4 u  i) W
  126.                 LuCal(hFor,pPara);        //计算表达式的值
    - p. b) M2 S+ I
  127.         }
    # F5 z* k5 r8 j+ R4 X0 M( k7 r6 X
  128.         LockKey(Matrix,NULL,OpMatrix);//解锁键Matrix,本例中,该函数可以不用* j# z1 s* w; i" N. S7 s
  129.         FreeLu();                        //释放Lu. K0 A. V2 V  B8 d- l8 j  ?9 h& `
  130. }
复制代码
习题:
5 ]. L! }5 @' u% ?( w( U0 s3 z
$ h1 S# {. `. m6 X) k    (1)自定义矩阵的加、减、左除、右除、点左除等运算,自编测试字符串代码,重新编译运行程序,观察计算结果。
- M5 ?( g9 m) J% M
% z1 X- c9 O' p/ ~+ Y  m    (2)小矩阵乘效率测试。编译运行以下Lu字符串代码:
  1. main(:a,b,c,d,t,i)=$ a) M2 E$ t5 z3 D
  2.     a=new[matrix,2,2,data:1.,2.,2.,1.],
    , g3 s# V" U! g2 B4 a- \
  3.     b=new[matrix,2,2,data:2.,1.,1.,2.],
    : X. C& j. j7 n+ ^
  4.     c=new[matrix,2,2,data:2/3.,-1/3.,-1/3.,2/3.],! S# F/ _! t$ X+ `
  5.     t=clock(),5 b$ M- a" [( W( O
  6.     d=a*b, i=0, while{i<1000000, d=d*c*b, i++},+ z  \1 ?; C6 S3 d% A4 H
  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 W! D; Z& Y1 Y" J5 g% g' K, X
  2. 5. 4.
    / e* h2 F$ O9 [+ ?9 v/ n3 U
  3. time=0.875 seconds.
      P. o0 \& c2 F; d
  4. 请按任意键继续. . .
复制代码
Matlab 2009a 代码:
  1. a=[1.,2.;2.,1.];
    ; A6 Y' {4 B0 Y) R. D
  2. b=[2.,1.;1.,2.];' U4 ^: `1 U+ s" J1 P
  3. c=[2/3.,-1/3.;-1/3.,2/3.];
    2 p% E6 P& D1 e5 R- n) U
  4. tic,/ W1 A" D$ E. m- ^+ m3 w
  5. d=a*b;% e6 J5 A0 `% J4 r7 |4 Y8 d% N4 Y5 U
  6. for i=1:1000000+ Y0 ~" m5 d. _( `$ D5 i, Y8 y+ [
  7.     d=d*c*b;" |" F. O% V5 ]
  8. end5 S2 n: t+ c5 {9 A: X
  9. d,
    2 l, {3 F1 j9 O! R, R: @7 j) V
  10. toc
复制代码
结果:
  1. d =7 h' |) h2 N& j) ]0 [; m/ U
  2.      4     5
    : h. N# i4 R% }/ v
  3.      5     4
    . q- V, H0 L" E; n4 {" G
  4. Elapsed time is 2.903034 seconds.
复制代码
本例矩阵乘效率测试,Lu的速度超过了Matlab,主要在于Lu有更高的动态对象管理效率。/ p. Z- q. s2 L2 ]- ?- S





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