数学建模社区-数学中国
标题:
在Lu中创建自定义数据类型,小矩阵乘效率测试
[打印本页]
作者:
forcal
时间:
2011-10-24 18:54
标题:
在Lu中创建自定义数据类型,小矩阵乘效率测试
本例中,我们将自定义矩阵(matrix)类型,基本类型和扩展类型均为matrix(标识矩阵)。
/ t( Z- `$ h E: K5 A
" \( J( \6 A H" `: C2 u$ g
基本要点:
" S* Q2 G7 N$ E* O
/ \; @, j: @4 K+ D R0 n+ v4 U$ I
(1)编写生成矩阵(matrix)的函数NewMatrix和销毁矩阵的函数DelMatrix。
2 J+ T9 _# t5 e( q( L- u! `2 w) \
. p2 V- i# X' w1 P8 X5 t9 k: D
(2)为自定义类型matrix编写运算符重载函数OpMatrix。
; \1 q$ d( I; C$ w
/ K" k% @, O# P$ s0 Y+ v
(3)用函数LockKey将重载函数OpMatrix注册到Lu,锁定的键的类型即为matrix,要注册为常量,以便于使用。
2 V4 ~2 i0 k/ _
$ k5 c) F. Q- S4 ^
(4)为自定义类型matrix编写其他操作函数(本例未提供)。
9 ^7 T0 S2 v5 o) f M
1 G5 @% O# _ o
(5)用函数LockKey解锁键matrix(本例中,程序退出时会自动解锁,故可以不用)。
#include <windows.h>
- U# A9 w5 h& H6 Q
#include <iostream>
( G: P2 ?' y/ N+ ~( u: }- J
#include <math.h>
/ }. D7 D* v7 v( Z
#include "lu32.h"
/ ~8 ?5 I6 m) @2 m
#pragma comment( lib, "lu32.lib" )
& q9 h( i9 m; s; l: c9 F
using namespace std;
# _4 Q. j( }9 ~
//自定义矩阵
$ I; L1 B* n1 |. u: v
class myMatrix
# e2 b. V6 W- ^( r0 x2 u
{
8 k8 V+ E) A- } {7 e; u
public:
+ W- a7 v% C; h. R) K
double *Array; //数据缓冲区
1 I5 M5 u- a+ J* z0 b$ s* [
luVOID ArrayLen; //数据缓冲区长度
A1 {% r8 ]; p" @
luVOID Dim[2]; //矩阵维数
4 |. T2 w* a" u' T8 P) I# [
myMatrix(){Array=NULL; ArrayLen=0; Dim[0]=0; Dim[1]=0;}
8 f( i! A- q# p- i/ f0 v R- E
~myMatrix()
% d0 A! H0 Q( D) d$ a0 u
{
! U# N$ D3 u7 v; m# q
if(Array) delete[] Array;
$ _. l8 H# q/ G) w' K
}
6 o, `0 L7 p, }# Z; R( y/ W
};
2 m2 a4 y n; z! Y
luKEY Matrix=-1000; //标识矩阵类型,最终的Matrix由LockKey决定
]; m* j8 G! ?* i+ L, _9 e
void _stdcall LuMessage(wchar_t *pch)//输出动态库信息,该函数注册到Lu,由Lu二级函数调用
V0 u4 w7 x( U) g2 F
{
! u, X/ v8 U" j( h' W8 y
wcout<<pch;
( }( q4 C3 [% ~7 r
}
/ X0 k6 A# T7 F' P5 w
void _stdcall DelMatrix(void *me) //用于LockKey函数及InsertKey函数,使Lu能自动销毁myMatrix对象
4 V7 w4 x+ K0 i0 ?& E+ O
{
9 O4 o4 f% N3 F, B$ q* S
delete (myMatrix *)me;
% e4 G2 \8 j5 X. H! x% C3 L1 i- e
}
! P4 L; S+ M. j
myMatrix * _stdcall NewMatrix(luVOID m,luVOID n) //生成一个myMatrix对象
& t" B2 k% v; N2 T: C4 E. `# W
{
! p0 M. E, l6 H' ]0 Q
myMatrix *pMatrix;
, p6 j% k! V& j( ~6 x0 Z
luVOID k;
& Z e! N: q9 F) H; t+ F8 N% E
double *pa;
" y" M4 c( ]; ]* @
char keyname[sizeof(luVOID)];
7 p# F# x# f6 u- ^ h' f* h
void *NowKey;
! J3 l; k2 [4 c& n" x3 n
k=m*n;
/ R; b+ u7 u q) f$ t
pMatrix=(myMatrix *)GetBufObj(Matrix,keyname);//先尝试从缓冲区中获取一个矩阵对象
o8 G. h L) O" Q; E
if(pMatrix)
( r' ?7 D! {# q2 m
{
$ X6 P% ]5 b7 O$ ^0 O- z
if(pMatrix->ArrayLen!=k) //重置矩阵的大小
& N; F. `; r; h. Z6 M' }2 f
{
+ m+ W& D: a7 i0 c+ k
pa=new double[k];
2 l$ N/ ?. L- o' s/ n
if(!pa)
; x% i% @" N* S* S* k
{
X/ a4 r3 l8 _& h
DeleteKey(keyname,sizeof(luVOID),Matrix,DelMatrix,1); //将矩阵对象放回缓冲区
% ~( k+ @0 Y* d$ a
return NULL;
% p5 {7 y6 d% u, |# L. b: r- i8 i
}
7 p4 i" R( f2 z, }+ X
delete[] pMatrix->Array;
5 i' [$ o: H% g
pMatrix->Array=pa;
" F5 A9 }$ M) ~9 \6 E2 h7 a$ d
}
. f; z! r) g+ O* @! ~4 Y& n: o* O& _ K
}
2 y$ _( Y# F. ], {" T' U1 ]2 R: y
else
3 l' S2 u& l' l' l
{
/ M- @, \! z* V9 ?
pMatrix=new myMatrix; //创建矩阵对象
. B* n. Z! g1 ^: _# g7 u7 Q" d. v( P
if(!pMatrix) return NULL;
( V, X+ a. H3 g- L- ~ w! ^0 a. A- \
pMatrix->Array=new double[k];
0 ], s$ t7 @5 k! d1 ]- k' L. F. m
if(!pMatrix->Array)
* u1 _& `0 v. D: X0 j8 {
{
6 p' _( c0 V5 }; G& f0 Q
delete pMatrix;
! { \4 x7 a' n6 I' _ _
return NULL;
7 d3 w% S# o9 \2 p, m7 b5 e
}
/ ^8 C, o- ?! W+ J3 R0 r
if(InsertKey((char *)&pMatrix,-1,Matrix,pMatrix,DelMatrix,NULL,0,NowKey)) //将矩阵对象注册到Lu
* l b; e- Z" @% {
{
6 F- o, k9 e' H- s
delete pMatrix;
& y( K+ q3 [8 {* @
return NULL;
% c$ }: ~2 Z; h4 K, K. {; H: z
}
: P# E# B8 r I5 P; E( F
}
# x4 w) [5 B H, R3 [5 ~8 z# k
pMatrix->ArrayLen=k; pMatrix->Dim[0]=m; pMatrix->Dim[1]=n;
& I1 B/ O4 F7 h8 u3 T
return pMatrix;
$ I' Y" j' U, v" ^+ ^6 _
}
6 f. l+ N6 v8 X
LuData _stdcall OpMatrix(luINT mm,LuData *xx,void *hFor,int theOperator) //运算符重载函数,用于LockKey函数
* k) g: J2 Z J6 k
{
! ?) {( {' K, i6 z! ]& z- z5 H9 ]) t
LuData a;
: ^8 @5 F$ t. @8 f O
myMatrix *pMatrix1,*pMatrix2,*pMatrix3;
+ v" E7 R, r3 n% R
luVOID i,j,k,m,n,u,v;
2 c% m/ o: C' \( U; c+ N
double *pa,*pb,*pc;
) c; t& _- M" |3 ]7 n1 v5 d) K
luMessage pMessage;
% T9 Y( ^! A" {7 C, [9 O
wchar_t wchNum[32];
- F m3 q- w& V% B# X! f
char chNum[32];
+ { |* t% F8 j5 Q1 y. V
a.BType=luStaData_nil; a.VType=luStaData_nil; a.x=0;
; p: m0 K9 V$ A$ \
switch(theOperator)
2 X0 d9 f( d. L; o2 M1 c$ M
{
1 [. W- C5 B$ C6 C/ M4 m) j
case 2: //重载运算符*
2 v% [# Z. I6 f4 P# }
pMatrix1=(myMatrix *)SearchKey((char *)&(xx->x),sizeof(luVOID),Matrix);
/ h$ ]6 y* c' u1 x
pMatrix2=(myMatrix *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),Matrix);
8 u. i: O, ^0 M3 K
if(!pMatrix1 || !pMatrix2) break; //对象句柄无效,不是矩阵
* Y' |, F+ W) H2 a& a. ^5 r" M# S* R' T2 p
if(pMatrix1->Dim[1]!=pMatrix2->Dim[0]) break; //维数不匹配
4 F5 q( k* q6 r, A$ l l6 D" W
pMatrix3=NewMatrix(pMatrix1->Dim[0],pMatrix2->Dim[1]); //生成新矩阵
( M% f r& X% Y) D% ~
if(!pMatrix3) break;
& h5 \. } j" x l6 w5 Q$ y! r5 j
pa=pMatrix1->Array; pb=pMatrix2->Array; pc=pMatrix3->Array;
% x; q4 `, @& s7 S6 O3 M# K5 O; V
m=pMatrix1->Dim[0]; n=pMatrix1->Dim[1]; k=pMatrix2->Dim[1];
8 R5 c0 e5 |+ k/ q6 `7 \: o, }& L* U
for(i=0; i<m; i++) //矩阵乘
' e0 `4 H% t/ o1 N* y
{
/ b$ o& C! L/ v% a- P5 y& w* o
for(j=0; j<k; j++)
, S1 _+ a8 r0 ^
{
1 n, E. ]6 e2 u0 ^. ~
u=i*k+j; pc[u]=0.0;
0 C, X! r* v: v. `
for (v=0; v<n; v++)
8 f) C. q, q1 I2 `3 E, H1 d
{
: b; h6 f6 Q( }( v2 b
pc[u]=pc[u]+pa[i*n+v]*pb[v*k+j];
- Q4 l1 S1 ]* ]- e+ n& a; u
}
* r: h* h1 R* h3 h
}
4 X- U' w) }7 n! w1 o) n
}
' F! b, I5 \3 b! ~' I" t" J, `
FunReObj(hFor); //告诉Lu,返回一个动态对象
1 n+ m% m3 R/ k x+ s
a.BType=Matrix; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pMatrix3;
5 Q$ w+ L0 U& U! H
break;
+ I9 v. T' f, [$ P
case 25: //重载运算符.*
! O8 D: ~& \8 o: W! g& Y
pMatrix1=(myMatrix *)SearchKey((char *)&(xx->x),sizeof(luVOID),Matrix);
3 s. O! b7 s4 \, L/ ]" r
pMatrix2=(myMatrix *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),Matrix);
) d% {8 Y& c4 e v
if(!pMatrix1 || !pMatrix2) break; //对象句柄无效,不是矩阵
8 A0 |0 q; m# V) ^2 @
if(pMatrix1->Dim[0]!=pMatrix2->Dim[0] || pMatrix1->Dim[1]!=pMatrix2->Dim[1]) break; //维数不相同
, j X! p& s* n
pMatrix3=NewMatrix(pMatrix1->Dim[0],pMatrix1->Dim[1]); //生成新矩阵
3 y7 O9 D5 I7 Y4 o
if(!pMatrix3) break;
* ~5 }( u5 t; `# u$ v7 ^
for(i=0;i<pMatrix1->ArrayLen;i++) pMatrix3->Array[i]=pMatrix1->Array[i]*pMatrix2->Array[i]; //矩阵点乘
( q, ]" O0 Q A- x1 b1 g& R
FunReObj(hFor); //告诉Lu,返回一个动态对象
4 B# f+ l6 b3 d. c: Q" l# e& l
a.BType=Matrix; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pMatrix3;
8 D( Q! e4 R9 X+ ^5 b
break;
' Y; D9 V) X V/ O
case 46: //重载函数new
- c, Y/ n1 Z: z7 R
if(mm<2) break;
' K: j! C8 O6 e2 |
if((xx+1)->x<1 || (xx+2)->x<1 || (xx+1)->BType!=luStaData_int64 || (xx+2)->BType!=luStaData_int64) break;
) \ o! a2 k E# s+ M. j* t- k
pMatrix3=NewMatrix((luVOID)(xx+1)->x,(luVOID)(xx+2)->x);//生成新矩阵
. `% O( V( p2 J
if(!pMatrix3) break;
% I8 Q7 {( R5 f. p! z7 c
for(j=0,i=3;i<=mm;i++,j++) //赋初值
6 }6 f. ~ o, _% m
{
6 c5 n$ q7 f3 o$ a; D# A
if(j>=pMatrix3->ArrayLen) break;
# s: w6 f; u* R0 q) }6 V
if((xx+i)->BType!=luStaData_double) break; //只接受实数参数
" p$ f3 J3 m. }0 a. u* U9 r8 T) t
pMatrix3->Array[j]=*(double *)&((xx+i)->x);
, Q% j+ y& \0 F; E% N5 V
}
" _7 V1 ]6 e# | j7 E, m
FunReObj(hFor); //告诉Lu,返回一个动态对象
, M7 w# f1 M& ]* A$ f/ Y
a.BType=Matrix; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pMatrix3;
& Q9 `! R+ R1 r- N" z' g$ C
break;
; \- R" j" {# s1 v; \& a- _
case 49: //重载函数o
% x! l U5 S& B! L
pMessage=(luMessage)SearchKey("\0\0\0\0",sizeof(luVOID),luPubKey_User);
s) b2 O4 }. r
if(!pMessage) break;
' u$ |' {) b; @1 k; S; n
pMatrix1=(myMatrix *)SearchKey((char *)&(xx->x),sizeof(luVOID),Matrix);
2 q# z5 ` W. v' u" M
if(!pMatrix1) break; //对象句柄无效,不是矩阵
% E# m6 g( E7 H' t3 A9 }
pa=pMatrix1->Array;
: n0 U- v4 _ d+ f
m=pMatrix1->Dim[0]; n=pMatrix1->Dim[1]; k=0;
" K' e C9 E+ |- ~4 t" w* g5 {+ T9 g7 V
for(i=0; i<m; i++) //输出矩阵
6 y) e: W/ h D- E J/ H
{
5 G! y. O& w9 D- Z- P
pMessage(L"\r\n"); k+=2;
( P* j$ G) P( \
for(j=0; j<n; j++)
# J5 P. K( W o8 \* k) h! t8 u
{
; j( n V* f+ p& l+ H5 [
_gcvt_s(chNum,pa[i*n+j],16);
8 P- j: E) x" F5 l/ @
for(u=0;chNum[u];u++) {wchNum[u]=chNum[u]; k++;}
( n9 k$ X" B8 Q
wchNum[u]='\0';
- K$ _$ Y7 I. ^* b! k
pMessage(wchNum); pMessage(L" "); k+=2;
2 ^; v! `! |9 w* y% }# n6 H
}
% \9 \2 o9 B" C8 s2 {1 M
}
' e9 l/ h1 { t' i. G1 X1 W% u
pMessage(L"\r\n"); k+=2;
3 ~! W7 f% v+ m, h0 ^% X
a.BType=luStaData_int64; a.VType=luStaData_int64; a.x=k; //按函数o的要求,返回输出的字符总数
$ Q! i L! K8 W4 D- E
break;
4 f9 }, {+ r, n& n
default:
& j. n$ L n" B0 W
break;
7 Q; {7 f+ B) ^1 S
}
8 R) m0 R% M8 @* T7 \' p: y/ a
return a;
7 H9 s4 t Y" @' F2 v
}
8 F7 `# I+ @% M* o. p* W
void main(void)
7 m4 F+ r+ K. y* s- O
{
c" T* c3 m* u9 l& \" J) ~
void *hFor; //表达式句柄
' r& U, Y: S& J- @4 s
luINT nPara; //存放表达式的自变量个数
+ Q' F( v) S' V( O) {/ t- n0 g# d
LuData *pPara; //存放输入自变量的数组指针
+ Q: w2 n# C! F" ~+ B) ^$ [
luINT ErrBegin,ErrEnd; //表达式编译出错的初始位置和结束位置
! U) w X3 x& M" o1 Q/ c
int ErrCode; //错误代码
; n1 C) w$ j2 s; ^
void *v;
' e$ F, y* h& z
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.]}";//字符串表达式,矩阵乘
# g8 G4 U# C. M
//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.]}";//字符串表达式,矩阵点乘
' O3 k( \/ [4 g/ m7 L
LuData Val;
5 k8 d7 f- J9 o- M+ x
if(!InitLu()) return; //初始化Lu
; F+ z0 _/ ]- v, Y, [1 i
while(LockKey(Matrix,DelMatrix,OpMatrix)){Matrix--;} //锁定一个键,用于存储矩阵扩展类型
) M4 x% k$ z a3 g4 J/ q
2 `3 P! [9 K: s3 b: S+ K9 S: e
Val.BType=luStaData_int64; Val.VType=luStaData_int64; Val.x=Matrix; //定义整数常量
2 ~5 o' o5 [; N" R7 H% n, ^
SetConst(L"matrix",&Val); //设置整数常量
; D+ P/ p0 ?; y8 `+ g
InsertKey("\0\0\0\0",4,luPubKey_User,LuMessage,NULL,NULL,1,v); //使Lu运行时可输出函数信息
; |1 @: |4 R8 L$ i; w! m' A
wcout.imbue(locale("chs")); //设置输出的locale为中文
6 v$ K |, b+ H8 U5 C
9 G/ W* b+ t! b7 v. M
ErrCode=LuCom(ForStr,0,0,0,hFor,nPara,pPara,ErrBegin,ErrEnd); //编译表达式
- r; A( D# U& T. t# k, w+ V
if(ErrCode)
! C& s# y6 A. x( m8 U8 U! o
{
0 z- q& v2 ?/ W. _; c
wcout<<L"表达式有错误!错误代码:"<<ErrCode<<endl;
$ _) ]3 h' ]# W: \1 b
}
/ S5 [) U7 n' h0 ]$ V
else
$ `+ S0 M6 y2 d5 e2 Y; r
{
+ j9 L% a' M6 x; S% e' c9 T5 F
LuCal(hFor,pPara); //计算表达式的值
! h" o) j9 ]) ^ _) A1 h7 P: o
}
1 d. N) x/ o0 ^, v' Y( d& `# z
LockKey(Matrix,NULL,OpMatrix);//解锁键Matrix,本例中,该函数可以不用
' ?# a/ R8 M: i+ X1 Y9 X
FreeLu(); //释放Lu
. X3 H: ^- a" Z o6 P7 X
}
复制代码
习题:
$ v7 w) B8 @0 |* |) R
8 ~0 U" \. }$ S. f, W4 K
(1)自定义矩阵的加、减、左除、右除、点左除等运算,自编测试字符串代码,重新编译运行程序,观察计算结果。
! ?4 D$ B+ W9 Z; G1 G
7 g3 D$ |! G6 N* b3 k
(2)小矩阵乘效率测试。编译运行以下Lu字符串代码:
main(:a,b,c,d,t,i)=
3 y, R: L" v$ z: d5 g
a=new[matrix,2,2: 1.,2.,2.,1.],
5 q+ G0 w& ]6 v; J
b=new[matrix,2,2: 2.,1.,1.,2.],
5 K* O0 W- Y6 w2 L- f1 h* }
c=new[matrix,2,2: 2/3.,-1/3.,-1/3.,2/3.],
# K5 o6 ` M. x) E
t=clock(),
. u W1 K7 T- ?9 N& }
d=a*b, i=0, while{i<1000000, d=d*c*b, i++},
: _$ P- [* R" y' z
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.
4 y2 X4 G5 {5 c7 G& l( M
5. 4.
! J K9 ~+ `- v- G# _
time=0.797 seconds.
, ?2 J5 r2 R$ u( \# X" U V1 k
请按任意键继续. . .
复制代码
Matlab 2009a 代码:
a=[1.,2.;2.,1.];
- I# }) I3 G+ y. X/ T- X6 y) J: d0 T
b=[2.,1.;1.,2.];
" t' m& |2 i% F& m6 }$ N. w. o
c=[2/3.,-1/3.;-1/3.,2/3.];
1 e' u) V" A5 _! B' r, X/ u0 {
tic,
. N6 l: j5 w7 D! }0 R! M
d=a*b;
( {5 U3 J; w) C0 x" j
for i=1:1000000
+ m" T8 e$ H1 C, ~$ p
d=d*c*b;
' x1 r: F" z) i" n- U
end
3 r4 }7 p% |7 i9 l9 Q: A
d,
/ [1 |3 z0 P/ k- F: D" @
toc
复制代码
结果:
d =
* N, Y3 x: W/ l& [3 B4 q8 q
4 5
: |9 B" _+ p5 G2 p$ Z2 w+ @
5 4
8 Q1 v& @3 i# f
Elapsed time is 2.903034 seconds.
复制代码
本例矩阵乘效率测试,Lu的速度超过了Matlab,主要在于Lu有更高的动态对象管理效率。
* C/ u' T! A; b8 T. _$ y# p% r4 s
; O; P, C5 P( n9 Y% z$ d: C
由以上可以看出,自定义数据类型和系统内置类型有近乎相同的效率。
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5