数学建模社区-数学中国
标题:
Lu基于系统内置对象创建扩展数据类型,小矩阵乘效率测试
[打印本页]
作者:
forcal
时间:
2011-10-23 09:37
标题:
Lu基于系统内置对象创建扩展数据类型,小矩阵乘效率测试
本例中,我们将基于系统内置实数数组创建矩阵(matrix)类型,即:基本类型为luDynData_realarray(标识实数数组),扩展类型为matrix(标识矩阵)。为了简单,我们仅处理二维实数数组即矩阵类型。
4 q8 Z3 T) a! Q A, E# I& r2 N! `
. t+ ^" n" q- q; v* H$ T
基本要点:
: U3 g6 m6 ~1 @ W( x+ G
3 n6 z0 n: u; U4 H/ U' G4 {
(1)为扩展类型matrix编写运算符重载函数OpMatrix。
; l- G$ O8 T9 w3 q
/ c* `" w7 i6 G! ~6 F
(2)用函数LockKey将重载函数OpMatrix注册到Lu,锁定的键的类型即为matrix,要注册为常量,以便于使用。
7 P! D$ s" d0 u q/ I1 ~0 e4 O
- G; v$ ?0 [0 x: @% B4 A
(3)为扩展类型matrix编写其他操作函数(本例未提供)。
0 v7 ]* X. V7 A4 M; c
$ F. e7 n4 n2 S' l C
(4)用函数LockKey解锁键matrix(本例中,程序退出时会自动解锁,故可以不用)。
#include <windows.h>
8 L' P( h9 l; W" k t
#include <iostream>
3 N* @% a3 l- b* d/ Q. K1 Y
#include <math.h>
/ C' }3 R+ T4 J& p& X
#include "lu32.h"
1 r9 u4 K) A$ N2 x
# H, D3 ^& W* U- K/ U% X
#pragma comment( lib, "lu32.lib" )
8 h7 ^) C7 X4 |4 j+ [! J0 a
0 u6 q+ Z+ m) G5 U2 d2 P1 V7 \# r
using namespace std;
2 q) E2 V4 z' v
5 u8 S$ S; P) k/ t( r5 Z
luKEY Matrix=-1000; //标识矩阵类型,最终的Matrix由LockKey决定
- D' g! Y7 j( h4 ^8 N' D0 n9 e
3 O6 {$ ~% n# B
void _stdcall LuMessage(wchar_t *pch)//输出动态库信息,该函数注册到Lu,由Lu二级函数调用
- n3 K2 f$ ^$ _/ o) x# e
{
5 Q3 D5 d _) c. b/ r c1 o4 \ W
wcout<<pch;
9 y, s+ ^ J, y3 W6 f6 O2 |5 f8 p1 h
}
7 M4 _$ y# m, I- Z% p o
void _stdcall DelMatrix(void *me) //用于LockKey函数,因为是基于系统内置实数数组创建矩阵,故该函数什么也不做
; `4 e2 p0 h2 U8 q. \9 R
{
. E0 p0 X; k4 y6 ~' R0 {* \
}
5 u5 g- g% ^+ I l& E
LuData _stdcall OpMatrix(luINT mm,LuData *xx,void *hFor,int theOperator) //运算符重载函数,用于LockKey函数
; V" K' {# J- x$ c% k9 V& D; @# C6 l
{
# E* R* i. o% Y; k( ?9 p I% `
LuData a;
; \3 S. R8 U1 s8 Q6 q
luRealArray *pRealArray1,*pRealArray2,*pRealArray3;
! V2 t+ f8 t6 x, X
luVOID i,j,k,m,n,u,v;
5 f4 Z" I8 }. R
double *pa,*pb,*pc;
0 `2 t' Z7 n3 E/ t
luMessage pMessage;
! {! L5 a" I7 m+ K) G- ~: ^
wchar_t wchNum[32];
- f4 j" y+ u" l) E& A2 i" |
char chNum[32];
: B: m- I& d; U' X: S
a.BType=luStaData_nil; a.VType=luStaData_nil; a.x=0;
/ J0 t* [$ L$ @5 l- [- @" e- ^: D4 l7 _
switch(theOperator)
) {. k7 N1 v- P+ y/ z
{
+ T+ x$ m' _) v3 T1 p$ m
case 2: //重载运算符*
$ B, e5 M1 F- ~5 F6 T
pRealArray1=(luRealArray *)SearchKey((char *)&(xx->x),sizeof(luVOID),luDynData_realarray);
# Z( F1 ^0 ~; r
pRealArray2=(luRealArray *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),luDynData_realarray);
/ w+ E% g1 Y! F8 ]; o/ y! s
if(!pRealArray1 || !pRealArray2) break; //对象句柄无效,不是实数数组
: q$ g# z% d, Z; ]% M- l& D9 t9 Y/ c
if(pRealArray1->DimLen!=2 || pRealArray2->DimLen!=2) break; //不是二维实数数组(矩阵)
% K! F9 I6 s1 I, i' T: Y, S- t4 D
if(pRealArray1->Dim[1]!=pRealArray2->Dim[0]) break; //维数不匹配
9 G5 O! U b4 G& J* s5 w6 G
pRealArray3=(luRealArray *)NewSysObj(luDynData_realarray,pRealArray1->Dim[0]*pRealArray2->Dim[1],2); //创建矩阵对象
9 f8 e& `$ H$ M# Q% }
if(!pRealArray3) break;
& O8 P% N i v: N6 k R
pRealArray3->Dim[0]=pRealArray1->Dim[0]; pRealArray3->Dim[1]=pRealArray2->Dim[1]; //设置矩阵维数大小
" E0 S# V% D4 h: e: b- X0 H; Z
pa=pRealArray1->Array; pb=pRealArray2->Array; pc=pRealArray3->Array;
: N# H4 k* s% u( J! m/ g/ i
m=pRealArray1->Dim[0]; n=pRealArray1->Dim[1]; k=pRealArray2->Dim[1];
# P* }& A! g, @5 @, K6 h! {
for(i=0; i<m; i++) //矩阵乘
: M6 a7 L: p- J2 H% E
{
) k3 K* q; r0 m, {# v
for(j=0; j<k; j++)
( u" C4 E0 l% }6 w' [2 e
{
& H9 {% a1 R" R' k3 ]: s6 [4 b! r, S
u=i*k+j; pc[u]=0.0;
# h' `$ R. a8 F) [# N
for (v=0; v<n; v++)
6 L4 a* |7 `8 W7 ]! d
{
4 ?. H6 @6 W3 J$ Y
pc[u]=pc[u]+pa[i*n+v]*pb[v*k+j];
2 V! C1 j; I+ n6 l! `* b A: D
}
& J8 e) b' Y0 c: w9 r
}
8 ]. g. A: M* _) L
}
* ?1 [1 y5 \8 p6 G- m5 A/ z& |- n5 O
FunReObj(hFor); //告诉Lu,返回一个动态对象
2 m' O4 V1 P+ s3 z
a.BType=luDynData_realarray; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pRealArray3;
& f7 L5 h0 o# @# e$ \
break;
. R' d3 Z4 m- @& X' d6 o
case 25: //重载运算符.*
4 A6 q% U; S1 m( ~5 f
pRealArray1=(luRealArray *)SearchKey((char *)&(xx->x),sizeof(luVOID),luDynData_realarray);
1 y' ^8 u k: R/ D; ?: M
pRealArray2=(luRealArray *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),luDynData_realarray);
4 w, |2 n/ M* S& D
if(!pRealArray1 || !pRealArray2) break; //对象句柄无效,不是实数数组
7 a7 J4 w# O; L0 D& H# e2 e
if(pRealArray1->DimLen!=2 || pRealArray2->DimLen!=2) break; //不是二维实数数组(矩阵)
8 V) [6 m- @) E! A: E
if(pRealArray1->Dim[0]!=pRealArray2->Dim[0] || pRealArray1->Dim[1]!=pRealArray2->Dim[1]) break; //维数不相同
( t% z B* \% H0 M& o7 L
pRealArray3=(luRealArray *)NewSysObj(luDynData_realarray,pRealArray1->ArrayLen,2); //创建矩阵对象
/ A6 n, C7 k$ ~( t- |
if(!pRealArray3) break;
, I7 D# I1 o* O2 }( ~5 r
pRealArray3->Dim[0]=pRealArray1->Dim[0]; pRealArray3->Dim[1]=pRealArray1->Dim[1]; //设置矩阵维数大小
4 m3 o% ^5 S8 F6 e6 ` X5 p# v0 t
for(i=0;i<pRealArray1->ArrayLen;i++) pRealArray3->Array[i]=pRealArray1->Array[i]*pRealArray2->Array[i];//矩阵点乘
: J0 p2 [6 A' b, Z4 v6 W( e
FunReObj(hFor); //告诉Lu,返回一个动态对象
2 g& y; U" y& X) h9 h$ ^, Z
a.BType=luDynData_realarray; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pRealArray3;
; S8 J6 E" ^' x$ h( \/ Z a5 P U# h* a
break;
/ u) N& W8 e" G4 o5 q t4 R
case 46: //重载函数new
' y6 R) c1 K$ t5 A4 E- g _ u
a=ExeOperator(mm,xx,hFor,theOperator,luDynData_realarray); //直接调用基本类型luDynData_realarray的new函数
1 B8 ~ U" i# X7 ]0 a, x
if(a.VType==luDynData_realarray) a.VType=Matrix; //设置扩展类型为自定义的Matrix类型
' Z3 }) P- I) p1 l. g+ E
break;
! |1 H& v6 ^' h! |' M! H0 ^
case 49: //重载函数o
% S$ j# Q' s( t5 i3 r
pMessage=(luMessage)SearchKey("\0\0\0\0",sizeof(luVOID),luPubKey_User);
% S1 {* H3 Z5 H3 W
if(!pMessage) break;
9 F* y! j, s, J; C; Q
pRealArray1=(luRealArray *)SearchKey((char *)&(xx->x),sizeof(luVOID),luDynData_realarray);
/ O& ~5 S; E+ r( g
if(!pRealArray1) break; //对象句柄无效,不是实数数组
; ^$ v8 _( R8 T$ i" i
if(pRealArray1->DimLen!=2) break; //不是二维实数数组(矩阵)
e$ h% }4 S" m& f
pa=pRealArray1->Array;
! V% Y! \& Z) w; b
m=pRealArray1->Dim[0]; n=pRealArray1->Dim[1]; k=0;
# y7 x8 c5 u0 s* n* A7 h
for(i=0; i<m; i++) //输出矩阵
4 Q. H/ h: i0 O. s1 _, P
{
" X) t# G# P7 z4 `# U4 R/ d
pMessage(L"\r\n"); k+=2;
1 |8 d' A! g( L
for(j=0; j<n; j++)
# N' \! W' H6 j6 P. v/ h! }
{
2 S% B# v# O, a, w# V* n
_gcvt_s(chNum,pa[i*n+j],16);
7 a- R0 O7 I& P. \
for(u=0;chNum[u];u++) {wchNum[u]=chNum[u]; k++;}
+ J9 Z1 a7 i9 y& K
wchNum[u]='\0';
( O7 [8 D) Y) y' N# h
pMessage(wchNum); pMessage(L" "); k+=2;
: j& |( H% H% {* {& l1 F' k
}
# E [- T, P: Z$ ~; t$ B' ]/ N, N
}
& l, C; ^1 Q- p8 `+ n
pMessage(L"\r\n"); k+=2;
) ~% p5 f/ j' ^/ H3 E
a.BType=luStaData_int64; a.VType=luStaData_int64; a.x=k; //按函数o的要求,返回输出的字符总数
/ I& u: S) I. K9 V2 r
break;
1 g, g2 y# r+ E) e+ s) c9 @, Q
default:
$ F- ?6 z" i4 L9 _2 c& i) Y# X
break;
4 i. M' T1 b/ M# W
}
4 _$ W7 ]9 T0 Z! o$ e+ c
return a;
' {1 D& E2 d3 y( q4 Y& u# r
}
; L4 X0 ?$ A R- ~, ^0 ~9 i
void main(void)
% H2 Q0 W0 E) A) ~4 Q. K; r
{
# p% N# \% t. S. W' T4 H: e
void *hFor; //表达式句柄
+ }/ C; Z9 M, @- R9 s
luINT nPara; //存放表达式的自变量个数
# B1 m U' s! f+ `3 K2 I. d4 Q
LuData *pPara; //存放输入自变量的数组指针
9 `9 w) P' Y$ Q
luINT ErrBegin,ErrEnd; //表达式编译出错的初始位置和结束位置
, D3 R, \$ n4 O0 k
int ErrCode; //错误代码
1 m) q& y! L: B! v
void *v;
' D0 M. k5 T; t1 x* v
wchar_t ForStr[]=L"o{new[matrix,2,3,data: 0.,1.,2.;3.,4.,5.]*new[matrix,3,2,data: 1.,2.;3.,4.;5.,6.]}";//字符串表达式,矩阵乘
- s8 u4 S! F+ A' i+ N& w3 }
//wchar_t ForStr[]=L"o{new[matrix,2,3,data: 0.,1.,2.;3.,4.,5.].*new[matrix,2,3,data: 1.,2.,3.;4.,5.,6.]}";//字符串表达式,矩阵点乘
8 B( F" I0 W6 t3 C
LuData Val;
& O4 E& H" s8 t: x
if(!InitLu()) return; //初始化Lu
- O6 N8 B7 m- e
while(LockKey(Matrix,DelMatrix,OpMatrix)){Matrix++;} //锁定一个键,用于存储矩阵扩展类型
. D* L- k1 M' k) M3 M/ J" B s8 k
$ k0 L/ C! r ~- j/ _/ _! K
Val.BType=luStaData_int64; Val.VType=luStaData_int64; Val.x=Matrix; //定义整数常量
# j3 U' W1 \& {7 h! z+ j' t9 r
SetConst(L"matrix",&Val); //设置整数常量
. r% I5 A) Z: V1 G8 _0 D
InsertKey("\0\0\0\0",4,luPubKey_User,LuMessage,NULL,NULL,1,v); //使Lu运行时可输出函数信息
$ p! S C$ T. f- d3 t$ X9 j3 F. o9 G
wcout.imbue(locale("chs")); //设置输出的locale为中文
) \" k. B0 k! l" p2 _6 Q- \
+ t0 Y; M1 N1 e9 S' | S
ErrCode=LuCom(ForStr,0,0,0,hFor,nPara,pPara,ErrBegin,ErrEnd); //编译表达式
5 }2 S+ S( c/ Q& w+ ? h5 L7 F
if(ErrCode)
. P" ? Z6 k" k P/ ~+ `
{
3 ]3 ^ k4 K) Q6 f5 F
wcout<<L"表达式有错误!错误代码:"<<ErrCode<<endl;
\: k+ I- _ p/ N4 U! q% \0 V, U
}
/ F# z8 F7 n5 T9 u$ {/ u6 a
else
: e3 [2 a% J8 x# |2 g F/ b3 p
{
) Y3 M/ E) J1 P9 k- X t! b- m
LuCal(hFor,pPara); //计算表达式的值
4 a" T! U2 T! b
}
5 b5 L# q6 W9 T% i' N0 x* h: z9 B
LockKey(Matrix,NULL,OpMatrix);//解锁键Matrix,本例中,该函数可以不用
- }: _ T- x4 {7 L
FreeLu(); //释放Lu
# n) t' G7 _$ K3 Y {
}
复制代码
习题:
- H E7 }( o- x8 |# W
2 e% [8 o: W: u0 k( |, {9 j2 T7 L
(1)自定义矩阵的加、减、左除、右除、点左除等运算,自编测试字符串代码,重新编译运行程序,观察计算结果。
* [) S# l: Q4 Q4 s6 t2 W
2 s. F! o6 @4 C
(2)小矩阵乘效率测试。编译运行以下Lu字符串代码:
main(:a,b,c,d,t,i)=
y+ c- N7 d" V
a=new[matrix,2,2,data:1.,2.,2.,1.],
+ s& w0 j% v- z- ^% ~ M( l6 A
b=new[matrix,2,2,data:2.,1.,1.,2.],
+ T( k2 x# [* L) ?5 M
c=new[matrix,2,2,data:2/3.,-1/3.,-1/3.,2/3.],
; W6 c5 J g8 e% F! `4 A& @
t=clock(),
; c7 s" C+ ^/ s
d=a*b, i=0, while{i<1000000, d=d*c*b, i++},
6 x; H2 U; j) e( q. c$ ]* B! @0 V
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,data:1.1,2.,2.,1.], b=new[matrix,2,2,data:2.,1.,1.,2.], c=new[matrix,2,2,data: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.
8 g6 i1 P9 f3 O' ]6 ~6 Z
5. 4.
$ K9 j0 u. H) Y: F2 f W
time=0.875 seconds.
5 K) Z% O0 ?; v# |! H- c
请按任意键继续. . .
复制代码
Matlab 2009a 代码:
a=[1.,2.;2.,1.];
+ l; U& P4 O& d1 T7 y! S3 M
b=[2.,1.;1.,2.];
) r- b! m& _, R0 y6 x2 G
c=[2/3.,-1/3.;-1/3.,2/3.];
5 |8 C: M9 }1 S( ?0 N) W
tic,
- y6 F1 ]2 Y3 V0 }1 V: |
d=a*b;
2 {: ^2 J3 `* a3 |6 S
for i=1:1000000
9 i; Z% D9 X, Q1 U1 j
d=d*c*b;
- Q; _; f0 q- M" y% J/ o
end
1 _5 i5 ?1 Z0 X5 W2 l5 Z( T2 z/ n
d,
3 V4 w" K$ U ?& @# y1 {% G
toc
复制代码
结果:
d =
W( Y( N. A0 Q8 a* H' k- ~
4 5
; {. Y1 _- Y' L
5 4
) r# K; u5 K+ ^) v2 t8 e1 D
Elapsed time is 2.903034 seconds.
复制代码
本例矩阵乘效率测试,Lu的速度超过了Matlab,主要在于Lu有更高的动态对象管理效率。
: I g! e% w3 B
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5