数学建模社区-数学中国
标题:
在Lu中创建自定义数据类型,小矩阵乘效率测试
[打印本页]
作者:
forcal
时间:
2011-10-24 18:54
标题:
在Lu中创建自定义数据类型,小矩阵乘效率测试
本例中,我们将自定义矩阵(matrix)类型,基本类型和扩展类型均为matrix(标识矩阵)。
7 r' ^( N+ T, X3 H* l
, Z1 M: s- y3 L( i4 C6 L. S+ U
基本要点:
o* V( p. y" [0 ]
( y2 K3 u3 `8 i" v! d y! [
(1)编写生成矩阵(matrix)的函数NewMatrix和销毁矩阵的函数DelMatrix。
+ S1 L# D. q; |( T7 e
8 d$ e/ b( `3 F: @
(2)为自定义类型matrix编写运算符重载函数OpMatrix。
9 U6 q9 |$ T8 J7 a
) i. p9 a* {2 F8 E0 q
(3)用函数LockKey将重载函数OpMatrix注册到Lu,锁定的键的类型即为matrix,要注册为常量,以便于使用。
) M5 ]" Y9 ]" F8 K/ W k1 L% q8 ^
- a- @3 u2 B, j3 a( C
(4)为自定义类型matrix编写其他操作函数(本例未提供)。
% y$ }% U( @ V8 m, }
+ b4 K9 z6 |* N# q
(5)用函数LockKey解锁键matrix(本例中,程序退出时会自动解锁,故可以不用)。
#include <windows.h>
( a* _# ?) q2 q
#include <iostream>
+ M+ p w# \9 v$ P: ^1 J6 v1 }9 D
#include <math.h>
, P7 i! y& f' U6 ^; w. S
#include "lu32.h"
3 F `) X( v$ u5 @' S' X9 o" |
#pragma comment( lib, "lu32.lib" )
, S4 j- O* X% j& ?
using namespace std;
9 I: u6 G. f- S/ J
//自定义矩阵
- `- N# @; x; O: w
class myMatrix
9 U4 m- ]; q, }
{
0 w" W9 A. e1 b* G. N+ Y! H3 U3 F7 y! G1 X
public:
7 Q" S+ P; m5 k' W. j/ w
double *Array; //数据缓冲区
k* k4 h; B1 `; k) l4 l, g
luVOID ArrayLen; //数据缓冲区长度
0 t1 ^1 A* {3 E; ~! F! E3 F
luVOID Dim[2]; //矩阵维数
+ v0 T2 a/ f6 x+ K$ ]& ~
myMatrix(){Array=NULL; ArrayLen=0; Dim[0]=0; Dim[1]=0;}
K7 F) w4 H% N1 u7 s+ D) @
~myMatrix()
2 g. x( k8 T4 r, i* n% `
{
0 c6 z) d3 q9 [3 L2 E
if(Array) delete[] Array;
, u# z6 G' [9 Z$ p2 r4 D6 ^1 F
}
( J; }6 }. m# T) G4 u( c A9 G
};
5 }; d2 U% @+ m! Z6 j( I* p# A* ]
luKEY Matrix=-1000; //标识矩阵类型,最终的Matrix由LockKey决定
* j+ s4 t' A" f0 e2 b. t
void _stdcall LuMessage(wchar_t *pch)//输出动态库信息,该函数注册到Lu,由Lu二级函数调用
! W. [" \5 L: E2 O" Z& m9 h
{
! k) k3 Q' ?! S% u! v; f1 |
wcout<<pch;
" A) |9 A9 d& `$ [* ?1 j2 o
}
h# o9 Z' \7 ?$ s0 Z
void _stdcall DelMatrix(void *me) //用于LockKey函数及InsertKey函数,使Lu能自动销毁myMatrix对象
0 i) K6 k' u) S) _. Z6 m
{
$ o) g. ^1 g T2 T. F7 B
delete (myMatrix *)me;
, U3 H" [8 s+ S; c# D2 o4 ?% }
}
4 v5 D$ e, I$ L% X: P
myMatrix * _stdcall NewMatrix(luVOID m,luVOID n) //生成一个myMatrix对象
" [) s7 H! Z5 B
{
% }0 f2 ^6 ]" M
myMatrix *pMatrix;
7 ]: V2 o. _9 y
luVOID k;
- A' b. B% [: C7 \1 D, I9 y
double *pa;
: }4 E1 ^. G$ q2 T6 V+ L2 S! e* [; h& D
char keyname[sizeof(luVOID)];
, S) T8 y9 j8 o e+ |2 l; I) Y
void *NowKey;
q, l! e& a1 D' {; I2 t5 ]0 x7 }
k=m*n;
$ U1 ?* b& \. }2 H# F- I S& N
pMatrix=(myMatrix *)GetBufObj(Matrix,keyname);//先尝试从缓冲区中获取一个矩阵对象
2 s/ ?6 {7 K! ^, N
if(pMatrix)
6 l% J# ^( u, i* K8 S- r8 o2 F
{
: G+ E# @. M4 Q9 {7 N' T, q' V
if(pMatrix->ArrayLen!=k) //重置矩阵的大小
3 S2 p1 I& z5 G* k/ z9 u( b8 t
{
. r3 N0 i! {, v. R- y5 B
pa=new double[k];
$ i" S: h$ z0 k6 T+ d1 t# p
if(!pa)
) C4 R7 y" @4 M$ l% q7 O/ o
{
4 Q) R: j1 S' H7 k4 w( e7 @
DeleteKey(keyname,sizeof(luVOID),Matrix,DelMatrix,1); //将矩阵对象放回缓冲区
$ L( W8 |. G* ^8 N0 c
return NULL;
5 |) Z$ g/ C7 [' d( J- C$ W8 O/ a' Z
}
. @4 N$ k3 } q9 p: w
delete[] pMatrix->Array;
* g5 v* {0 G' S+ R# Z$ Y5 ]1 V6 t0 s
pMatrix->Array=pa;
4 K9 R3 x/ d+ Z o9 a! V
}
) `! h3 @1 t" M; g
}
3 C: \% H A" b) {- I1 {* k
else
5 z* K: P/ s, Y
{
) g/ T0 @) F, O. S) D8 \$ r
pMatrix=new myMatrix; //创建矩阵对象
% B$ ]1 f" v$ f/ ]1 N' w
if(!pMatrix) return NULL;
0 M" ]( `! } n r. i4 w8 b
pMatrix->Array=new double[k];
2 F* E8 u4 k H& n
if(!pMatrix->Array)
: `1 ]5 M. [, l5 E, G4 B
{
6 ^$ F( u* V9 O# [" d
delete pMatrix;
" `+ f1 c5 W9 c9 O! I- j& f* z4 F9 B
return NULL;
) W; p/ F. R) m8 ^" f
}
5 h8 l8 u5 j9 g5 C6 U$ l7 j) J
if(InsertKey((char *)&pMatrix,-1,Matrix,pMatrix,DelMatrix,NULL,0,NowKey)) //将矩阵对象注册到Lu
' x# t, X3 R0 e# Y
{
; V; `0 B4 V& b* A) ?7 l& N6 m1 G: }
delete pMatrix;
( `# R5 L5 e- o
return NULL;
# t4 {6 R# V1 \ e) S$ u _$ t# A1 b
}
" A, J; [/ `. x4 y& T+ R# n' `7 f
}
6 p2 ]* v, s; p, |
pMatrix->ArrayLen=k; pMatrix->Dim[0]=m; pMatrix->Dim[1]=n;
) s' k: O! R" J" {! z7 I7 `, H
return pMatrix;
* L6 q/ E- \, j# p, m- R
}
3 j1 S4 _) g- e* T* V% w2 y+ K9 q' c
LuData _stdcall OpMatrix(luINT mm,LuData *xx,void *hFor,int theOperator) //运算符重载函数,用于LockKey函数
0 o5 b0 W2 T" k8 i( U9 I
{
. g- i& ^% t8 g+ S) {! j
LuData a;
2 q6 f9 E2 ~+ Z
myMatrix *pMatrix1,*pMatrix2,*pMatrix3;
c" u' C8 P4 r) u
luVOID i,j,k,m,n,u,v;
9 m1 a4 |6 B+ Y7 B% @
double *pa,*pb,*pc;
; A2 |6 P& B. P0 [+ z- u5 j
luMessage pMessage;
6 T q' Z2 m- @/ ?& _9 x! e- v
wchar_t wchNum[32];
: j+ V4 C) N+ O% A6 K9 A, A" S/ Q
char chNum[32];
$ \# B/ |- a* x1 j1 H4 m
a.BType=luStaData_nil; a.VType=luStaData_nil; a.x=0;
9 V% a. ~' G2 I' Y' s
switch(theOperator)
) \# \/ L* ~) s" r
{
' m) _( _ b. u/ u; h
case 2: //重载运算符*
. H1 J1 b5 R# K: L, d/ ?* _
pMatrix1=(myMatrix *)SearchKey((char *)&(xx->x),sizeof(luVOID),Matrix);
9 W) O* ? S5 U/ {; L
pMatrix2=(myMatrix *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),Matrix);
" K! a3 u$ R2 \% H
if(!pMatrix1 || !pMatrix2) break; //对象句柄无效,不是矩阵
! p: ]; e/ Y1 D% h, W
if(pMatrix1->Dim[1]!=pMatrix2->Dim[0]) break; //维数不匹配
, p0 T+ t' x, O: w( \0 R2 v$ B
pMatrix3=NewMatrix(pMatrix1->Dim[0],pMatrix2->Dim[1]); //生成新矩阵
! K& b; l I6 I
if(!pMatrix3) break;
' N; I* c S: |1 G7 j# ~/ s8 S$ I
pa=pMatrix1->Array; pb=pMatrix2->Array; pc=pMatrix3->Array;
! }: D8 |8 o% L0 g9 W) n
m=pMatrix1->Dim[0]; n=pMatrix1->Dim[1]; k=pMatrix2->Dim[1];
- H" X x( p2 a# A7 g; N
for(i=0; i<m; i++) //矩阵乘
7 Z, x! A9 \5 t" Y0 E8 C$ K
{
/ D1 x7 z7 H' M
for(j=0; j<k; j++)
( K8 b+ L' R- B+ y
{
% J4 L* F, N& [4 U6 X
u=i*k+j; pc[u]=0.0;
9 s+ }9 V9 Q9 T/ g
for (v=0; v<n; v++)
$ p7 u: [9 \2 e2 F* ~
{
/ S, u" [! ~% {( {. t
pc[u]=pc[u]+pa[i*n+v]*pb[v*k+j];
0 J* S) f- @8 _, }. h. X
}
) W9 ] w% X, W: T. A
}
! O1 q1 [3 v( e3 K* v7 W
}
1 x, g2 @) d6 i
FunReObj(hFor); //告诉Lu,返回一个动态对象
3 [2 V" E+ ^( Q0 \4 c; E- g, n
a.BType=Matrix; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pMatrix3;
3 g# ~4 U$ F: X$ e6 S
break;
) Y/ t) h) |7 C Y: v8 a; _
case 25: //重载运算符.*
! {9 f: s- N+ |, k" G4 E- m. X0 d5 b
pMatrix1=(myMatrix *)SearchKey((char *)&(xx->x),sizeof(luVOID),Matrix);
$ I I6 Y+ l8 A* I& e
pMatrix2=(myMatrix *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),Matrix);
! U" T1 p6 ^5 N6 j% Y6 B2 W+ L/ c: }
if(!pMatrix1 || !pMatrix2) break; //对象句柄无效,不是矩阵
, h3 z# n7 v5 L) }3 I& W$ m
if(pMatrix1->Dim[0]!=pMatrix2->Dim[0] || pMatrix1->Dim[1]!=pMatrix2->Dim[1]) break; //维数不相同
5 ~& s6 m0 P# }: \
pMatrix3=NewMatrix(pMatrix1->Dim[0],pMatrix1->Dim[1]); //生成新矩阵
# m' o) Q: ~0 t9 m" k1 P! v8 i
if(!pMatrix3) break;
+ m% ?' D( m1 }0 u$ F
for(i=0;i<pMatrix1->ArrayLen;i++) pMatrix3->Array[i]=pMatrix1->Array[i]*pMatrix2->Array[i]; //矩阵点乘
$ y8 l7 B# p4 k. G, s8 H
FunReObj(hFor); //告诉Lu,返回一个动态对象
3 j, w8 m8 C3 q! @
a.BType=Matrix; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pMatrix3;
8 t9 z" C3 J7 O2 ?3 T: F
break;
* {5 q% V9 k4 R Q- r
case 46: //重载函数new
) ~% P2 X/ v0 p9 G- p
if(mm<2) break;
0 i, K9 J! Y* x& ]7 {
if((xx+1)->x<1 || (xx+2)->x<1 || (xx+1)->BType!=luStaData_int64 || (xx+2)->BType!=luStaData_int64) break;
" ~! }' S: O1 R' Y, x$ ?1 T2 Y
pMatrix3=NewMatrix((luVOID)(xx+1)->x,(luVOID)(xx+2)->x);//生成新矩阵
F5 N( x3 H: `" v/ m: x9 s
if(!pMatrix3) break;
: y0 U& p+ M$ B" r% U
for(j=0,i=3;i<=mm;i++,j++) //赋初值
" x0 i, a) L+ b) x/ T4 x+ _/ D
{
?2 G- f! Q. \0 a+ C) S' h2 p8 v' A
if(j>=pMatrix3->ArrayLen) break;
9 R+ X8 _5 Q) _( j2 ^
if((xx+i)->BType!=luStaData_double) break; //只接受实数参数
& B' z9 _0 o: Q& l! D1 z9 O& P
pMatrix3->Array[j]=*(double *)&((xx+i)->x);
# x* W7 e# E; y
}
6 }( G$ A8 m8 L$ n: Z
FunReObj(hFor); //告诉Lu,返回一个动态对象
1 A5 F( s+ Q' H9 r: ~. ^" g
a.BType=Matrix; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pMatrix3;
2 x: g( y) A+ A$ J& ^8 D
break;
2 Y- S% h8 L( `& }1 n8 X
case 49: //重载函数o
- k+ |, @% |" l9 u. @" x
pMessage=(luMessage)SearchKey("\0\0\0\0",sizeof(luVOID),luPubKey_User);
' r0 l W* l; N1 Y% o% Q0 C% l2 l' |) ?
if(!pMessage) break;
. \* K& U# z, f/ l# S
pMatrix1=(myMatrix *)SearchKey((char *)&(xx->x),sizeof(luVOID),Matrix);
) r5 H% G/ E4 n0 C' ^
if(!pMatrix1) break; //对象句柄无效,不是矩阵
\: s( D2 g: S+ F( d
pa=pMatrix1->Array;
& k+ D0 ]1 w) L
m=pMatrix1->Dim[0]; n=pMatrix1->Dim[1]; k=0;
) j/ {& Z- G' c0 {! c6 c
for(i=0; i<m; i++) //输出矩阵
. g+ z4 p5 V: b5 |' k" m' ]* N
{
( A: e6 [3 N0 @/ E6 I
pMessage(L"\r\n"); k+=2;
K4 r! N+ r7 M0 k `
for(j=0; j<n; j++)
/ a& |7 Y; b6 q3 B P$ G9 }
{
' Q3 s& F: r C8 F
_gcvt_s(chNum,pa[i*n+j],16);
2 M, \2 F+ U3 T6 C0 P( M
for(u=0;chNum[u];u++) {wchNum[u]=chNum[u]; k++;}
e; K2 Q9 ^1 b) s& S
wchNum[u]='\0';
6 ?$ n5 d% X! ?8 I1 H2 ~
pMessage(wchNum); pMessage(L" "); k+=2;
9 y& F. m) c% v" l' _
}
- U, P+ C$ p- o+ @' |1 p
}
: o/ b4 O* k& I8 L
pMessage(L"\r\n"); k+=2;
) ~; ]. L" S- F; J" v% {
a.BType=luStaData_int64; a.VType=luStaData_int64; a.x=k; //按函数o的要求,返回输出的字符总数
8 U+ Q' ]) c! {
break;
8 Q8 H. b* I$ D7 A2 A
default:
6 x& u* z* K: t( v% p4 a
break;
2 M' D" M8 o8 X/ H% x
}
% n! {" M; o; f/ s; Z
return a;
3 s4 w N X- x+ Y6 ]5 }8 P
}
7 m. A' j% K; k( v, z0 W
void main(void)
- z% c0 f5 w1 D
{
3 e6 l+ h7 v' v% k+ v. s" b
void *hFor; //表达式句柄
0 I0 `* w$ z+ Y7 |6 l2 a
luINT nPara; //存放表达式的自变量个数
4 d# X% m2 E; O: h9 a( C6 |6 Y( N
LuData *pPara; //存放输入自变量的数组指针
+ [" r! J# g! @
luINT ErrBegin,ErrEnd; //表达式编译出错的初始位置和结束位置
' ~$ r! S" s- }( n
int ErrCode; //错误代码
0 B! r) Q( Y: r1 |6 x+ [# C
void *v;
; x; X' ? F. @! h- B1 P
wchar_t ForStr[]=L"o{new[matrix,2,3: 0.,1.,2.;3.,4.,5.]*new[matrix,3,2: 1.,2.;3.,4.;5.,6.]}";//字符串表达式,矩阵乘
$ c( F/ {- e8 F8 p" X6 o. \! Q. T
//wchar_t ForStr[]=L"o{new[matrix,2,3: 0.,1.,2.;3.,4.,5.].*new[matrix,2,3: 1.,2.,3.;4.,5.,6.]}";//字符串表达式,矩阵点乘
) ~8 u- l7 }. o
LuData Val;
$ m0 e# j8 C& K/ M( I' M
if(!InitLu()) return; //初始化Lu
+ P9 o: K8 p* e0 S9 w, ]
while(LockKey(Matrix,DelMatrix,OpMatrix)){Matrix--;} //锁定一个键,用于存储矩阵扩展类型
% v6 e0 ]' ?" c0 r# d6 G3 I0 e
, Y9 F' e$ r# n) d. Z# i' y
Val.BType=luStaData_int64; Val.VType=luStaData_int64; Val.x=Matrix; //定义整数常量
; x/ t9 w# W O$ R4 b# H
SetConst(L"matrix",&Val); //设置整数常量
- C" v$ t8 D' b- g" B5 r
InsertKey("\0\0\0\0",4,luPubKey_User,LuMessage,NULL,NULL,1,v); //使Lu运行时可输出函数信息
# p! x0 i7 ]" u4 W) z J; M
wcout.imbue(locale("chs")); //设置输出的locale为中文
6 v/ p6 _& Q$ N3 Y, Y& d/ L3 z
' ?% {/ a' f+ I5 G" R
ErrCode=LuCom(ForStr,0,0,0,hFor,nPara,pPara,ErrBegin,ErrEnd); //编译表达式
/ c4 c/ W6 w- r) f2 h0 Y- }
if(ErrCode)
9 W3 r9 Q4 E' @. {) H, ~
{
( B. T8 A6 O' l# |1 s0 C
wcout<<L"表达式有错误!错误代码:"<<ErrCode<<endl;
1 m' D* M( e5 P/ l- ]
}
2 Z+ O$ }8 m7 a9 q) W
else
( B2 j) s% G8 P7 A% j
{
& H8 S/ `( }$ J, G
LuCal(hFor,pPara); //计算表达式的值
6 ^, C( d) z8 S, Q, P
}
" g3 U- g7 R; V( P+ r) w1 e
LockKey(Matrix,NULL,OpMatrix);//解锁键Matrix,本例中,该函数可以不用
2 w% A( r% Q: k8 K' E
FreeLu(); //释放Lu
5 h$ \2 b" Z6 s X3 ?
}
复制代码
习题:
% G7 T9 P1 n b9 h8 s' A: l
. t, J4 {0 Y; S( w7 \+ X
(1)自定义矩阵的加、减、左除、右除、点左除等运算,自编测试字符串代码,重新编译运行程序,观察计算结果。
8 f- K H7 K8 u( A0 U/ Z9 _% Z
0 J: v. l6 i1 W5 `9 f" v! Y: q4 b
(2)小矩阵乘效率测试。编译运行以下Lu字符串代码:
main(:a,b,c,d,t,i)=
9 J& u4 e! ?% ]" C3 t' K
a=new[matrix,2,2: 1.,2.,2.,1.],
# V5 y' e/ N+ @: R& o* k
b=new[matrix,2,2: 2.,1.,1.,2.],
. W- b0 y% h$ ^1 |
c=new[matrix,2,2: 2/3.,-1/3.,-1/3.,2/3.],
7 E' ^5 P+ p$ J. i/ s/ Y
t=clock(),
1 h) j4 G$ U3 H% Z0 k
d=a*b, i=0, while{i<1000000, d=d*c*b, i++},
. h O w, B4 k8 O" Q! E$ C! `9 W, j: U
o{d, "time=",[clock()-t]/1000.," seconds.\r\n"}
复制代码
C/C++中的字符串定义为:
wchar_t ForStr[]=L"main(:a,b,c,d,t,i)= a=new[matrix,2,2: 1.,2.,2.,1.], b=new[matrix,2,2: 2.,1.,1.,2.], c=new[matrix,2,2: 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\"}";//字符串表达式
复制代码
结果:
4. 5.
- O1 [& ^9 O1 n# m& x6 V
5. 4.
1 i* _7 r! I- ?2 [
time=0.797 seconds.
1 m$ M- F! S: q2 b! W7 h7 A
请按任意键继续. . .
复制代码
Matlab 2009a 代码:
a=[1.,2.;2.,1.];
2 ]* S8 ?; k: P z5 P. f& R2 K0 S
b=[2.,1.;1.,2.];
# |5 z+ S% h: A$ W/ x- [' S( f+ i) G
c=[2/3.,-1/3.;-1/3.,2/3.];
; C- B# l6 d& n* K/ }* o4 {
tic,
0 W9 g _% N) L- k, ]. @6 G
d=a*b;
. s5 C5 B. ^* @4 ~! H$ X" k
for i=1:1000000
9 J; \5 f5 W) \' x- C1 s# J
d=d*c*b;
. C) ^2 f. w9 C2 u
end
+ F- M- r) Y' I3 q N9 n
d,
% s9 b* g" M6 ~ w7 a
toc
复制代码
结果:
d =
5 _5 W7 j+ B$ `% l# K) y8 k
4 5
3 r4 M$ h/ C( i* f2 Y
5 4
" O: v1 E6 f7 w# A) ]
Elapsed time is 2.903034 seconds.
复制代码
本例矩阵乘效率测试,Lu的速度超过了Matlab,主要在于Lu有更高的动态对象管理效率。
& p9 i' x( a7 M3 u) t8 u
5 a0 ^# U- S& s. _
由以上可以看出,自定义数据类型和系统内置类型有近乎相同的效率。
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5