数学建模社区-数学中国
标题:
在Lu中创建自定义数据类型,小矩阵乘效率测试
[打印本页]
作者:
forcal
时间:
2011-10-24 18:54
标题:
在Lu中创建自定义数据类型,小矩阵乘效率测试
本例中,我们将自定义矩阵(matrix)类型,基本类型和扩展类型均为matrix(标识矩阵)。
6 Y+ u: A' `3 I- x3 R8 {9 h, s9 [
& B' Q4 W. E; j
基本要点:
* z6 y; c' S+ O, Y: d* C1 E
2 A- O& M8 P2 C% _
(1)编写生成矩阵(matrix)的函数NewMatrix和销毁矩阵的函数DelMatrix。
+ h$ A5 [7 U+ O3 Y. r5 @8 a
8 g; I! ]% i4 b, Z0 A4 V
(2)为自定义类型matrix编写运算符重载函数OpMatrix。
$ ^! B! b, A- C6 b( w
# h F, {' o" h1 @3 s8 W
(3)用函数LockKey将重载函数OpMatrix注册到Lu,锁定的键的类型即为matrix,要注册为常量,以便于使用。
* ~' Q9 U* s4 O4 Z/ Q# x3 ]1 N
k% C+ E* R8 N* I, P0 q7 N1 d
(4)为自定义类型matrix编写其他操作函数(本例未提供)。
5 N' W) m- T& k" \
3 o1 [+ U' B; H, K! }/ I* a5 ~
(5)用函数LockKey解锁键matrix(本例中,程序退出时会自动解锁,故可以不用)。
#include <windows.h>
8 B3 b5 ]% j$ e; J7 W; a) s
#include <iostream>
5 f5 V0 ~: K4 d0 i8 X ~
#include <math.h>
0 O. \7 w7 a u* w' ?. o, G% P. |
#include "lu32.h"
; `5 N0 O1 d( q5 ?
#pragma comment( lib, "lu32.lib" )
5 T B+ `2 _. Z
using namespace std;
& w1 \8 }5 a$ v4 f
//自定义矩阵
7 S3 ?4 ?- Y# K" L# g
class myMatrix
& [3 U* D# l7 S" [- [/ e
{
" f) a2 l0 I% y) w$ Y4 h
public:
" q, C. ^( M; }; ]8 \6 B
double *Array; //数据缓冲区
6 \% j/ B( R' I, n) e8 U$ U1 ~# t
luVOID ArrayLen; //数据缓冲区长度
; v2 L [9 j G" I
luVOID Dim[2]; //矩阵维数
, k/ V* e0 W' a3 u) w8 w- y5 Q
myMatrix(){Array=NULL; ArrayLen=0; Dim[0]=0; Dim[1]=0;}
) V7 ]# S( j* j$ H, z' P2 Z
~myMatrix()
5 _/ F( f3 W; |+ R% _. p7 Q/ d, ]
{
7 G0 }+ t8 A+ e9 f- P
if(Array) delete[] Array;
1 g( B1 P+ R, K' \2 b* J
}
% ]0 t( X5 D' f6 [* S9 h x
};
9 b1 h1 G: p! Z* F+ T
luKEY Matrix=-1000; //标识矩阵类型,最终的Matrix由LockKey决定
, t! _$ D! @% J
void _stdcall LuMessage(wchar_t *pch)//输出动态库信息,该函数注册到Lu,由Lu二级函数调用
( ]) r" j, H5 V* F# R' ]
{
# i3 X! w$ ]( J
wcout<<pch;
8 V- ^1 I) e$ k: H$ X) }7 f# Z% h" l
}
. ^* l- a- m% U, e) U
void _stdcall DelMatrix(void *me) //用于LockKey函数及InsertKey函数,使Lu能自动销毁myMatrix对象
: R$ @$ h0 x6 W( r8 [6 a- a2 s
{
# {! q: c/ q* B4 ]8 o) g' b
delete (myMatrix *)me;
* g! M% ^$ R- M0 J
}
% E1 ]) y' T) }! C1 f, I. j
myMatrix * _stdcall NewMatrix(luVOID m,luVOID n) //生成一个myMatrix对象
! o, q9 c } }
{
/ F p* \2 j! n7 L4 s5 v' l( R6 k
myMatrix *pMatrix;
/ @& ` t, } D
luVOID k;
3 F% S2 g3 F" P- @
double *pa;
: @- T# r0 E8 x$ m( Y6 l+ w3 g
char keyname[sizeof(luVOID)];
& p( Y7 P/ m0 Z# h0 S. g2 i w
void *NowKey;
. A/ @+ Z& }5 V" k
k=m*n;
1 G* m' R, P- @3 C7 ~% l
pMatrix=(myMatrix *)GetBufObj(Matrix,keyname);//先尝试从缓冲区中获取一个矩阵对象
" b; F# j" X6 M/ m! @3 t# G
if(pMatrix)
) k$ P0 w9 a- s1 n# ~; o. D
{
2 B: a( J! x. ?, y7 i2 `
if(pMatrix->ArrayLen!=k) //重置矩阵的大小
4 {: \$ g/ [6 r/ v( _6 f
{
) p @+ V# Y- g c
pa=new double[k];
/ k3 _( ?$ m3 C# d) Z, _4 R
if(!pa)
7 U, A% ~- V* T$ e
{
( v) r% u/ e7 e8 k
DeleteKey(keyname,sizeof(luVOID),Matrix,DelMatrix,1); //将矩阵对象放回缓冲区
" a$ X2 p j' A6 D; j( X5 ~( H6 e
return NULL;
( k/ `6 i- [& y
}
3 U% O7 I- ]6 X
delete[] pMatrix->Array;
! J) L: O" }, ^7 C/ y% o9 D# G2 g
pMatrix->Array=pa;
4 Q- E7 K2 ^1 i& q! n
}
9 T8 P7 ~& |- w1 T# x
}
9 C2 x$ K4 X# j* L L
else
) G; |0 t3 H$ p% ^
{
) O! \& P# t1 o- X* X& c. W6 `
pMatrix=new myMatrix; //创建矩阵对象
" E) i2 O( N8 D8 }" @
if(!pMatrix) return NULL;
) h% S8 _( R; ~- e) y$ H, F6 O! d
pMatrix->Array=new double[k];
0 v: _5 x7 d- H: K
if(!pMatrix->Array)
7 o8 y: P. D4 _% S5 S0 R
{
$ s8 E1 B7 B" z4 O, C O% a
delete pMatrix;
( R: Z9 B5 D' C$ {! Z6 ^
return NULL;
7 F* G% Y1 x; }1 U
}
/ g6 h+ Z; P- _0 A! [" l& d
if(InsertKey((char *)&pMatrix,-1,Matrix,pMatrix,DelMatrix,NULL,0,NowKey)) //将矩阵对象注册到Lu
$ |9 b( |# T: X1 `& j- G) M6 [2 j
{
& q0 p4 I9 ]. @; z8 i
delete pMatrix;
9 U1 v0 J% l$ a5 ~" y/ T
return NULL;
( T( q: \. s2 b9 v/ w
}
1 a* a% |5 {* N$ g& Q& q) G
}
3 W$ Y2 Y& ]0 d, M; W: ?
pMatrix->ArrayLen=k; pMatrix->Dim[0]=m; pMatrix->Dim[1]=n;
% j2 N' o, x6 n$ T5 Z- T2 ^
return pMatrix;
* o4 j: c( c. H% v Y6 U6 x* T
}
' x# Y" S% {* |
LuData _stdcall OpMatrix(luINT mm,LuData *xx,void *hFor,int theOperator) //运算符重载函数,用于LockKey函数
. ?7 R! Q3 A: v; o4 L: D
{
1 M+ f9 D. m. ^) W' F$ Z
LuData a;
. B# E. c, \5 p) U, \( `. K
myMatrix *pMatrix1,*pMatrix2,*pMatrix3;
; m$ g3 y9 |8 J
luVOID i,j,k,m,n,u,v;
r/ F# @( T3 n( K0 H* q8 ^+ F
double *pa,*pb,*pc;
) I/ o9 x! _% f2 k/ y' s# a
luMessage pMessage;
# Z: d, c& S: I: r" h
wchar_t wchNum[32];
, u; g4 ]! W3 R- p
char chNum[32];
: E" P# |2 Q- x O
a.BType=luStaData_nil; a.VType=luStaData_nil; a.x=0;
`- x7 {: c7 z# }) ~& s
switch(theOperator)
/ H# B$ _1 B% g2 v6 M
{
/ W1 E* b* h, U
case 2: //重载运算符*
4 \+ _; v8 h o2 @
pMatrix1=(myMatrix *)SearchKey((char *)&(xx->x),sizeof(luVOID),Matrix);
: b7 g# f$ Q/ ~5 Z Z
pMatrix2=(myMatrix *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),Matrix);
' P* K: p: B+ K' ]8 u
if(!pMatrix1 || !pMatrix2) break; //对象句柄无效,不是矩阵
9 p- _$ w# Y) \; R1 i( p5 a6 d
if(pMatrix1->Dim[1]!=pMatrix2->Dim[0]) break; //维数不匹配
+ n. ] _ z1 a" ?
pMatrix3=NewMatrix(pMatrix1->Dim[0],pMatrix2->Dim[1]); //生成新矩阵
7 X. \. k) U5 z( h- k! B
if(!pMatrix3) break;
9 Z3 R* B! R( ^9 _& U, S: G
pa=pMatrix1->Array; pb=pMatrix2->Array; pc=pMatrix3->Array;
9 o) w# G' y, N' r9 ?
m=pMatrix1->Dim[0]; n=pMatrix1->Dim[1]; k=pMatrix2->Dim[1];
4 p- v8 s, K) u2 k* c& x# ]8 c4 N5 S
for(i=0; i<m; i++) //矩阵乘
& _. \ f2 P3 K- @- h' t0 K8 L$ t' a
{
0 l$ x9 |4 B; b; O$ d" `# C9 R0 j5 t0 \2 P I
for(j=0; j<k; j++)
3 a5 R. ]! g# k& L
{
9 @) ?+ C* ^7 z) Z) s
u=i*k+j; pc[u]=0.0;
" G: g4 v8 |( F, N
for (v=0; v<n; v++)
' R# i% [" a: u# r5 H
{
; x. J. \/ }* Q
pc[u]=pc[u]+pa[i*n+v]*pb[v*k+j];
. s% t0 t+ l. Q$ @& U# p
}
8 O, {7 j2 n4 s1 t7 x+ y- ~
}
+ l9 H2 `5 n# I: V1 t' U; `( I
}
# N3 ~- L4 n# f- _
FunReObj(hFor); //告诉Lu,返回一个动态对象
6 C, |. o- g3 x% P+ z4 c
a.BType=Matrix; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pMatrix3;
3 B" c: c; ^) Z, {& j* }
break;
0 G6 b$ k* m, I4 m; @! h; k
case 25: //重载运算符.*
! U. W8 W" k0 X0 W
pMatrix1=(myMatrix *)SearchKey((char *)&(xx->x),sizeof(luVOID),Matrix);
3 Y7 q; L% n* w; p2 L) l& X8 i+ l
pMatrix2=(myMatrix *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),Matrix);
; |. { Y, X& D! X# t
if(!pMatrix1 || !pMatrix2) break; //对象句柄无效,不是矩阵
3 z1 J: R/ x4 \: j- _" G3 T
if(pMatrix1->Dim[0]!=pMatrix2->Dim[0] || pMatrix1->Dim[1]!=pMatrix2->Dim[1]) break; //维数不相同
" [3 K* f9 s3 m' A) E
pMatrix3=NewMatrix(pMatrix1->Dim[0],pMatrix1->Dim[1]); //生成新矩阵
$ T- V+ \9 u& Y# I9 a8 w1 j; ~* g
if(!pMatrix3) break;
) N) S0 G7 u! K1 `& @3 B4 _- F9 Q
for(i=0;i<pMatrix1->ArrayLen;i++) pMatrix3->Array[i]=pMatrix1->Array[i]*pMatrix2->Array[i]; //矩阵点乘
M' z1 j a L; j
FunReObj(hFor); //告诉Lu,返回一个动态对象
4 z" {0 M" O, v" G7 B3 x& u
a.BType=Matrix; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pMatrix3;
/ p/ S9 G# _( a9 X- n
break;
5 l, ^" ^; B. k9 j
case 46: //重载函数new
: {9 x( }) O9 B
if(mm<2) break;
" `1 O+ `3 _2 ^1 U5 N$ c# @% K2 z E8 K/ @
if((xx+1)->x<1 || (xx+2)->x<1 || (xx+1)->BType!=luStaData_int64 || (xx+2)->BType!=luStaData_int64) break;
2 C& T! h+ R" ?
pMatrix3=NewMatrix((luVOID)(xx+1)->x,(luVOID)(xx+2)->x);//生成新矩阵
7 Q) F" `# i a5 z' V' ?! s
if(!pMatrix3) break;
$ X$ H$ u; i# d( Y. E. x0 P' H/ f
for(j=0,i=3;i<=mm;i++,j++) //赋初值
% H( e" ~# F% V w; f; x- k
{
) y b$ \% d8 K1 X; Y+ L
if(j>=pMatrix3->ArrayLen) break;
* H6 D1 H. J1 ?7 H3 ^# l9 e
if((xx+i)->BType!=luStaData_double) break; //只接受实数参数
! N4 b4 _ S p6 z
pMatrix3->Array[j]=*(double *)&((xx+i)->x);
7 x w' c3 X- o1 @* g, k9 K
}
, d' t+ i( ?7 e5 T- N* `" d& ?
FunReObj(hFor); //告诉Lu,返回一个动态对象
6 g+ O. `( J+ n
a.BType=Matrix; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pMatrix3;
' J' {0 x% r/ B
break;
% a8 K) |' H6 ~6 v4 U, g& z0 @! {
case 49: //重载函数o
$ H6 Y4 ]; ?4 O6 d0 h) @6 |+ }
pMessage=(luMessage)SearchKey("\0\0\0\0",sizeof(luVOID),luPubKey_User);
" x$ H% q8 I8 G
if(!pMessage) break;
5 N* M8 T, M- G' |9 y# A% Q/ ]8 b
pMatrix1=(myMatrix *)SearchKey((char *)&(xx->x),sizeof(luVOID),Matrix);
, m5 s, C3 T3 P5 T0 F3 D2 T
if(!pMatrix1) break; //对象句柄无效,不是矩阵
; g3 ]: T* }( L7 p0 f$ Z# b! p
pa=pMatrix1->Array;
# ~+ E! X. m* ?
m=pMatrix1->Dim[0]; n=pMatrix1->Dim[1]; k=0;
. u# x- [. g7 I: }' f9 r) K6 l
for(i=0; i<m; i++) //输出矩阵
: T. G& T) N5 T1 M
{
6 p3 ]. b0 _1 Q& T/ b7 J8 M
pMessage(L"\r\n"); k+=2;
3 Q( {0 ]0 Y0 }5 o9 H$ P
for(j=0; j<n; j++)
% b Q& K5 c: s: ?/ S
{
( n9 K& U! }# Y: E/ J8 a) A
_gcvt_s(chNum,pa[i*n+j],16);
6 F" l9 {% h" H6 p$ K3 p
for(u=0;chNum[u];u++) {wchNum[u]=chNum[u]; k++;}
2 E& i: J* [% Z: P* Q
wchNum[u]='\0';
* q) ]2 [$ s0 k+ ~' R2 x. x
pMessage(wchNum); pMessage(L" "); k+=2;
' a! I A# U$ |" ~
}
+ K8 u4 A( l% i. ]% `1 |
}
a' U @$ N' u: i1 }1 D7 A0 W$ W
pMessage(L"\r\n"); k+=2;
$ U% `9 c8 U& T5 n2 O
a.BType=luStaData_int64; a.VType=luStaData_int64; a.x=k; //按函数o的要求,返回输出的字符总数
- C" j2 m, n: ]
break;
5 Q5 W6 ?/ M s( x: u" G% W" c) {
default:
# J4 e. q( P% I- N6 @
break;
. w) q# @, b) r0 D
}
0 E; }2 t! l+ `5 o; |+ `# D- l
return a;
6 w* E- A; ^/ o3 _$ U9 G' y
}
1 t B6 |! a2 u3 `, u: ^
void main(void)
! e H n7 \# q& f, W/ r
{
& }/ j! z x# z: X% h7 k. t/ ?
void *hFor; //表达式句柄
. F5 M4 H' N# s- c
luINT nPara; //存放表达式的自变量个数
( N. s) e: t$ N7 `0 S S9 L% Z. ?
LuData *pPara; //存放输入自变量的数组指针
7 `% ~% H" J7 W4 W: ^# l e
luINT ErrBegin,ErrEnd; //表达式编译出错的初始位置和结束位置
D1 ]( D* N* \: [* K
int ErrCode; //错误代码
9 k) m1 ~5 z0 }7 M
void *v;
$ q9 u" V( |3 d! L
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.]}";//字符串表达式,矩阵乘
/ D O) f$ ?4 d2 i. ^/ n1 d2 H# t1 k1 K
//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.]}";//字符串表达式,矩阵点乘
% Q9 J0 N/ X; {; ^, r6 u
LuData Val;
( z* g. t/ @3 T/ i* A
if(!InitLu()) return; //初始化Lu
% e4 v& g, t1 x5 u. S' z
while(LockKey(Matrix,DelMatrix,OpMatrix)){Matrix--;} //锁定一个键,用于存储矩阵扩展类型
3 x J3 W9 B* v6 E4 W
7 J2 t% H. ?* `3 b% T) B
Val.BType=luStaData_int64; Val.VType=luStaData_int64; Val.x=Matrix; //定义整数常量
# c& J& k; t3 U) L6 b* h9 t6 a
SetConst(L"matrix",&Val); //设置整数常量
7 y/ I$ q7 l' P; k& r
InsertKey("\0\0\0\0",4,luPubKey_User,LuMessage,NULL,NULL,1,v); //使Lu运行时可输出函数信息
, d( t) d' A; g6 E
wcout.imbue(locale("chs")); //设置输出的locale为中文
5 j- A3 P5 ?, U5 c; b- J. e
) a* _% ~6 D6 h1 z
ErrCode=LuCom(ForStr,0,0,0,hFor,nPara,pPara,ErrBegin,ErrEnd); //编译表达式
) e1 | A6 B7 i& q- Y7 F- O
if(ErrCode)
0 f/ S0 I- d: m: \- b# d
{
" J; i8 ?/ J; M- \1 f
wcout<<L"表达式有错误!错误代码:"<<ErrCode<<endl;
) M4 v3 \2 T" e% n1 m
}
9 q- `. H$ Q, I: Z: c) Z
else
4 R- z9 W) C: o; g; \
{
/ _0 p) l- _8 S, g' g
LuCal(hFor,pPara); //计算表达式的值
, b7 l- u2 ~7 L6 j Q
}
2 f \6 P, U! h2 P2 |
LockKey(Matrix,NULL,OpMatrix);//解锁键Matrix,本例中,该函数可以不用
; D$ |* }; q1 F; i# Z
FreeLu(); //释放Lu
: K6 p. y2 y& s1 L) g# P1 G
}
复制代码
习题:
- P4 i; J7 `9 p, Y
& ]4 ?4 |0 U; V, }- J+ \" p; ~
(1)自定义矩阵的加、减、左除、右除、点左除等运算,自编测试字符串代码,重新编译运行程序,观察计算结果。
% v# l5 t$ ^9 _; \$ m I
$ `% B9 F; _& N$ g
(2)小矩阵乘效率测试。编译运行以下Lu字符串代码:
main(:a,b,c,d,t,i)=
5 b$ `8 |. B) J) o1 @3 p; R
a=new[matrix,2,2: 1.,2.,2.,1.],
" _7 w6 U+ J' P& N- G3 x2 D
b=new[matrix,2,2: 2.,1.,1.,2.],
6 l- r5 s! b. c% L0 F
c=new[matrix,2,2: 2/3.,-1/3.,-1/3.,2/3.],
: o i4 k& B- S
t=clock(),
# E& a+ U* q, [% }
d=a*b, i=0, while{i<1000000, d=d*c*b, i++},
& U% \& o9 B3 r3 ~6 Z4 s
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.
6 b$ n8 v4 `* z0 n
5. 4.
* y5 d2 o7 a5 \" e0 i* q; D
time=0.797 seconds.
. ?' I* q) G8 v( q
请按任意键继续. . .
复制代码
Matlab 2009a 代码:
a=[1.,2.;2.,1.];
+ l4 n9 i: r9 J5 y4 ]
b=[2.,1.;1.,2.];
' c! ]$ k) e2 @. d- e' e A) T
c=[2/3.,-1/3.;-1/3.,2/3.];
- Z6 }5 A; l& c6 S% B+ m
tic,
% _2 P1 S( ] P/ l
d=a*b;
. M$ p: m" u+ l0 ]! X
for i=1:1000000
* F4 j- L; q5 {5 b
d=d*c*b;
# |7 Y5 ]% v% a
end
& g5 Z7 g) o: ~$ ^* k/ p
d,
" @1 n! g, y7 ?$ _% q1 n4 _) T
toc
复制代码
结果:
d =
0 I% G1 q+ y4 x) ~
4 5
( g; |! r1 c. ?5 T4 ]
5 4
3 `# L6 T, ?# q8 u
Elapsed time is 2.903034 seconds.
复制代码
本例矩阵乘效率测试,Lu的速度超过了Matlab,主要在于Lu有更高的动态对象管理效率。
! H" D0 |* x( b2 q! n8 ~. J
7 b; q y& h8 T8 m- K+ q' H
由以上可以看出,自定义数据类型和系统内置类型有近乎相同的效率。
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5