数学建模社区-数学中国
标题:
在Lu中创建自定义数据类型,小矩阵乘效率测试
[打印本页]
作者:
forcal
时间:
2011-10-24 18:54
标题:
在Lu中创建自定义数据类型,小矩阵乘效率测试
本例中,我们将自定义矩阵(matrix)类型,基本类型和扩展类型均为matrix(标识矩阵)。
. r( w9 B. U3 B' h3 y5 V8 Q" w% \
% N/ R1 n0 K" t* s5 @
基本要点:
9 B' [. X; a$ R
8 d7 _5 e6 @8 x" E" _, @
(1)编写生成矩阵(matrix)的函数NewMatrix和销毁矩阵的函数DelMatrix。
) @/ j9 K, k/ V4 R
4 b8 o3 o) ^7 l+ [
(2)为自定义类型matrix编写运算符重载函数OpMatrix。
+ s/ Q4 C/ C/ Y6 P3 o8 C; v
4 g* ]7 { o* f" I# M# V( K2 Z7 x
(3)用函数LockKey将重载函数OpMatrix注册到Lu,锁定的键的类型即为matrix,要注册为常量,以便于使用。
8 u: D% Q/ S5 g+ J" I: U
2 F0 p/ t8 _+ C; h! L
(4)为自定义类型matrix编写其他操作函数(本例未提供)。
; Q. ~! {; v* ^* j
4 a! G' r5 _" u. N
(5)用函数LockKey解锁键matrix(本例中,程序退出时会自动解锁,故可以不用)。
#include <windows.h>
9 M7 _$ h0 a) T) z% v$ [6 j
#include <iostream>
- n3 q/ Z$ S: W: C
#include <math.h>
5 w1 L; F1 ~6 g7 \0 S1 H! b9 u
#include "lu32.h"
# g6 H* Z! M. N3 }. O* O
#pragma comment( lib, "lu32.lib" )
1 a" X1 y( H- u9 m' c
using namespace std;
( d% b, m% I, l2 M
//自定义矩阵
K" Y/ X: K5 k/ B ~8 Q( a4 b" x' J
class myMatrix
2 H }* ?: p! I! B# m
{
$ | _" p+ m9 N" ?8 f- p
public:
1 c/ ?+ z0 a+ z5 y$ R9 a: L' P
double *Array; //数据缓冲区
7 F: }* ?- _5 \- }; p! k7 a% Z( U
luVOID ArrayLen; //数据缓冲区长度
& N/ J, r' v* |3 [7 p5 y5 A
luVOID Dim[2]; //矩阵维数
* R- b) y3 h: l* g
myMatrix(){Array=NULL; ArrayLen=0; Dim[0]=0; Dim[1]=0;}
+ O7 h z' ~" g
~myMatrix()
- [0 j6 P, V& ^9 k
{
1 ]# u, f" k$ m. F( M8 n+ B
if(Array) delete[] Array;
" l' D% T- P: @. n a9 A7 T+ H3 p
}
# j# z3 \! I! p9 w) U9 ^
};
$ P9 q9 j) B2 ~8 d1 Y
luKEY Matrix=-1000; //标识矩阵类型,最终的Matrix由LockKey决定
6 D$ @0 }& W6 w. |$ z+ q
void _stdcall LuMessage(wchar_t *pch)//输出动态库信息,该函数注册到Lu,由Lu二级函数调用
- X5 k7 [! }$ x% r. r* J. i
{
# H3 {# X4 N, e
wcout<<pch;
) _0 x& G; ~$ y+ r* w* `
}
+ g0 G& E( O! z* c9 ]( W
void _stdcall DelMatrix(void *me) //用于LockKey函数及InsertKey函数,使Lu能自动销毁myMatrix对象
. F8 ]$ T2 |) s: k& A
{
* p k. X- H, i6 c0 @
delete (myMatrix *)me;
3 f- t) W5 S6 J) g3 C3 c8 b
}
3 [/ g, q! w* E6 j1 D: x7 Q
myMatrix * _stdcall NewMatrix(luVOID m,luVOID n) //生成一个myMatrix对象
$ [ u) \9 k8 y p% N
{
# K5 q/ J/ O5 y
myMatrix *pMatrix;
, b! P/ Y# Z+ P9 b% S# v
luVOID k;
4 r% t. t* O( J+ Z; n! s# z1 j7 f
double *pa;
: P: z% T9 ?' S: Z9 o( d2 M# C+ U! W
char keyname[sizeof(luVOID)];
% G9 W0 s4 T$ e% r
void *NowKey;
# g5 F: O3 _6 x; e
k=m*n;
1 l, O: J' ^$ W& Q7 K3 O
pMatrix=(myMatrix *)GetBufObj(Matrix,keyname);//先尝试从缓冲区中获取一个矩阵对象
' `0 B/ i/ _7 f7 G7 m+ b
if(pMatrix)
3 Y) `+ @% h7 d9 C z2 n
{
9 b5 U, y, P x* q4 I
if(pMatrix->ArrayLen!=k) //重置矩阵的大小
7 d5 U+ h; y4 a& L# j2 R4 V* o
{
( |- ?( P( Y% e5 V) G& x
pa=new double[k];
9 i( K/ b& C) K5 l. h
if(!pa)
O' ?8 E- l6 Z+ }, E) Q
{
$ F( e# e5 a0 W/ u
DeleteKey(keyname,sizeof(luVOID),Matrix,DelMatrix,1); //将矩阵对象放回缓冲区
& o# h; E3 S$ B- b7 Y" j* V$ Z
return NULL;
' ^6 s* j' u2 j v* }
}
* W) Z n/ m2 E4 G* _3 B
delete[] pMatrix->Array;
; f4 ?0 y& P5 F( X9 h3 |
pMatrix->Array=pa;
' `1 T& M; s" R
}
! o" f1 d& F, H5 l7 [+ h3 Y
}
/ S8 w$ k; @' n
else
$ A) m5 n" a8 [& w1 x6 n* V
{
V8 \% k5 c; |0 W$ X' U- }# Z
pMatrix=new myMatrix; //创建矩阵对象
, `( q- [3 @& `2 m: K4 R' a* t
if(!pMatrix) return NULL;
( Z7 b8 h! r8 Q# v1 c. P# d* N a! a
pMatrix->Array=new double[k];
, H3 E% S* B; e5 B; r
if(!pMatrix->Array)
( ^7 Y+ Q- e" L! Y
{
- k5 K- N0 r( q2 k
delete pMatrix;
3 o$ e* ]# z: N9 u9 j
return NULL;
' T w. G; n9 w
}
/ s% d2 y l* p; B9 i; a0 e
if(InsertKey((char *)&pMatrix,-1,Matrix,pMatrix,DelMatrix,NULL,0,NowKey)) //将矩阵对象注册到Lu
( o( b9 b1 S# s- w! E* J
{
5 U+ D7 u- C) a3 j c: ?4 J. z
delete pMatrix;
$ G5 p* j3 Q; _! |$ I* K7 T
return NULL;
1 W" F& w4 \7 g7 d& a( J
}
8 ~- U. _! o) a$ I
}
% Q1 ^& P- a& P+ P: r4 d
pMatrix->ArrayLen=k; pMatrix->Dim[0]=m; pMatrix->Dim[1]=n;
. A- R4 z6 f! ^0 w5 n3 \ w0 [2 F
return pMatrix;
; z: y# R7 H6 D) E: u( b
}
$ R" k6 A- ~* _! O9 M6 a' [
LuData _stdcall OpMatrix(luINT mm,LuData *xx,void *hFor,int theOperator) //运算符重载函数,用于LockKey函数
$ L5 i+ l5 y, f1 ]
{
) X% G% D; T/ A, ^
LuData a;
7 ]9 k! _/ s- Y" B% l
myMatrix *pMatrix1,*pMatrix2,*pMatrix3;
7 Y% }4 x1 G0 x: ^0 U* g% \
luVOID i,j,k,m,n,u,v;
( Z! }, O: u$ m. x2 H! @
double *pa,*pb,*pc;
1 p+ z4 y7 H5 O4 p
luMessage pMessage;
p) ^0 m' r! |6 [9 }% J5 V6 l
wchar_t wchNum[32];
' q: O1 Z: L2 A/ m* k" ?, X
char chNum[32];
8 v. b: K' Q, B) e# J2 B$ G
a.BType=luStaData_nil; a.VType=luStaData_nil; a.x=0;
1 |1 t1 A( ^/ V* E& A" W
switch(theOperator)
1 o9 N5 b1 ]8 c4 m/ W& r8 [# I
{
0 p, L1 ~+ Q; |( A; Z
case 2: //重载运算符*
1 Z/ Y e' \+ @6 L8 ]: h
pMatrix1=(myMatrix *)SearchKey((char *)&(xx->x),sizeof(luVOID),Matrix);
_2 t7 S: c7 b# m' K5 a
pMatrix2=(myMatrix *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),Matrix);
! m- t- d2 P+ f: d" M( J A
if(!pMatrix1 || !pMatrix2) break; //对象句柄无效,不是矩阵
& F- B, Y# H4 T0 q, q( R5 V
if(pMatrix1->Dim[1]!=pMatrix2->Dim[0]) break; //维数不匹配
( d6 z0 [% d: ]5 {& ?8 J( v
pMatrix3=NewMatrix(pMatrix1->Dim[0],pMatrix2->Dim[1]); //生成新矩阵
- {3 f. P c) M+ [' S6 S
if(!pMatrix3) break;
: [% p+ K' J' C& D( \) D& Z5 `
pa=pMatrix1->Array; pb=pMatrix2->Array; pc=pMatrix3->Array;
" R Q6 T8 J3 |4 u0 j, L
m=pMatrix1->Dim[0]; n=pMatrix1->Dim[1]; k=pMatrix2->Dim[1];
2 c5 k( S; M' p# T1 B, a! O; b
for(i=0; i<m; i++) //矩阵乘
$ A& Q; `8 \0 }/ M- v. S
{
" h; B9 q5 c; G; m- f e0 l0 z- w! r
for(j=0; j<k; j++)
% I# O3 K1 }1 e& n. o6 g9 V
{
* _5 d5 H' n- D; x3 ]0 p2 h
u=i*k+j; pc[u]=0.0;
$ o$ q3 G$ i ?" f4 t
for (v=0; v<n; v++)
; m) Z- F$ l/ T
{
7 [9 @% o& d3 j, s, S* ~
pc[u]=pc[u]+pa[i*n+v]*pb[v*k+j];
# N: D' a% O5 _ l$ K
}
5 D3 V. m; E$ z
}
1 N1 p5 W' u: e6 z5 R! d; D4 C( Y
}
. F9 R) L- D3 R3 Z
FunReObj(hFor); //告诉Lu,返回一个动态对象
2 J& j. o* k1 m7 u9 n' {3 j. x k
a.BType=Matrix; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pMatrix3;
% \0 v8 c( T, B( J6 \% k# ~
break;
9 f1 ~, l+ P) K# v
case 25: //重载运算符.*
! V3 M- }- N) _( ]5 ]% |8 j9 Z
pMatrix1=(myMatrix *)SearchKey((char *)&(xx->x),sizeof(luVOID),Matrix);
' c& z& o- b1 s% r) l+ [
pMatrix2=(myMatrix *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),Matrix);
$ c! w& f4 A3 u: _
if(!pMatrix1 || !pMatrix2) break; //对象句柄无效,不是矩阵
* X+ E( s O* r% l
if(pMatrix1->Dim[0]!=pMatrix2->Dim[0] || pMatrix1->Dim[1]!=pMatrix2->Dim[1]) break; //维数不相同
6 g/ I' k: w9 Q5 P8 _5 g+ V# x% t
pMatrix3=NewMatrix(pMatrix1->Dim[0],pMatrix1->Dim[1]); //生成新矩阵
) U" a+ b: J* _/ C+ r+ z* A
if(!pMatrix3) break;
& I( R; h$ A! ^: f. l
for(i=0;i<pMatrix1->ArrayLen;i++) pMatrix3->Array[i]=pMatrix1->Array[i]*pMatrix2->Array[i]; //矩阵点乘
5 ~* p$ `3 C: S2 o8 i% R
FunReObj(hFor); //告诉Lu,返回一个动态对象
: C5 c: R: d7 b8 r
a.BType=Matrix; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pMatrix3;
0 L% P& l2 H t: P' @9 I0 _( w8 y5 C
break;
1 h' N& X. r& B& m
case 46: //重载函数new
7 e4 O; t8 d3 S7 ]
if(mm<2) break;
! [5 H/ r1 [9 F: N$ F0 ~
if((xx+1)->x<1 || (xx+2)->x<1 || (xx+1)->BType!=luStaData_int64 || (xx+2)->BType!=luStaData_int64) break;
" @1 w& ]8 ~( U7 U( ^
pMatrix3=NewMatrix((luVOID)(xx+1)->x,(luVOID)(xx+2)->x);//生成新矩阵
* r5 I2 m# q0 r, o& _9 H
if(!pMatrix3) break;
2 D1 G3 H( |% o& d
for(j=0,i=3;i<=mm;i++,j++) //赋初值
+ g5 q2 Z* v9 _: D, @6 \' x* u g0 y
{
' z! B6 x2 j& W7 U
if(j>=pMatrix3->ArrayLen) break;
. p( V% [& _% ~" O1 [4 Z- k
if((xx+i)->BType!=luStaData_double) break; //只接受实数参数
/ c0 f5 `* C+ t2 ?7 t6 N# g8 \
pMatrix3->Array[j]=*(double *)&((xx+i)->x);
Y. ]! Y& }+ k
}
7 c/ k0 b# o9 c" Z$ p
FunReObj(hFor); //告诉Lu,返回一个动态对象
3 n L9 c# _1 r$ R+ q& q3 d4 @% l
a.BType=Matrix; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pMatrix3;
$ {. t6 |2 `1 C
break;
9 n, h, ]$ }7 w: Y x
case 49: //重载函数o
2 p5 Z- w1 p, h5 o- p
pMessage=(luMessage)SearchKey("\0\0\0\0",sizeof(luVOID),luPubKey_User);
$ j# t3 y: z$ s% i
if(!pMessage) break;
4 u* a: f$ r) r7 H7 Q, I* @+ p
pMatrix1=(myMatrix *)SearchKey((char *)&(xx->x),sizeof(luVOID),Matrix);
" F! Y( M0 C2 s9 G( O
if(!pMatrix1) break; //对象句柄无效,不是矩阵
' H0 W# s: [1 Z" O; O8 _, R5 b% x
pa=pMatrix1->Array;
4 G& s( ?1 o0 m- M* U
m=pMatrix1->Dim[0]; n=pMatrix1->Dim[1]; k=0;
+ @$ ?) S& M* R; [0 o8 C( y
for(i=0; i<m; i++) //输出矩阵
. o5 Y& N( x4 G' k3 [. s
{
2 Z" K: b8 c/ f j' p1 A
pMessage(L"\r\n"); k+=2;
# _% X& k" m0 Z0 z- E! \
for(j=0; j<n; j++)
8 g' B0 Q, L) s& Y( r$ d* M5 y
{
2 j9 @1 |5 _4 ~ b! [& Z/ l0 p
_gcvt_s(chNum,pa[i*n+j],16);
- k3 E% U* S2 r' o( _
for(u=0;chNum[u];u++) {wchNum[u]=chNum[u]; k++;}
w6 i3 k. I3 ?: o! j# a2 M
wchNum[u]='\0';
5 G! F z6 p3 K5 C& `/ ~
pMessage(wchNum); pMessage(L" "); k+=2;
! j }1 w" Y4 O2 k( L( Z1 K% H
}
. \$ i6 R$ p8 M$ }! A' E1 Y4 S9 `
}
- {8 ]2 ]& x t% F
pMessage(L"\r\n"); k+=2;
( z7 ?3 X: B0 D) K/ r- j
a.BType=luStaData_int64; a.VType=luStaData_int64; a.x=k; //按函数o的要求,返回输出的字符总数
9 O- K' u! ~! `9 J
break;
9 t8 k- t% O6 O8 X( K
default:
5 \% p2 Y! M4 d- Y) d) c4 l. K
break;
, k* k# Y2 G, ~
}
/ |9 Q' d5 V, ]4 M) M+ {
return a;
9 o4 d1 m7 ?/ R5 V
}
3 M! s8 N# |7 m
void main(void)
/ \2 F# b9 G6 K: W8 J' Q
{
9 J. N& g# P: d; g4 k& j* v
void *hFor; //表达式句柄
" |6 `) ?" [, R* Z$ u
luINT nPara; //存放表达式的自变量个数
7 y1 d) e- _2 Y9 @1 }7 T
LuData *pPara; //存放输入自变量的数组指针
1 c* ?- ^: h% p: R
luINT ErrBegin,ErrEnd; //表达式编译出错的初始位置和结束位置
' N+ J4 R, }2 Z W9 g
int ErrCode; //错误代码
( g1 U% d6 X& r# A
void *v;
+ b. {9 K0 ~, M1 f+ w" M
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.]}";//字符串表达式,矩阵乘
- T: N' E1 l7 ~" i9 l. _
//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.]}";//字符串表达式,矩阵点乘
" M' a% |9 x! p' S8 y
LuData Val;
3 t& z! h: ?9 I% H6 a" b/ ]
if(!InitLu()) return; //初始化Lu
( a" {$ b: R4 i; i; L
while(LockKey(Matrix,DelMatrix,OpMatrix)){Matrix--;} //锁定一个键,用于存储矩阵扩展类型
: J& b/ R! `( U I. F1 o- y
( ~8 i7 {% N+ z) C. L0 o
Val.BType=luStaData_int64; Val.VType=luStaData_int64; Val.x=Matrix; //定义整数常量
* {2 Y T# b& p5 {8 l
SetConst(L"matrix",&Val); //设置整数常量
6 U/ d, t1 `9 _4 s0 G* [
InsertKey("\0\0\0\0",4,luPubKey_User,LuMessage,NULL,NULL,1,v); //使Lu运行时可输出函数信息
0 M! \- [7 j! D1 t
wcout.imbue(locale("chs")); //设置输出的locale为中文
( J; B T- J. m
" l) l6 `7 {) ~8 t2 \: K8 W
ErrCode=LuCom(ForStr,0,0,0,hFor,nPara,pPara,ErrBegin,ErrEnd); //编译表达式
4 L0 W/ B+ n; }
if(ErrCode)
$ _( e8 X5 z7 J" o- {
{
: T4 X- n0 A' g
wcout<<L"表达式有错误!错误代码:"<<ErrCode<<endl;
) F" ? O$ r5 v" G0 p
}
% j, p* G9 y5 \7 n" V9 D* j$ H9 ~
else
n$ ]+ W) L* i! j7 K$ n2 e x. i
{
! u, D2 R) `3 @" I9 d1 Z
LuCal(hFor,pPara); //计算表达式的值
9 X- `: F9 @2 ?* @7 p. S- ~
}
& w* y) y7 \( O! d7 w- h5 ~, c. u
LockKey(Matrix,NULL,OpMatrix);//解锁键Matrix,本例中,该函数可以不用
4 ~. u$ z) C; @1 `( u
FreeLu(); //释放Lu
" \) W) C/ Z3 \4 }9 }
}
复制代码
习题:
- M# F0 j! d; O; g
2 w0 @8 T; p- D
(1)自定义矩阵的加、减、左除、右除、点左除等运算,自编测试字符串代码,重新编译运行程序,观察计算结果。
. l: `2 S; p9 k1 b, v
& F8 ^( |$ R4 ]$ ^+ H5 l
(2)小矩阵乘效率测试。编译运行以下Lu字符串代码:
main(:a,b,c,d,t,i)=
: B$ a( o1 u. W/ `2 `# Q# o
a=new[matrix,2,2: 1.,2.,2.,1.],
, Z" g) A% W2 m) G6 E5 Y# M
b=new[matrix,2,2: 2.,1.,1.,2.],
3 N+ ^( A% A8 u; j
c=new[matrix,2,2: 2/3.,-1/3.,-1/3.,2/3.],
" N+ f* e6 C8 K4 K f1 d+ L# D
t=clock(),
* O3 D7 |( k4 R: X- b
d=a*b, i=0, while{i<1000000, d=d*c*b, i++},
9 e `5 }# h- P
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.
! K7 e- ~! X! e2 U
5. 4.
* e% ~4 {3 U% L. j0 T1 u
time=0.797 seconds.
9 w+ Q+ Y3 l; c4 d
请按任意键继续. . .
复制代码
Matlab 2009a 代码:
a=[1.,2.;2.,1.];
0 X z7 d: r9 r
b=[2.,1.;1.,2.];
1 A: b) U; @ A5 F8 j/ o
c=[2/3.,-1/3.;-1/3.,2/3.];
7 `8 @! @2 ?) k+ Q/ | f) `
tic,
, M* {7 T. A2 m2 Q+ E9 H! }2 u! q% e
d=a*b;
3 B. q7 N) n9 w2 i2 X4 _0 R
for i=1:1000000
6 t- O7 i9 U$ E
d=d*c*b;
4 M2 a! [$ v/ [" ^9 M0 @/ V: E
end
# V2 _ i6 }0 e+ D' D( k
d,
3 j C) J. U6 @& Q8 M$ t
toc
复制代码
结果:
d =
* ~ Y4 e9 _ r$ R6 W% H6 w
4 5
4 B7 @" c. [ a/ O
5 4
$ N$ g( W' h5 Q) y
Elapsed time is 2.903034 seconds.
复制代码
本例矩阵乘效率测试,Lu的速度超过了Matlab,主要在于Lu有更高的动态对象管理效率。
$ J" P9 C6 b* L: b: R, C
. T b2 c( W! ?
由以上可以看出,自定义数据类型和系统内置类型有近乎相同的效率。
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5