数学建模社区-数学中国
标题:
Lu基于系统内置对象创建扩展数据类型,小矩阵乘效率测试
[打印本页]
作者:
forcal
时间:
2011-10-23 09:37
标题:
Lu基于系统内置对象创建扩展数据类型,小矩阵乘效率测试
本例中,我们将基于系统内置实数数组创建矩阵(matrix)类型,即:基本类型为luDynData_realarray(标识实数数组),扩展类型为matrix(标识矩阵)。为了简单,我们仅处理二维实数数组即矩阵类型。
- [2 W0 d! \: J2 Z
# j B) G$ l+ t- C
基本要点:
5 u% e9 W5 x" z; f5 Z% q! p/ m
% G) ~( o. L, Q1 l: h
(1)为扩展类型matrix编写运算符重载函数OpMatrix。
3 w; e; r- J# ?& {
3 a$ s1 U6 a6 I4 S4 F
(2)用函数LockKey将重载函数OpMatrix注册到Lu,锁定的键的类型即为matrix,要注册为常量,以便于使用。
( z" u# w6 q) S; e
' F9 p, {) b3 | b, M: [
(3)为扩展类型matrix编写其他操作函数(本例未提供)。
6 ^5 B* l7 m! b5 d2 N
" v5 Y5 O& c) z' L( B; Q3 c! f7 e
(4)用函数LockKey解锁键matrix(本例中,程序退出时会自动解锁,故可以不用)。
#include <windows.h>
% ~% v" ~( n/ h
#include <iostream>
. C: d) ^0 a" }( k/ \6 a5 Y
#include <math.h>
5 r3 ?2 e/ M+ G* a8 H
#include "lu32.h"
, f* u$ [% o3 J$ l3 N
7 r& a7 e6 k: Q4 i3 ?5 m6 ^) h
#pragma comment( lib, "lu32.lib" )
9 y: K5 Z$ e6 E9 v
8 o c% c: { |1 T1 a
using namespace std;
1 h H( ]2 Q$ Z! Y* Y5 }
. E! M, c( w; ^6 v4 t h
luKEY Matrix=-1000; //标识矩阵类型,最终的Matrix由LockKey决定
( B% I& p/ i: U4 U2 X
* z: j( U9 r4 u/ f2 u3 w+ l
void _stdcall LuMessage(wchar_t *pch)//输出动态库信息,该函数注册到Lu,由Lu二级函数调用
+ \& Y f; _' i; X' J u3 M
{
5 }4 M2 B3 {# P% y
wcout<<pch;
8 [0 a' n) y8 [$ y
}
8 D1 e1 G' f, t8 J6 L: k
void _stdcall DelMatrix(void *me) //用于LockKey函数,因为是基于系统内置实数数组创建矩阵,故该函数什么也不做
9 i) J+ O9 s/ f* q% Y! W( T0 Q
{
. Y8 H; o) O. G" G9 z' Y8 _7 |) Y
}
) w, ^/ h1 s( o' u+ U
LuData _stdcall OpMatrix(luINT mm,LuData *xx,void *hFor,int theOperator) //运算符重载函数,用于LockKey函数
1 d2 c% `- U7 D, M
{
$ m# Z8 t i. y+ |5 v) q* A
LuData a;
" o" q! @) W. n0 N; T6 @
luRealArray *pRealArray1,*pRealArray2,*pRealArray3;
+ W* l8 q$ [5 o6 I5 l) T# k
luVOID i,j,k,m,n,u,v;
# c1 P8 o; W) S8 s6 k' C0 T
double *pa,*pb,*pc;
0 {6 ]9 ~- u9 ~; {3 L
luMessage pMessage;
& z# l* W& r2 D7 F
wchar_t wchNum[32];
! N, E0 K0 [; u4 V+ ?8 R" b. q
char chNum[32];
" i9 `9 r5 Z, @. P. g2 {: q
a.BType=luStaData_nil; a.VType=luStaData_nil; a.x=0;
) Y2 _9 R5 d& o, V' E
switch(theOperator)
/ _! J, C# Q) I7 b
{
2 X8 r* ~! Q; h. |: _: m
case 2: //重载运算符*
# ~' D' d# s7 \; J, K1 ~7 {7 m
pRealArray1=(luRealArray *)SearchKey((char *)&(xx->x),sizeof(luVOID),luDynData_realarray);
/ W4 [2 r3 s' |+ _: V) R7 f
pRealArray2=(luRealArray *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),luDynData_realarray);
0 ?) |+ D& I9 E; e! f, D
if(!pRealArray1 || !pRealArray2) break; //对象句柄无效,不是实数数组
z7 i/ b+ Y( N# e' u
if(pRealArray1->DimLen!=2 || pRealArray2->DimLen!=2) break; //不是二维实数数组(矩阵)
6 D1 j- Z# g4 ]; F* y
if(pRealArray1->Dim[1]!=pRealArray2->Dim[0]) break; //维数不匹配
1 t8 ?; C c/ s! f: _8 }
pRealArray3=(luRealArray *)NewSysObj(luDynData_realarray,pRealArray1->Dim[0]*pRealArray2->Dim[1],2); //创建矩阵对象
$ q5 j* q7 K2 B/ v% T/ l3 L/ [
if(!pRealArray3) break;
7 r# s3 h* u k. `, g u
pRealArray3->Dim[0]=pRealArray1->Dim[0]; pRealArray3->Dim[1]=pRealArray2->Dim[1]; //设置矩阵维数大小
1 a$ \; |) K* f- c$ b
pa=pRealArray1->Array; pb=pRealArray2->Array; pc=pRealArray3->Array;
9 O4 C. W% A3 Z
m=pRealArray1->Dim[0]; n=pRealArray1->Dim[1]; k=pRealArray2->Dim[1];
8 W" a B. Q& l9 J0 ]4 M
for(i=0; i<m; i++) //矩阵乘
8 i9 h0 q& v; X+ V" o+ n, K& Q& n& A
{
& B, c1 V1 C. j, y2 I
for(j=0; j<k; j++)
/ l6 _; f1 V# V" |! X- ~" W
{
: }6 ^6 v) ]& X) h
u=i*k+j; pc[u]=0.0;
: B. O# f/ m' s5 h7 |6 [% m* F% u
for (v=0; v<n; v++)
* `# R/ Y, l" s$ L
{
" T# S$ |- L# A% k
pc[u]=pc[u]+pa[i*n+v]*pb[v*k+j];
4 y1 y& E; K2 g6 c2 z: n
}
: G4 N% l( |1 ?/ A
}
, @9 b; S1 @0 N; I8 R
}
$ y! g, Q, O7 l+ p0 b" r
FunReObj(hFor); //告诉Lu,返回一个动态对象
. E1 Y4 l) Y1 S9 o0 s
a.BType=luDynData_realarray; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pRealArray3;
% |3 `4 g! Y9 l9 E3 v
break;
/ P* f( B' _+ m5 `+ I8 q+ M
case 25: //重载运算符.*
4 M/ r% ~7 U' J4 E- s+ }* U
pRealArray1=(luRealArray *)SearchKey((char *)&(xx->x),sizeof(luVOID),luDynData_realarray);
P: ?- R6 ]' ?. ]5 I4 e
pRealArray2=(luRealArray *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),luDynData_realarray);
- s4 O" T/ t* c" R+ O- f" R) J
if(!pRealArray1 || !pRealArray2) break; //对象句柄无效,不是实数数组
/ ]1 s1 B& W) ?, r8 F5 p X0 w
if(pRealArray1->DimLen!=2 || pRealArray2->DimLen!=2) break; //不是二维实数数组(矩阵)
; D0 {6 [6 e) u" g7 x3 m
if(pRealArray1->Dim[0]!=pRealArray2->Dim[0] || pRealArray1->Dim[1]!=pRealArray2->Dim[1]) break; //维数不相同
* k( B1 F9 p8 ?% W( i, [$ j
pRealArray3=(luRealArray *)NewSysObj(luDynData_realarray,pRealArray1->ArrayLen,2); //创建矩阵对象
" J+ K3 R( k' V7 a, U' E' ~0 z: ^
if(!pRealArray3) break;
7 U, G5 Z* H+ C0 A) ~ q9 t, D
pRealArray3->Dim[0]=pRealArray1->Dim[0]; pRealArray3->Dim[1]=pRealArray1->Dim[1]; //设置矩阵维数大小
: p, ]) ^- Y; O
for(i=0;i<pRealArray1->ArrayLen;i++) pRealArray3->Array[i]=pRealArray1->Array[i]*pRealArray2->Array[i];//矩阵点乘
: `" ~' t8 H4 j2 s q- H
FunReObj(hFor); //告诉Lu,返回一个动态对象
( z0 o- E4 u" j7 R1 u
a.BType=luDynData_realarray; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pRealArray3;
/ W" x M& W3 q! z2 S
break;
3 s" A$ D; f. b1 ?) ~7 W( M
case 46: //重载函数new
: p R" R3 s, [% j# ?7 j+ }
a=ExeOperator(mm,xx,hFor,theOperator,luDynData_realarray); //直接调用基本类型luDynData_realarray的new函数
2 T3 u, f* e% V3 x# O
if(a.VType==luDynData_realarray) a.VType=Matrix; //设置扩展类型为自定义的Matrix类型
2 _3 a2 x5 E U" Y* H+ A0 O
break;
" a0 w) q8 {) J: Z4 ^2 t
case 49: //重载函数o
6 x/ p. F; s2 I7 S3 M2 s
pMessage=(luMessage)SearchKey("\0\0\0\0",sizeof(luVOID),luPubKey_User);
0 R0 q( v: n7 V9 h- _& i
if(!pMessage) break;
$ s3 j& Q( }3 ?. X3 J, c g- F. U
pRealArray1=(luRealArray *)SearchKey((char *)&(xx->x),sizeof(luVOID),luDynData_realarray);
* \9 z# W" M. t- a, k) m
if(!pRealArray1) break; //对象句柄无效,不是实数数组
! B1 i) F7 g% h
if(pRealArray1->DimLen!=2) break; //不是二维实数数组(矩阵)
4 c' f3 h6 K: i8 \( a
pa=pRealArray1->Array;
% H0 H' o6 D/ [, U' R1 {7 T1 P
m=pRealArray1->Dim[0]; n=pRealArray1->Dim[1]; k=0;
$ I7 x5 @/ d" X. g ?* j
for(i=0; i<m; i++) //输出矩阵
+ h3 B5 P5 b& x7 U7 w* Z, M
{
; ?8 ~4 c: }: E2 f2 n5 d5 ~$ t
pMessage(L"\r\n"); k+=2;
! r+ Z5 r; x* `
for(j=0; j<n; j++)
& D; g% q7 y4 A: _( E. h
{
3 \" Z# z* ~# k3 }
_gcvt_s(chNum,pa[i*n+j],16);
9 h' X* l! b5 |$ T
for(u=0;chNum[u];u++) {wchNum[u]=chNum[u]; k++;}
\1 M$ A, e6 c' K, m* M1 N
wchNum[u]='\0';
: R; L& B, i7 M# `2 Z5 M: W. H( P
pMessage(wchNum); pMessage(L" "); k+=2;
1 b" p* T/ M+ }
}
1 t0 O" @; P% K7 |% v6 v( \
}
8 L4 H5 o6 O4 l. j) a
pMessage(L"\r\n"); k+=2;
/ u$ o4 D5 L% o
a.BType=luStaData_int64; a.VType=luStaData_int64; a.x=k; //按函数o的要求,返回输出的字符总数
6 A4 X& W/ r2 ]3 l) F2 Z1 z
break;
+ p$ ~( q4 m- v" `6 f
default:
; G$ Q1 s; G6 u: V
break;
4 g& H+ J$ i* d! u
}
: B. Y1 Z5 P- ~- e
return a;
2 [& n5 w1 a( `1 `- \7 Q, ~! q( V
}
0 A+ ]9 |* s9 q6 ^8 j; B4 |2 c
void main(void)
2 A! i. ~1 Z9 r
{
, B* I; L; S& w
void *hFor; //表达式句柄
- q& J5 r" A" Z! E: _
luINT nPara; //存放表达式的自变量个数
/ u' i4 i, A! E/ X. F
LuData *pPara; //存放输入自变量的数组指针
3 [3 i# u% G- x! _- j! K' L% ]
luINT ErrBegin,ErrEnd; //表达式编译出错的初始位置和结束位置
( x$ O2 Z; A* J: D8 v
int ErrCode; //错误代码
, \/ w5 q2 ^9 T N
void *v;
# r9 v+ A/ y3 [& p
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.]}";//字符串表达式,矩阵乘
: c" ~/ W4 o% ~& n& y! R
//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.]}";//字符串表达式,矩阵点乘
! r/ k1 t/ f5 U, Z
LuData Val;
+ I, ]7 I4 D9 w b6 `$ U1 a
if(!InitLu()) return; //初始化Lu
o& ]9 j6 U# z ~8 S: e! Y
while(LockKey(Matrix,DelMatrix,OpMatrix)){Matrix++;} //锁定一个键,用于存储矩阵扩展类型
8 f6 ^& Y! Q, @- H& z( C
3 Q9 y- i- Q1 s' Q- i6 Z
Val.BType=luStaData_int64; Val.VType=luStaData_int64; Val.x=Matrix; //定义整数常量
, q6 Z1 c- t) p: Z/ L; t5 p
SetConst(L"matrix",&Val); //设置整数常量
6 Z: u, I ?/ ^
InsertKey("\0\0\0\0",4,luPubKey_User,LuMessage,NULL,NULL,1,v); //使Lu运行时可输出函数信息
) @2 M: M4 P8 E$ D7 D+ Y
wcout.imbue(locale("chs")); //设置输出的locale为中文
' K" |- W9 q5 w
- ]2 g6 Y0 m/ C, x& g, V( K
ErrCode=LuCom(ForStr,0,0,0,hFor,nPara,pPara,ErrBegin,ErrEnd); //编译表达式
# _4 `, N4 Q3 q5 U0 f9 O
if(ErrCode)
5 A8 L& ^; d/ B: K$ |% M; O+ w
{
7 J5 n( J g& ]6 V( v3 v7 r
wcout<<L"表达式有错误!错误代码:"<<ErrCode<<endl;
$ r) i* S( F& ]) I) b) ?
}
2 Q4 M2 ?' |$ ^8 `1 M) ]: s
else
7 Z' p, Q6 y; L( {$ P5 n
{
& ?4 J9 ~& S) X; E' I0 o
LuCal(hFor,pPara); //计算表达式的值
1 _) {1 N/ [9 _0 R0 a$ s
}
6 ]9 t o/ o$ Z& S
LockKey(Matrix,NULL,OpMatrix);//解锁键Matrix,本例中,该函数可以不用
0 Z* c- v' c' j; N
FreeLu(); //释放Lu
9 m" q( c& u8 l! I b! I! t1 t9 G2 X
}
复制代码
习题:
7 o u2 F; i3 D2 k1 W3 ~" q
& D8 W/ T! o# Z* [% y' n: |
(1)自定义矩阵的加、减、左除、右除、点左除等运算,自编测试字符串代码,重新编译运行程序,观察计算结果。
: P% R' M$ ~7 Y1 N' w
0 g+ B/ N2 S" |
(2)小矩阵乘效率测试。编译运行以下Lu字符串代码:
main(:a,b,c,d,t,i)=
7 I2 R) c' P' _
a=new[matrix,2,2,data:1.,2.,2.,1.],
$ }- W# h4 f) e* |8 b
b=new[matrix,2,2,data:2.,1.,1.,2.],
# S2 w/ b: E( ~! j) l
c=new[matrix,2,2,data:2/3.,-1/3.,-1/3.,2/3.],
z1 j+ ]9 D) V% p
t=clock(),
- s' a6 J8 \! B
d=a*b, i=0, while{i<1000000, d=d*c*b, i++},
; v& y0 G6 b- ~! m5 E0 Y
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.
' }3 L: w5 c* ~/ E, v7 U/ b @
5. 4.
$ f% Q2 ?9 K! E9 y$ c
time=0.875 seconds.
/ O2 t6 y. B$ S0 p; r
请按任意键继续. . .
复制代码
Matlab 2009a 代码:
a=[1.,2.;2.,1.];
7 _+ b) C. |: Y3 [
b=[2.,1.;1.,2.];
, O+ u _2 V3 M- r+ i$ s
c=[2/3.,-1/3.;-1/3.,2/3.];
9 k' t" I7 }. |( x, P' S
tic,
7 P+ L% \' P4 B- w
d=a*b;
+ b+ q) h( \4 i: O
for i=1:1000000
v' }. F2 ~% ` `% g9 U' A% N* V* `$ x
d=d*c*b;
/ H# ~# {6 s' B o A
end
3 f( g8 a# B1 [! C, B
d,
+ n. x& W6 ~, m
toc
复制代码
结果:
d =
% X7 @' i" }9 X6 ~' E. @# B& U4 @
4 5
- | C& D2 m- [) f# e C6 E
5 4
6 R5 I; E3 r" ?1 z5 o
Elapsed time is 2.903034 seconds.
复制代码
本例矩阵乘效率测试,Lu的速度超过了Matlab,主要在于Lu有更高的动态对象管理效率。
' r0 P6 f* A7 d, e0 x9 e
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5