数学建模社区-数学中国
标题:
在Lu中创建自定义数据类型,小矩阵乘效率测试
[打印本页]
作者:
forcal
时间:
2011-10-24 18:54
标题:
在Lu中创建自定义数据类型,小矩阵乘效率测试
本例中,我们将自定义矩阵(matrix)类型,基本类型和扩展类型均为matrix(标识矩阵)。
* v( f! S) z% P- R
' Z* ?# a+ G' l: L3 z
基本要点:
9 U) F9 j# Z4 B$ u
% U. M F% r" N( ]+ L
(1)编写生成矩阵(matrix)的函数NewMatrix和销毁矩阵的函数DelMatrix。
) c* f `* d) B$ a/ j% J
$ u* `# G- j" M* y
(2)为自定义类型matrix编写运算符重载函数OpMatrix。
4 l2 Q* i& o# \# g# K X- E
+ `( }4 E& R* m& {$ ?7 R
(3)用函数LockKey将重载函数OpMatrix注册到Lu,锁定的键的类型即为matrix,要注册为常量,以便于使用。
' F d( g" d0 Q3 n' X W
- ~0 c" V+ C6 v4 ^8 U. y( {/ D
(4)为自定义类型matrix编写其他操作函数(本例未提供)。
8 b, V, p6 n5 Y: w: E
/ V4 ]# l+ D% M% v& y0 R1 t
(5)用函数LockKey解锁键matrix(本例中,程序退出时会自动解锁,故可以不用)。
#include <windows.h>
+ B$ K4 Z: k0 F |
#include <iostream>
/ ~$ p$ ?2 P8 r% E( a3 v2 i3 J5 k
#include <math.h>
/ T7 z' k* {6 Y ~
#include "lu32.h"
( p( o' D; U6 X; s
#pragma comment( lib, "lu32.lib" )
) e2 p: h% Y- `
using namespace std;
. y; [# z# H3 O: J5 F/ k. b
//自定义矩阵
& n! H7 c, y) N( |5 N
class myMatrix
' f" `, t- }7 W
{
, D( H: C7 W/ m0 H: F# ?
public:
' @2 b% d, Z+ l% B% o' C
double *Array; //数据缓冲区
! u) W! u9 j' P) s$ R# z1 t. [8 J
luVOID ArrayLen; //数据缓冲区长度
0 E7 f5 b- }% \* [, k
luVOID Dim[2]; //矩阵维数
! Y# G3 O2 p6 O
myMatrix(){Array=NULL; ArrayLen=0; Dim[0]=0; Dim[1]=0;}
& }5 E4 Q; M' R" M z7 F9 C
~myMatrix()
: G9 X, Q) f% e+ v- [3 a) S
{
& N0 j( @$ o, H i
if(Array) delete[] Array;
* b, ~1 k! G' p! u
}
% S3 k* y+ u4 E1 S8 y$ I
};
) ]) a! U& J+ b
luKEY Matrix=-1000; //标识矩阵类型,最终的Matrix由LockKey决定
1 |' R6 h2 x( F& x0 a6 E3 m
void _stdcall LuMessage(wchar_t *pch)//输出动态库信息,该函数注册到Lu,由Lu二级函数调用
1 g. _9 w1 O/ H g5 L+ o
{
& {0 z) b/ B) f- V5 t$ b4 R ^
wcout<<pch;
" b/ [% u u0 A6 X: h; [: w$ p/ g
}
( v5 t8 N" D; x
void _stdcall DelMatrix(void *me) //用于LockKey函数及InsertKey函数,使Lu能自动销毁myMatrix对象
' M u2 Q k# R% t+ C& X
{
1 d2 R) B7 _6 y- E/ U
delete (myMatrix *)me;
3 v8 e* O- \. A3 u
}
2 Q, a4 h9 O* a" f- h n: i$ p
myMatrix * _stdcall NewMatrix(luVOID m,luVOID n) //生成一个myMatrix对象
z- B) N y/ E" c
{
1 K/ m2 |/ m' I
myMatrix *pMatrix;
?; G# N0 h+ q8 M
luVOID k;
0 B3 |- B7 W& O& U
double *pa;
2 x* K3 a% B H5 V" x
char keyname[sizeof(luVOID)];
% |) O6 n; s) F8 b8 `
void *NowKey;
- i8 c- | \# n, e z) r. R/ Q: e
k=m*n;
% {) ~* s5 V. X- g3 j8 M3 I$ y# x
pMatrix=(myMatrix *)GetBufObj(Matrix,keyname);//先尝试从缓冲区中获取一个矩阵对象
# F+ Y2 y9 W. ^7 G
if(pMatrix)
' w6 \% d0 Q+ o) P" g' X
{
4 B6 U- u' R% V& [" b
if(pMatrix->ArrayLen!=k) //重置矩阵的大小
6 G: k4 F6 v9 F! r
{
) `- X7 ~, K5 T4 r1 ?! N3 R
pa=new double[k];
/ k& f, Y$ J2 r5 u3 d3 F& m( _$ S
if(!pa)
% Z- g% n/ \2 j6 n2 g+ l# q
{
% Z" Y) D1 b' {- I+ c
DeleteKey(keyname,sizeof(luVOID),Matrix,DelMatrix,1); //将矩阵对象放回缓冲区
$ A, V" `% Y* C5 {
return NULL;
6 J" r/ L: t/ b$ k
}
* f/ P( n- c6 u) s/ H! A
delete[] pMatrix->Array;
1 f" z* `% ~ g1 P$ k. K/ M
pMatrix->Array=pa;
0 f* j+ _1 p5 x' H; e7 S
}
% H6 U$ T8 d; D# s1 _9 B, n3 t
}
3 S( r6 U, R: S* G* U
else
% q# O% c+ c" f. E5 [' L
{
' Y4 Q8 N& p0 ^% f' K1 b" {
pMatrix=new myMatrix; //创建矩阵对象
! {8 f( s: D# D
if(!pMatrix) return NULL;
% y1 K) i! {5 X8 m& _+ x
pMatrix->Array=new double[k];
# o3 ?+ }7 n5 d. p2 d; S
if(!pMatrix->Array)
: L, M9 `! W1 Z6 g. ], k
{
, i0 `3 x; n. I& _
delete pMatrix;
; v4 J: R' Y8 @3 C: K
return NULL;
/ [( z9 C) f+ d9 D1 Z* N
}
, {, i: B }* F
if(InsertKey((char *)&pMatrix,-1,Matrix,pMatrix,DelMatrix,NULL,0,NowKey)) //将矩阵对象注册到Lu
# h0 v# ]8 Y& i" o8 _
{
: a) V5 g3 X3 p6 f
delete pMatrix;
! T p# G, ?% X T
return NULL;
, x& J0 P- m4 X3 f
}
+ e( U+ Q6 N+ E8 L
}
6 h0 Y( s' X; Z8 E
pMatrix->ArrayLen=k; pMatrix->Dim[0]=m; pMatrix->Dim[1]=n;
# y3 e4 q# |6 _; ~8 ^/ u& l
return pMatrix;
% w2 B% ]! q9 v
}
! Z8 z, I' P/ E ~$ @5 z2 H ]8 k
LuData _stdcall OpMatrix(luINT mm,LuData *xx,void *hFor,int theOperator) //运算符重载函数,用于LockKey函数
4 d' f+ }& |9 S0 @7 `/ ~
{
# s# @8 f( e& C# X/ H3 V
LuData a;
6 Z+ I0 o4 T- M$ D2 E
myMatrix *pMatrix1,*pMatrix2,*pMatrix3;
$ r+ ]) \0 a/ N7 e
luVOID i,j,k,m,n,u,v;
0 t" n- [9 x2 x/ N( N/ l( c$ P
double *pa,*pb,*pc;
: z) B0 \, O9 ~+ E& V
luMessage pMessage;
v$ |: ~6 @# E9 u: t& t
wchar_t wchNum[32];
! ~' o% `+ W5 V$ n( g" E
char chNum[32];
: {6 x1 R! C) u% z' i, j- n* }" u3 o
a.BType=luStaData_nil; a.VType=luStaData_nil; a.x=0;
5 o2 Z: ~* b0 B
switch(theOperator)
: q7 y& w, p8 ~# J$ A7 H
{
% O0 E7 f" e& W) d6 s! ]
case 2: //重载运算符*
, v" _: r9 v, d U1 }* _
pMatrix1=(myMatrix *)SearchKey((char *)&(xx->x),sizeof(luVOID),Matrix);
$ X5 q- v& F3 q
pMatrix2=(myMatrix *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),Matrix);
! |, a4 V, e0 Q8 S& F9 e
if(!pMatrix1 || !pMatrix2) break; //对象句柄无效,不是矩阵
. w( I5 E& Z6 P# X
if(pMatrix1->Dim[1]!=pMatrix2->Dim[0]) break; //维数不匹配
( [) Y: i8 r0 E& v: m( S2 [
pMatrix3=NewMatrix(pMatrix1->Dim[0],pMatrix2->Dim[1]); //生成新矩阵
4 x b! j8 N7 g( Q( E, w/ K. z8 t, D
if(!pMatrix3) break;
: @3 c# ` m7 U ?! O
pa=pMatrix1->Array; pb=pMatrix2->Array; pc=pMatrix3->Array;
. N& {2 z- y: D
m=pMatrix1->Dim[0]; n=pMatrix1->Dim[1]; k=pMatrix2->Dim[1];
/ M. H& v; u; K. s; F' z# C$ z$ u4 d
for(i=0; i<m; i++) //矩阵乘
3 w3 }9 e% E, H8 e
{
1 i8 q7 G; i2 b1 f
for(j=0; j<k; j++)
( Y) D) k3 s. z& w/ U4 u
{
: \- f3 M+ M- d4 T6 n1 z
u=i*k+j; pc[u]=0.0;
9 i3 E& q9 ~* m( t+ i) {
for (v=0; v<n; v++)
* |+ G" Z( `* g% v0 f5 g
{
8 R% F6 N) R( l& g4 {) u
pc[u]=pc[u]+pa[i*n+v]*pb[v*k+j];
$ @: |8 W1 c9 L
}
/ p W, l8 D* e4 l) ]
}
: d( n2 r" h. F. t6 {6 e6 J# f
}
3 _) k- B# M8 y, j, d/ g
FunReObj(hFor); //告诉Lu,返回一个动态对象
* D, y2 ~* R# o+ Q" g+ G+ o
a.BType=Matrix; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pMatrix3;
2 H5 x3 e: J R; V) u
break;
' J& o0 z- o$ v0 V( K% B1 y
case 25: //重载运算符.*
, ^/ ]( b: w+ A/ e
pMatrix1=(myMatrix *)SearchKey((char *)&(xx->x),sizeof(luVOID),Matrix);
* r) Y* G0 b, U
pMatrix2=(myMatrix *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),Matrix);
! k. g1 @, @% e' d6 w* ~3 _
if(!pMatrix1 || !pMatrix2) break; //对象句柄无效,不是矩阵
- Z1 g& K/ K- k) a0 Q% w
if(pMatrix1->Dim[0]!=pMatrix2->Dim[0] || pMatrix1->Dim[1]!=pMatrix2->Dim[1]) break; //维数不相同
% L) `2 E$ s" C" W9 V
pMatrix3=NewMatrix(pMatrix1->Dim[0],pMatrix1->Dim[1]); //生成新矩阵
- u3 k" n% X) [/ Z' T, ~
if(!pMatrix3) break;
* k/ ^9 [) e k: @ M
for(i=0;i<pMatrix1->ArrayLen;i++) pMatrix3->Array[i]=pMatrix1->Array[i]*pMatrix2->Array[i]; //矩阵点乘
8 ]3 ?( ^4 d5 D k4 o4 f! c" u9 J
FunReObj(hFor); //告诉Lu,返回一个动态对象
1 {5 S% x# c7 d k
a.BType=Matrix; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pMatrix3;
- @+ r r* P9 D0 @) B5 X
break;
7 O2 F' @. t7 E1 O8 ^+ N' e
case 46: //重载函数new
! ]( [5 `: c8 l' h' H" K7 {
if(mm<2) break;
# m& t# s5 \( @
if((xx+1)->x<1 || (xx+2)->x<1 || (xx+1)->BType!=luStaData_int64 || (xx+2)->BType!=luStaData_int64) break;
5 b U% P1 y5 W1 D' ?# X
pMatrix3=NewMatrix((luVOID)(xx+1)->x,(luVOID)(xx+2)->x);//生成新矩阵
1 `+ `& Z& i4 L8 W9 @$ t; n. V
if(!pMatrix3) break;
8 ]/ F5 i* ~3 Y
for(j=0,i=3;i<=mm;i++,j++) //赋初值
6 h7 T$ `' A+ L5 z# q
{
, ?& l* a7 j `) u. h
if(j>=pMatrix3->ArrayLen) break;
) L, d+ U, V1 ?, \7 [! S+ M5 X
if((xx+i)->BType!=luStaData_double) break; //只接受实数参数
% h' n3 z: I- S! H+ I( B2 F5 Z
pMatrix3->Array[j]=*(double *)&((xx+i)->x);
2 m a: i4 o+ z- ~% Y3 M
}
) b* M, ~0 G$ E8 f* w1 O- a1 q
FunReObj(hFor); //告诉Lu,返回一个动态对象
) W9 R3 G% E% v) K
a.BType=Matrix; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pMatrix3;
% v; y" ?9 a0 \0 k
break;
1 L( M2 H6 ^2 Q6 A) z
case 49: //重载函数o
" n. p/ X3 z. M! v, E7 d2 Q6 T t
pMessage=(luMessage)SearchKey("\0\0\0\0",sizeof(luVOID),luPubKey_User);
' P ^% q3 v- H- U
if(!pMessage) break;
9 t i2 H3 T8 h& q5 c
pMatrix1=(myMatrix *)SearchKey((char *)&(xx->x),sizeof(luVOID),Matrix);
8 H/ S# q3 J9 U' x$ M- K. }9 u
if(!pMatrix1) break; //对象句柄无效,不是矩阵
3 E' f0 r; @+ f: q0 k
pa=pMatrix1->Array;
) }1 N0 ^2 k! [4 r! L
m=pMatrix1->Dim[0]; n=pMatrix1->Dim[1]; k=0;
3 a# r5 r8 ]! j7 g
for(i=0; i<m; i++) //输出矩阵
$ {; W, F7 {6 `2 Y6 ]
{
; j) G0 h, |& i$ W, x
pMessage(L"\r\n"); k+=2;
% J4 s s' s; K5 ]
for(j=0; j<n; j++)
, k- a% i3 u* y2 {! P$ E1 S
{
- C9 U' X! ]0 i2 S
_gcvt_s(chNum,pa[i*n+j],16);
& g# ]* M( E+ d. ^
for(u=0;chNum[u];u++) {wchNum[u]=chNum[u]; k++;}
( C7 y) ~$ f8 O( q+ W/ |: d
wchNum[u]='\0';
* w! d4 L, F: w8 n' y; i- p
pMessage(wchNum); pMessage(L" "); k+=2;
/ T/ {$ O- |6 \" L
}
, k' c+ E* [/ w
}
7 @0 N5 p( P# ~$ _
pMessage(L"\r\n"); k+=2;
. X8 T. U1 g9 @( t. m" N
a.BType=luStaData_int64; a.VType=luStaData_int64; a.x=k; //按函数o的要求,返回输出的字符总数
% J( S5 a! y/ P9 b
break;
) G4 Z9 } V5 w* l2 K W
default:
* z, b0 b. O9 T" z$ x" I; g6 {
break;
$ j5 {8 l, n/ D/ h* p$ d# l
}
4 o; C; Y) L- S, G
return a;
/ _, c- v9 Q/ M
}
% V3 A( M8 W* t5 Y
void main(void)
1 }9 i" r. S; w1 \7 a7 W1 j2 o
{
+ g: n. }, e- ?$ S3 }6 H
void *hFor; //表达式句柄
, v& ^/ n8 N( R, @# C
luINT nPara; //存放表达式的自变量个数
$ s) ^8 K, `, a1 a) h
LuData *pPara; //存放输入自变量的数组指针
- s, A( F% y. f% m( ?8 ~
luINT ErrBegin,ErrEnd; //表达式编译出错的初始位置和结束位置
$ @7 c1 ]1 k) \+ m, P
int ErrCode; //错误代码
' a8 G0 _$ w+ Z8 |1 E
void *v;
8 r7 C3 g; ?1 ~( C5 z, S
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.]}";//字符串表达式,矩阵乘
) ]# [6 Y, b& z& a% ~ u
//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.]}";//字符串表达式,矩阵点乘
- U; Y8 t) o6 C# h) e8 r; A- x
LuData Val;
+ e6 M+ s$ T6 ^7 W2 K* L
if(!InitLu()) return; //初始化Lu
& s8 j% M4 u) e, x! u
while(LockKey(Matrix,DelMatrix,OpMatrix)){Matrix--;} //锁定一个键,用于存储矩阵扩展类型
8 ?3 F8 X9 d) v0 ~4 k4 C6 O
0 J( G5 ]* D' y7 ]# u& k
Val.BType=luStaData_int64; Val.VType=luStaData_int64; Val.x=Matrix; //定义整数常量
, |& b0 z1 Z' s, I" J
SetConst(L"matrix",&Val); //设置整数常量
" `) k' A9 [7 \% n% X' A, h- Y
InsertKey("\0\0\0\0",4,luPubKey_User,LuMessage,NULL,NULL,1,v); //使Lu运行时可输出函数信息
. E; U, \0 Q( Z6 U
wcout.imbue(locale("chs")); //设置输出的locale为中文
& h1 `. g3 `% g! I$ e1 c
7 Q5 |) Q! y* `, g% |" t7 S
ErrCode=LuCom(ForStr,0,0,0,hFor,nPara,pPara,ErrBegin,ErrEnd); //编译表达式
) Y6 }: G6 O% b
if(ErrCode)
; g/ i' M, ?; V4 o1 J' `
{
6 b8 Z1 \! t! h
wcout<<L"表达式有错误!错误代码:"<<ErrCode<<endl;
% j! ~6 [4 Z% d4 ]9 O, t
}
" i6 |; J" n- {/ B9 j% X7 K- K: ?
else
" }" J( V$ Y! |5 D5 t" I4 M$ p+ a1 Z
{
# a& H7 n% Z# F' h0 i$ C
LuCal(hFor,pPara); //计算表达式的值
0 a+ d0 `0 ^' q4 o
}
) u$ [9 U( _' [. F
LockKey(Matrix,NULL,OpMatrix);//解锁键Matrix,本例中,该函数可以不用
8 r$ N5 D4 c/ h: `! S: @
FreeLu(); //释放Lu
9 A- z1 Y4 \$ N' v; R, U- p
}
复制代码
习题:
- J5 D5 p8 _6 T+ Q4 x! i: ^
& G O& A0 N. B0 V; w
(1)自定义矩阵的加、减、左除、右除、点左除等运算,自编测试字符串代码,重新编译运行程序,观察计算结果。
( l9 Z, p, t7 Q3 O. [
5 L v' U" E, s6 z; }6 T# D
(2)小矩阵乘效率测试。编译运行以下Lu字符串代码:
main(:a,b,c,d,t,i)=
% K- ~* v; T, m; H; M4 S# m9 E- y5 w
a=new[matrix,2,2: 1.,2.,2.,1.],
" Z+ R( r7 }' j ~! T: V. ^+ z, G
b=new[matrix,2,2: 2.,1.,1.,2.],
! o" c7 |9 T" {% s
c=new[matrix,2,2: 2/3.,-1/3.,-1/3.,2/3.],
" V, H, v/ L5 W# o, U' `
t=clock(),
4 y) A- @$ P5 {' [$ K
d=a*b, i=0, while{i<1000000, d=d*c*b, i++},
8 I; d0 S( {* a+ z8 \, ?" t) n7 J
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.
* r& b4 n. s7 H& x& c
5. 4.
5 a1 B, `. J s" t! r/ M
time=0.797 seconds.
. L1 f; S' b/ b. G$ o- a
请按任意键继续. . .
复制代码
Matlab 2009a 代码:
a=[1.,2.;2.,1.];
: s5 q; `& q \! @, l, l4 C
b=[2.,1.;1.,2.];
' d k3 F0 y' A7 j
c=[2/3.,-1/3.;-1/3.,2/3.];
: F! I7 K/ |; D' O
tic,
1 w- w ?! |" G/ ?! k" E
d=a*b;
/ W6 r" |- g* o0 Y w3 b
for i=1:1000000
/ s0 p3 t5 U& w8 F2 U" c
d=d*c*b;
: K3 k$ \7 |9 V- t& ^
end
6 a4 K% t1 n' O% R ~2 P+ o
d,
( e. J. o; u% O) w8 e7 ?
toc
复制代码
结果:
d =
5 a+ d! f+ X/ l0 e# C
4 5
% R5 s9 I! N9 t& O1 N
5 4
1 j8 m* f. z" X+ E7 A( B: w! C. }6 e" Y
Elapsed time is 2.903034 seconds.
复制代码
本例矩阵乘效率测试,Lu的速度超过了Matlab,主要在于Lu有更高的动态对象管理效率。
0 K* L& z- ~% G1 c( \: c. ~# I
; a6 ]/ B0 |3 r/ I
由以上可以看出,自定义数据类型和系统内置类型有近乎相同的效率。
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5