数学建模社区-数学中国
标题:
Lu基于系统内置对象创建扩展数据类型,小矩阵乘效率测试
[打印本页]
作者:
forcal
时间:
2011-10-23 09:37
标题:
Lu基于系统内置对象创建扩展数据类型,小矩阵乘效率测试
本例中,我们将基于系统内置实数数组创建矩阵(matrix)类型,即:基本类型为luDynData_realarray(标识实数数组),扩展类型为matrix(标识矩阵)。为了简单,我们仅处理二维实数数组即矩阵类型。
" n, e+ P! P5 [3 M: q. C X% ~
" r/ b& H1 R" c# b9 l
基本要点:
$ o$ c+ u. z9 J
- K2 A; Y) i! v) B
(1)为扩展类型matrix编写运算符重载函数OpMatrix。
; I( D1 d, b, y3 b3 [) H' e6 i6 W, E
: j) W6 i" n. ~: E( x$ ^6 [
(2)用函数LockKey将重载函数OpMatrix注册到Lu,锁定的键的类型即为matrix,要注册为常量,以便于使用。
6 O7 \* A8 L$ M3 L
4 t% r5 K, \7 R% Q: L+ V
(3)为扩展类型matrix编写其他操作函数(本例未提供)。
5 E5 N: ]3 k$ Z1 N9 v7 i! z
' P% Z3 {, x2 C& P& e
(4)用函数LockKey解锁键matrix(本例中,程序退出时会自动解锁,故可以不用)。
#include <windows.h>
* c, {3 x0 u6 c) a; J
#include <iostream>
3 F+ k# z7 D* [3 q* E! `* x
#include <math.h>
: ]! v) K" ^6 ~% E6 ?
#include "lu32.h"
9 A# F; u. w% `3 a4 b" {, V
/ t7 {/ `! o0 v$ T7 q9 J
#pragma comment( lib, "lu32.lib" )
: ~1 |; j$ l/ J- U$ D( \
+ E; j6 z k* h, `: i
using namespace std;
5 a9 E) ~& m' E; [) t
6 j' F; h% ?! Y- f3 ?
luKEY Matrix=-1000; //标识矩阵类型,最终的Matrix由LockKey决定
/ n/ L |. L: o6 N3 o
`8 y" E9 A+ Y/ J% q3 R
void _stdcall LuMessage(wchar_t *pch)//输出动态库信息,该函数注册到Lu,由Lu二级函数调用
, }' M% p6 L* ~3 i# k, |1 ^0 G
{
4 y4 m1 v2 t" ]% |
wcout<<pch;
$ ^' g' j9 m8 l2 G, |$ f4 t
}
+ w( Q- g3 P/ i( i2 `
void _stdcall DelMatrix(void *me) //用于LockKey函数,因为是基于系统内置实数数组创建矩阵,故该函数什么也不做
0 _0 S: O! x* U, U
{
( q: j- C Z+ l- |# d F [% i" l
}
3 b5 h$ X- q& t c0 u- o
LuData _stdcall OpMatrix(luINT mm,LuData *xx,void *hFor,int theOperator) //运算符重载函数,用于LockKey函数
7 x% O1 v! x& {- I6 S7 I
{
/ S8 ^3 _4 g3 k/ \
LuData a;
& ^$ N0 s: Y( w; n. Q/ A+ o
luRealArray *pRealArray1,*pRealArray2,*pRealArray3;
3 u4 \5 A( V$ W5 U, i% D
luVOID i,j,k,m,n,u,v;
6 D% V6 p9 }1 H
double *pa,*pb,*pc;
/ e" S3 S) p5 p( Z6 t9 N( L
luMessage pMessage;
+ n; K! e2 w# \7 D) K" x
wchar_t wchNum[32];
8 q4 l; D* R( I+ f; V( x o& u" A
char chNum[32];
3 r* U, X( a; H7 d9 ~
a.BType=luStaData_nil; a.VType=luStaData_nil; a.x=0;
' I% k) J8 @2 s+ O, T
switch(theOperator)
. T5 U/ Y) r6 f; ?( A% v
{
5 P; @* s. l5 W# t8 B) v- p
case 2: //重载运算符*
9 A; J4 X- i- ~( E2 B; g
pRealArray1=(luRealArray *)SearchKey((char *)&(xx->x),sizeof(luVOID),luDynData_realarray);
" l+ z5 w2 X# Z0 Z' W- k
pRealArray2=(luRealArray *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),luDynData_realarray);
" H8 \- }1 |% K. G5 n" T
if(!pRealArray1 || !pRealArray2) break; //对象句柄无效,不是实数数组
4 [7 j$ Y1 Z- W, y1 g- o
if(pRealArray1->DimLen!=2 || pRealArray2->DimLen!=2) break; //不是二维实数数组(矩阵)
0 S7 \8 z' s' R# |2 @( E
if(pRealArray1->Dim[1]!=pRealArray2->Dim[0]) break; //维数不匹配
6 S- ?5 i! R- b$ J+ C. S
pRealArray3=(luRealArray *)NewSysObj(luDynData_realarray,pRealArray1->Dim[0]*pRealArray2->Dim[1],2); //创建矩阵对象
3 }+ z* G* r, Q, Q8 M9 U
if(!pRealArray3) break;
" C: K/ d5 L3 q* M3 J+ r* T
pRealArray3->Dim[0]=pRealArray1->Dim[0]; pRealArray3->Dim[1]=pRealArray2->Dim[1]; //设置矩阵维数大小
/ P2 [$ p" V# D9 M6 p4 m: \
pa=pRealArray1->Array; pb=pRealArray2->Array; pc=pRealArray3->Array;
) y) m. P& Q2 {# B
m=pRealArray1->Dim[0]; n=pRealArray1->Dim[1]; k=pRealArray2->Dim[1];
9 X# Q) S1 I. U$ Y
for(i=0; i<m; i++) //矩阵乘
. u& F5 [9 w* F* z# \1 W" F
{
8 R7 }+ \; Y" I' J3 i9 l* A
for(j=0; j<k; j++)
6 j8 N+ \0 Q& c) @2 r
{
& U) k. F9 b; W4 G
u=i*k+j; pc[u]=0.0;
" C9 p- B' b) }) O2 I# p
for (v=0; v<n; v++)
; J+ u6 U# F$ o5 m7 Q$ Z$ F; I
{
4 C8 c: L6 S+ g% n2 t6 u5 w3 ?
pc[u]=pc[u]+pa[i*n+v]*pb[v*k+j];
: R: [4 z7 ]: P! d( w4 o
}
8 i& R$ o* p$ M# ? _+ D
}
2 q% s4 m/ }- _' ]6 \- X
}
4 O) E" B, ~; w& L- u
FunReObj(hFor); //告诉Lu,返回一个动态对象
, D2 T z1 q2 x9 A
a.BType=luDynData_realarray; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pRealArray3;
$ H' u. J8 l* D: T* |
break;
" N6 `1 w* }# D! {4 Y
case 25: //重载运算符.*
( r# z3 Q8 Q( I4 s. [( y4 I
pRealArray1=(luRealArray *)SearchKey((char *)&(xx->x),sizeof(luVOID),luDynData_realarray);
# c. `; m8 Y1 y$ B6 i$ K: F2 h1 w
pRealArray2=(luRealArray *)SearchKey((char *)&((xx+1)->x),sizeof(luVOID),luDynData_realarray);
5 L$ ^% E) A9 d* x
if(!pRealArray1 || !pRealArray2) break; //对象句柄无效,不是实数数组
: {7 ^7 C7 b1 \! w0 y+ X- D& Y! c
if(pRealArray1->DimLen!=2 || pRealArray2->DimLen!=2) break; //不是二维实数数组(矩阵)
' w/ F6 u7 U! @# s
if(pRealArray1->Dim[0]!=pRealArray2->Dim[0] || pRealArray1->Dim[1]!=pRealArray2->Dim[1]) break; //维数不相同
' j3 D. ~8 x7 @ j
pRealArray3=(luRealArray *)NewSysObj(luDynData_realarray,pRealArray1->ArrayLen,2); //创建矩阵对象
% Z' a! Y0 _1 r! L" O- H0 R/ K
if(!pRealArray3) break;
8 j: n5 S) A4 p4 q
pRealArray3->Dim[0]=pRealArray1->Dim[0]; pRealArray3->Dim[1]=pRealArray1->Dim[1]; //设置矩阵维数大小
/ r( T9 U" W9 x" `
for(i=0;i<pRealArray1->ArrayLen;i++) pRealArray3->Array[i]=pRealArray1->Array[i]*pRealArray2->Array[i];//矩阵点乘
, I2 l+ A8 _* h' ?% q1 g
FunReObj(hFor); //告诉Lu,返回一个动态对象
5 O* q: y! J2 v0 w- D" r8 K2 v
a.BType=luDynData_realarray; a.VType=Matrix; a.x=0; *(luVOID *)&(a.x)=(luVOID)pRealArray3;
+ b' s& @7 I6 ^! e$ [5 f& s. c
break;
, `6 K( K% p& y' B
case 46: //重载函数new
0 u4 \+ H, z; v2 } A
a=ExeOperator(mm,xx,hFor,theOperator,luDynData_realarray); //直接调用基本类型luDynData_realarray的new函数
# h/ R$ x6 n% e& m+ ?
if(a.VType==luDynData_realarray) a.VType=Matrix; //设置扩展类型为自定义的Matrix类型
0 H5 J+ \) n8 w$ D
break;
' E: P. f: ]% \5 @2 W( C" J
case 49: //重载函数o
) Q' n9 D) S; V/ G- k t: L' D
pMessage=(luMessage)SearchKey("\0\0\0\0",sizeof(luVOID),luPubKey_User);
5 R! i+ s2 p1 k0 ~9 @
if(!pMessage) break;
' h& a c* U3 [* T6 `' p/ u
pRealArray1=(luRealArray *)SearchKey((char *)&(xx->x),sizeof(luVOID),luDynData_realarray);
! V8 b2 J7 Y) \& G4 U. t( _% j
if(!pRealArray1) break; //对象句柄无效,不是实数数组
: m9 q* j% m3 k) f* N, S
if(pRealArray1->DimLen!=2) break; //不是二维实数数组(矩阵)
+ m- F. }! C9 j7 J6 L6 X
pa=pRealArray1->Array;
+ H X/ j" `2 g1 m4 q9 |" G
m=pRealArray1->Dim[0]; n=pRealArray1->Dim[1]; k=0;
4 k" c0 D4 W5 R1 v1 q9 K9 \
for(i=0; i<m; i++) //输出矩阵
7 ?: {& N/ P+ S2 ~ F. L0 [; I
{
( y1 ?/ M8 r) n& v
pMessage(L"\r\n"); k+=2;
% f1 k- s$ c# P+ G5 @+ x9 O+ Z
for(j=0; j<n; j++)
. V8 k: i% K8 S, D: d- Z
{
2 c% A, ]' E7 B( p; s2 X0 O
_gcvt_s(chNum,pa[i*n+j],16);
0 u! A9 q& u5 |* l
for(u=0;chNum[u];u++) {wchNum[u]=chNum[u]; k++;}
; U7 L# J& |; j5 C; e4 I
wchNum[u]='\0';
" A2 u! v$ J" {
pMessage(wchNum); pMessage(L" "); k+=2;
9 l* w* Z5 `5 I0 F5 D
}
# F. R' R% ?# g/ S4 w- |
}
: O+ ~6 D9 K' }, V, A
pMessage(L"\r\n"); k+=2;
- ?% v; Y1 K# j. c( ^
a.BType=luStaData_int64; a.VType=luStaData_int64; a.x=k; //按函数o的要求,返回输出的字符总数
; V2 | `: r( C- Z7 p; ?
break;
& s& {+ y* d/ O
default:
) W* O h6 |2 A6 r
break;
7 Q- w# z( G* F9 F9 \, f
}
9 G0 |! t# c5 L% _. E
return a;
! k A% d; A: \# N/ h9 z' b
}
5 o1 `$ a8 l4 f6 Z9 v
void main(void)
5 C( N8 Q* R5 u9 W
{
; o& H% o3 E: q/ X- n0 X u
void *hFor; //表达式句柄
9 a* C( W+ }5 K: G4 s+ y* }
luINT nPara; //存放表达式的自变量个数
5 N! K0 X6 L! n7 ^8 b2 ~4 {
LuData *pPara; //存放输入自变量的数组指针
. O! Z* U. s! b0 Q! Z( B- Z
luINT ErrBegin,ErrEnd; //表达式编译出错的初始位置和结束位置
4 O9 S$ d' {, a8 `+ x
int ErrCode; //错误代码
. w% H, ]1 y$ g- I
void *v;
1 Q, m4 G/ C* ]6 @, t; R
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.]}";//字符串表达式,矩阵乘
! I: L: D, ~2 V9 k x' v
//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.]}";//字符串表达式,矩阵点乘
( G# M5 o- j" I* h* S
LuData Val;
S w l7 \! p @/ ^, Q: ]
if(!InitLu()) return; //初始化Lu
5 C: ?6 e4 i- J8 W/ _; a$ O- h
while(LockKey(Matrix,DelMatrix,OpMatrix)){Matrix++;} //锁定一个键,用于存储矩阵扩展类型
4 z ]. s7 l& u3 k0 \4 {
3 Q/ v6 }: S1 I
Val.BType=luStaData_int64; Val.VType=luStaData_int64; Val.x=Matrix; //定义整数常量
* N$ l" s8 ~& ^& o. u j
SetConst(L"matrix",&Val); //设置整数常量
% h5 y5 ^2 o# t4 U3 p9 u! _
InsertKey("\0\0\0\0",4,luPubKey_User,LuMessage,NULL,NULL,1,v); //使Lu运行时可输出函数信息
/ R7 c- @, O3 S; P% D" Y2 k
wcout.imbue(locale("chs")); //设置输出的locale为中文
& _" a9 z2 D1 `
3 H5 z9 I# g4 _1 Y
ErrCode=LuCom(ForStr,0,0,0,hFor,nPara,pPara,ErrBegin,ErrEnd); //编译表达式
+ p, v" e% L2 L3 C1 b% ~( H3 A
if(ErrCode)
* a; `' H m5 b
{
2 E4 {; N j1 r5 w
wcout<<L"表达式有错误!错误代码:"<<ErrCode<<endl;
' H! }: t9 ?! {/ [+ N
}
$ S* b8 ]. d" J" A- A# G
else
2 N& n. N/ M; `& I
{
% C( l7 P( {7 O! |
LuCal(hFor,pPara); //计算表达式的值
, t* E* Q2 D4 n1 H- R
}
# l& ]9 v$ O$ x0 X. E. j
LockKey(Matrix,NULL,OpMatrix);//解锁键Matrix,本例中,该函数可以不用
* ~# w! ~6 ^8 P2 a$ ^+ c) C% e+ F
FreeLu(); //释放Lu
6 W, V5 g6 x! [- |# d4 C9 U
}
复制代码
习题:
9 n8 j7 v6 K( `$ Z5 T
9 e+ V/ [" K& Q% L) a
(1)自定义矩阵的加、减、左除、右除、点左除等运算,自编测试字符串代码,重新编译运行程序,观察计算结果。
5 j, f1 H; o, n5 y2 T
' z$ Q- S, v: T; Q$ E/ H
(2)小矩阵乘效率测试。编译运行以下Lu字符串代码:
main(:a,b,c,d,t,i)=
& |6 |5 X7 ^4 M- E, K- N l0 \; S
a=new[matrix,2,2,data:1.,2.,2.,1.],
; _# N6 {# k+ `% @. k* B
b=new[matrix,2,2,data:2.,1.,1.,2.],
% x* V* s: m9 {0 ^9 }
c=new[matrix,2,2,data:2/3.,-1/3.,-1/3.,2/3.],
# F: N% o, r+ {2 k! }8 u0 S
t=clock(),
" U- D* ?& S( D3 u! @. M$ d
d=a*b, i=0, while{i<1000000, d=d*c*b, i++},
; w, _1 W9 R$ T& w3 l
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.
7 s& ]% Q1 V' ]$ O: }
5. 4.
/ V2 ~! s! p: k' b g( i
time=0.875 seconds.
1 I3 c+ h5 \" d! Q1 Z. ]5 Q7 b, x
请按任意键继续. . .
复制代码
Matlab 2009a 代码:
a=[1.,2.;2.,1.];
+ U" V% V. p, \$ J: m0 e5 y
b=[2.,1.;1.,2.];
$ L1 k; j2 f: g0 |
c=[2/3.,-1/3.;-1/3.,2/3.];
: n& u3 U' u; w! J" l
tic,
$ a8 W9 }' }) Q- b- r* I
d=a*b;
" @7 i: G q' } N5 _( W
for i=1:1000000
1 R; Z, o, g' s B! M
d=d*c*b;
5 W3 \2 m; C4 h" [( c( x1 |
end
7 a7 Z$ N1 z, @& U% x
d,
9 [. F- c. k) V% L! W
toc
复制代码
结果:
d =
2 o2 n F+ H3 h: X1 V
4 5
2 U: D5 C! q# _. Q' C
5 4
3 x, b! t% }! m: H0 \! ` j
Elapsed time is 2.903034 seconds.
复制代码
本例矩阵乘效率测试,Lu的速度超过了Matlab,主要在于Lu有更高的动态对象管理效率。
- i G4 j y2 {9 O
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5