数学建模社区-数学中国
标题:
Lu基于系统内置对象创建扩展数据类型,小矩阵乘效率测试
[打印本页]
作者:
forcal
时间:
2011-10-23 09:37
标题:
Lu基于系统内置对象创建扩展数据类型,小矩阵乘效率测试
本例中,我们将基于系统内置实数数组创建矩阵(matrix)类型,即:基本类型为luDynData_realarray(标识实数数组),扩展类型为matrix(标识矩阵)。为了简单,我们仅处理二维实数数组即矩阵类型。
, E/ ~6 b3 u# O4 J3 C# ?
+ I* x( @. g1 w% k1 a
基本要点:
% y% ^" G: [ K$ P
- c* H6 [- g4 L, W; @9 ^, g) f9 Z
(1)为扩展类型matrix编写运算符重载函数OpMatrix。
) H) }# n0 C$ q0 @
, M8 X( U ^) i, B7 k& }
(2)用函数LockKey将重载函数OpMatrix注册到Lu,锁定的键的类型即为matrix,要注册为常量,以便于使用。
$ f! ~' x& l, G" Q6 `- x
+ J$ w9 Y' O- D7 w. O8 q
(3)为扩展类型matrix编写其他操作函数(本例未提供)。
5 P- B/ e$ E, j0 \- ]
" Z+ \% g* ?7 q/ \4 d+ [9 n. n
(4)用函数LockKey解锁键matrix(本例中,程序退出时会自动解锁,故可以不用)。
#include <windows.h>
0 u/ j! @/ z2 r6 X6 t4 W3 b
#include <iostream>
7 M8 J! z% n$ \4 L) W
#include <math.h>
+ F2 `; T1 _ h! W# v& D
#include "lu32.h"
- T* H/ y5 e7 G! r! }% h& q1 j: ]
. `$ h2 z* Y$ m- T
#pragma comment( lib, "lu32.lib" )
* b1 u) _" F K8 V$ J/ ~
; p+ ~$ }# q, I
using namespace std;
& y/ u) g8 X O+ w
" B9 W0 e" ~& m$ l9 l& e
luKEY Matrix=-1000; //标识矩阵类型,最终的Matrix由LockKey决定
! h0 v- O9 D- R- ]/ ~
3 I5 d2 A/ e* i, \- Z) H' o: x
void _stdcall LuMessage(wchar_t *pch)//输出动态库信息,该函数注册到Lu,由Lu二级函数调用
9 R1 V& O5 p% p
{
2 A6 N7 B Z" a* T0 H" z) K; ^
wcout<<pch;
% u7 V: \4 c4 x4 q6 d
}
& d( b& }$ w/ z0 ^
void _stdcall DelMatrix(void *me) //用于LockKey函数,因为是基于系统内置实数数组创建矩阵,故该函数什么也不做
1 i0 i9 K8 x5 @6 o. n( O
{
) N6 n$ _8 @4 V7 ]! L
}
0 g) n9 n/ K- G. i- ^1 q2 {/ M) q( J: s/ M
LuData _stdcall OpMatrix(luINT mm,LuData *xx,void *hFor,int theOperator) //运算符重载函数,用于LockKey函数
9 J/ i& S s+ F0 y
{
1 v4 e, V: B! W3 N8 E" Q r
LuData a;
: B+ o: W; R) V% H6 y2 d4 n
luRealArray *pRealArray1,*pRealArray2,*pRealArray3;
5 R% W2 S, h4 h4 `2 D+ }
luVOID i,j,k,m,n,u,v;
& v8 I( S/ w9 y# g
double *pa,*pb,*pc;
$ x, `; N+ h, A" `+ O2 }7 ~
luMessage pMessage;
6 T- N( ]$ R& d: x/ \$ G5 E4 o
wchar_t wchNum[32];
7 V- {" {5 [9 y- i8 q6 D
char chNum[32];
0 I# I- Y+ ?4 R. Z) p3 F2 X
a.BType=luStaData_nil; a.VType=luStaData_nil; a.x=0;
* W ^1 H2 U a. P
switch(theOperator)
4 u# e1 h8 i9 F% O: `+ p' ?' u9 V
{
' f8 a' {; ~& j% H2 J1 y
case 2: //重载运算符*
% V3 u' R2 j6 r/ R
pRealArray1=(luRealArray *)SearchKey((char *)&(xx->x),sizeof(luVOID),luDynData_realarray);
* F' K2 v- h O- s
pRealArray2=(luRealArray *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),luDynData_realarray);
9 b9 K* i. H# c
if(!pRealArray1 || !pRealArray2) break; //对象句柄无效,不是实数数组
5 _2 w3 w& @8 V0 n. ~! y9 N7 A- b
if(pRealArray1->DimLen!=2 || pRealArray2->DimLen!=2) break; //不是二维实数数组(矩阵)
1 C, e" _+ s! ^3 X+ B( b
if(pRealArray1->Dim[1]!=pRealArray2->Dim[0]) break; //维数不匹配
7 r4 a/ K2 \% W( @
pRealArray3=(luRealArray *)NewSysObj(luDynData_realarray,pRealArray1->Dim[0]*pRealArray2->Dim[1],2); //创建矩阵对象
: y$ B- N8 V3 B. e2 o" H
if(!pRealArray3) break;
, A' J1 ^4 h4 f- a
pRealArray3->Dim[0]=pRealArray1->Dim[0]; pRealArray3->Dim[1]=pRealArray2->Dim[1]; //设置矩阵维数大小
6 |9 G% W7 E; b/ ~1 \8 x3 b
pa=pRealArray1->Array; pb=pRealArray2->Array; pc=pRealArray3->Array;
5 E, ~) t( |7 a$ P# i* F
m=pRealArray1->Dim[0]; n=pRealArray1->Dim[1]; k=pRealArray2->Dim[1];
) L! m+ u9 L6 G: F
for(i=0; i<m; i++) //矩阵乘
; }0 ?4 l3 s3 m) B
{
5 s4 M+ ^0 N$ q
for(j=0; j<k; j++)
/ U" W" \1 K) e* H7 e
{
9 g" o/ \% a5 i# ~) J
u=i*k+j; pc[u]=0.0;
" W& M9 M: p7 c7 ~; g- S
for (v=0; v<n; v++)
3 U1 e O$ x/ e2 ?" B2 l7 D
{
5 J4 Q0 f2 {; j, w
pc[u]=pc[u]+pa[i*n+v]*pb[v*k+j];
9 L5 t) a/ i5 p: X4 b
}
/ x' J7 d! d( e( I, j& K3 _
}
6 x# k9 p! M, J, O, v6 c- S8 _, g
}
1 x: i& g! E* m# G1 F3 G
FunReObj(hFor); //告诉Lu,返回一个动态对象
7 F! k0 J2 Y* i1 l" K& W5 O3 B- B( e7 x
a.BType=luDynData_realarray; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pRealArray3;
' }% `; x0 T- M& j
break;
4 x2 k8 v# w7 M" C' _6 h. w
case 25: //重载运算符.*
; A# r5 ~# g: C2 B+ ^# c
pRealArray1=(luRealArray *)SearchKey((char *)&(xx->x),sizeof(luVOID),luDynData_realarray);
. S `2 n p" `9 E/ `) B4 ^
pRealArray2=(luRealArray *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),luDynData_realarray);
* Y: }& U$ H+ G4 s7 G
if(!pRealArray1 || !pRealArray2) break; //对象句柄无效,不是实数数组
# J; W) } W$ f* j
if(pRealArray1->DimLen!=2 || pRealArray2->DimLen!=2) break; //不是二维实数数组(矩阵)
/ D( v; n* C, p1 v) ~; U5 x* t
if(pRealArray1->Dim[0]!=pRealArray2->Dim[0] || pRealArray1->Dim[1]!=pRealArray2->Dim[1]) break; //维数不相同
. H1 |- n6 ]- K' U- `
pRealArray3=(luRealArray *)NewSysObj(luDynData_realarray,pRealArray1->ArrayLen,2); //创建矩阵对象
" f& A: O; X5 Y' W, L+ S
if(!pRealArray3) break;
% ^$ Z' X3 q% Q
pRealArray3->Dim[0]=pRealArray1->Dim[0]; pRealArray3->Dim[1]=pRealArray1->Dim[1]; //设置矩阵维数大小
' m" s" Y& j3 u
for(i=0;i<pRealArray1->ArrayLen;i++) pRealArray3->Array[i]=pRealArray1->Array[i]*pRealArray2->Array[i];//矩阵点乘
; k( w: j" W# x/ h2 o7 ?6 V
FunReObj(hFor); //告诉Lu,返回一个动态对象
e4 h0 h v3 W2 V
a.BType=luDynData_realarray; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pRealArray3;
; G' g& P4 G [1 |4 k. f" }
break;
8 I% X; [) F0 K( C
case 46: //重载函数new
! b+ R' T& _* p: }4 J$ X4 A# b
a=ExeOperator(mm,xx,hFor,theOperator,luDynData_realarray); //直接调用基本类型luDynData_realarray的new函数
. W) P6 H$ v" |7 i
if(a.VType==luDynData_realarray) a.VType=Matrix; //设置扩展类型为自定义的Matrix类型
- K5 O( ^- Y. {( r+ W( t4 U+ p
break;
! Q$ g( Q4 e; S9 I' E
case 49: //重载函数o
9 Z- A: R& }6 u3 \6 N
pMessage=(luMessage)SearchKey("\0\0\0\0",sizeof(luVOID),luPubKey_User);
& }" v5 [4 v1 J% l' t* r3 |$ \
if(!pMessage) break;
( C9 `3 k% N* w& w% [: t) J4 e K
pRealArray1=(luRealArray *)SearchKey((char *)&(xx->x),sizeof(luVOID),luDynData_realarray);
4 V$ K6 D+ C' ~* k' [
if(!pRealArray1) break; //对象句柄无效,不是实数数组
" x; {5 d3 e' x) I6 O
if(pRealArray1->DimLen!=2) break; //不是二维实数数组(矩阵)
: t- c9 I9 {, E4 q. c
pa=pRealArray1->Array;
7 m( h6 ]: m- L* H
m=pRealArray1->Dim[0]; n=pRealArray1->Dim[1]; k=0;
/ R, P. a [6 {# W# A( ], f
for(i=0; i<m; i++) //输出矩阵
/ _4 w+ [4 U/ d/ D
{
. q' i9 \( x4 ~
pMessage(L"\r\n"); k+=2;
6 s* R! L# v- H. {6 ^7 i: j0 h' n
for(j=0; j<n; j++)
9 M/ L+ D* N0 V2 G1 P
{
( J2 k8 N- `9 U0 u4 `1 q
_gcvt_s(chNum,pa[i*n+j],16);
8 N% z0 `: O# a& H; G& ^) J
for(u=0;chNum[u];u++) {wchNum[u]=chNum[u]; k++;}
/ t, S! e. Q3 q
wchNum[u]='\0';
1 z7 q& S/ F C% {# I/ q
pMessage(wchNum); pMessage(L" "); k+=2;
, f6 S( {/ `$ n) U
}
/ q0 T9 Q w2 k7 L0 y! u
}
% Z: L5 W/ [* h6 O+ H7 W0 D6 v5 a
pMessage(L"\r\n"); k+=2;
& P3 c8 @0 f5 A" q" C D
a.BType=luStaData_int64; a.VType=luStaData_int64; a.x=k; //按函数o的要求,返回输出的字符总数
* k- z& m1 K* T
break;
! P- L" q* F$ j6 X% G( J. e9 d- u
default:
7 R. {+ V% a: Q
break;
, E- v" J- {+ o F
}
n0 W. V9 n% d! W' _3 t
return a;
" X) M, W& u- z# m% j
}
) M* S* ]/ S9 K. E, \$ m7 o: x
void main(void)
$ Y3 l5 K4 [2 L9 H* r, J+ a% j/ U: j5 P
{
& N# a! `+ _" E( V2 Q5 ?
void *hFor; //表达式句柄
, ]% F( r& u& _- z" F1 g
luINT nPara; //存放表达式的自变量个数
; w% D; B0 f* h7 s2 ]6 d
LuData *pPara; //存放输入自变量的数组指针
" H2 \- T1 Q) ~$ t
luINT ErrBegin,ErrEnd; //表达式编译出错的初始位置和结束位置
1 x0 C6 X1 p# W1 s) T
int ErrCode; //错误代码
* I2 I, j- Y7 U
void *v;
, w$ |* |; X3 @2 v, X
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.]}";//字符串表达式,矩阵乘
& t. s! ^4 T. b; A" X3 K+ ^" k
//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.]}";//字符串表达式,矩阵点乘
, [$ w# F0 b4 D) ^! p/ \: ]
LuData Val;
4 M* @) }+ s8 O1 Q6 @6 l; ~
if(!InitLu()) return; //初始化Lu
) y3 d& z1 @7 r. B' t# l, s) d3 @
while(LockKey(Matrix,DelMatrix,OpMatrix)){Matrix++;} //锁定一个键,用于存储矩阵扩展类型
9 ?( k% ~, k3 p
P' P# U9 U* [: L4 e9 i4 M
Val.BType=luStaData_int64; Val.VType=luStaData_int64; Val.x=Matrix; //定义整数常量
3 | l3 p# H$ | e4 D, Y
SetConst(L"matrix",&Val); //设置整数常量
/ N5 O6 T' t" Y2 k5 o
InsertKey("\0\0\0\0",4,luPubKey_User,LuMessage,NULL,NULL,1,v); //使Lu运行时可输出函数信息
& w1 l, |! l! T: k n- h
wcout.imbue(locale("chs")); //设置输出的locale为中文
1 Z; p! U$ R( v
- f$ E: S5 B, i# e% K
ErrCode=LuCom(ForStr,0,0,0,hFor,nPara,pPara,ErrBegin,ErrEnd); //编译表达式
. g7 b/ w% y+ a7 b
if(ErrCode)
/ b3 h/ `3 j( c) L$ r' A5 V
{
3 S- m8 k6 L# N" S: l
wcout<<L"表达式有错误!错误代码:"<<ErrCode<<endl;
, c; j, \5 n1 {2 s7 U2 D
}
* |7 ~$ q) S# k& W. u
else
$ X0 [$ d" G% K- Z% Z# {6 {8 V6 m
{
9 H2 Y+ b# q' x" }- \4 c2 F* e
LuCal(hFor,pPara); //计算表达式的值
1 M9 `8 ?8 M6 |( ?" i! _9 E8 `4 G' F
}
1 Z! I. X( c; {
LockKey(Matrix,NULL,OpMatrix);//解锁键Matrix,本例中,该函数可以不用
& W: P, g! K/ H7 [- B
FreeLu(); //释放Lu
5 m% e: }' {; v& U* T5 q: R
}
复制代码
习题:
8 x; U/ d2 }( q, I
8 @/ z5 O) p7 k
(1)自定义矩阵的加、减、左除、右除、点左除等运算,自编测试字符串代码,重新编译运行程序,观察计算结果。
5 \4 T/ I7 Q" Z& d7 d" P( ^( Y
7 C4 W* u: c$ y* ?
(2)小矩阵乘效率测试。编译运行以下Lu字符串代码:
main(:a,b,c,d,t,i)=
7 c1 f5 g4 ^, m* F
a=new[matrix,2,2,data:1.,2.,2.,1.],
) }' o4 ?, ^, {, f6 t: ?) A' v
b=new[matrix,2,2,data:2.,1.,1.,2.],
. c$ X4 J' V' N9 ]
c=new[matrix,2,2,data:2/3.,-1/3.,-1/3.,2/3.],
- T: x u5 R6 k/ V
t=clock(),
% A/ R, a1 k/ q b
d=a*b, i=0, while{i<1000000, d=d*c*b, i++},
1 n) E/ l, ]3 C: c/ c" 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.
/ r8 e8 |* R5 G2 e
5. 4.
3 F- K2 K9 V! K6 c, N
time=0.875 seconds.
$ k# k! G( c8 o: N2 i
请按任意键继续. . .
复制代码
Matlab 2009a 代码:
a=[1.,2.;2.,1.];
3 X$ r2 C( L: T/ ]
b=[2.,1.;1.,2.];
8 w5 ~* m f [6 Q% j6 N
c=[2/3.,-1/3.;-1/3.,2/3.];
/ L" ?$ K! y2 s/ z
tic,
$ R( f- N0 I9 r! ~$ Z4 ?
d=a*b;
2 F7 w/ d' {) o/ z& J4 I
for i=1:1000000
5 f' Y) L5 u0 [) H {
d=d*c*b;
0 @3 v; C, w4 ] R
end
5 @$ N$ o2 N3 D0 C
d,
- x7 O% t* e; }. _( A
toc
复制代码
结果:
d =
5 ]6 g: P2 i4 a5 t4 @% w* v
4 5
& d& P& y! k: C! C) C" K
5 4
" b0 |$ q/ k: X) ?! z2 g; t( j9 N
Elapsed time is 2.903034 seconds.
复制代码
本例矩阵乘效率测试,Lu的速度超过了Matlab,主要在于Lu有更高的动态对象管理效率。
$ v# f9 k" P: I/ A$ i2 I
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5