- 在线时间
- 13 小时
- 最后登录
- 2013-12-8
- 注册时间
- 2010-5-13
- 听众数
- 3
- 收听数
- 0
- 能力
- 0 分
- 体力
- 399 点
- 威望
- 11 点
- 阅读权限
- 30
- 积分
- 282
- 相册
- 0
- 日志
- 0
- 记录
- 0
- 帖子
- 97
- 主题
- 45
- 精华
- 0
- 分享
- 0
- 好友
- 1
升级   91% TA的每日心情 | 难过 2012-8-27 18:22 |
|---|
签到天数: 1 天 [LV.1]初来乍到
|
本帖最后由 forcal 于 2010-10-12 21:46 编辑
" U) x1 o1 w- f' S1 z5 v3 h% n; a# M
+ V, L2 p: M# L& U4 `% q" S, N" R我正在练手设计的FcMath库也打算以矩阵运算为基础,设计一些专门的函数对数组元素集中运算,运行效率确实有所提高(甚至有些涉及矩阵的算法比matlab还快),代码也简洁了,但不知这是不是矢量化?, z, C% J. \/ z
6 z$ E% A7 F+ i0 Q p脚本运行效率应该取决于函数调度效率、对象管理效率和函数内部算法的实现。
# L" c( U2 x7 _9 Y% H( M* n& T& ?; N8 W% v$ {, K' p
我感觉,matlab的函数调度效率较低,对象管理效率这个不好说,但一些函数内部的设计比较优秀。故有些Forcal代码比matlab快,而有些慢。* w5 Y7 _' L% K2 \
4 t* X1 d4 ]& h1 Y& a5 b
以下例子体现了Forcal和matlab的效率差别所在。
( y9 \# n$ H) _8 a6 M b) Z9 c' E6 f$ n! C9 |
这个matlab程序段是网友lin2009 给出的,理论结果是每个元素均为275000。- clear all/ q/ m! ]6 N9 L8 T2 b6 t
- clc
% [+ S4 }- C* Y! w - tic' R. O# F& f* Q9 n8 B! e
- k = zeros(5,5); % //生成5×5全0矩阵
* k& z1 C7 H0 X+ ^/ n: d - % 循环计算以下程序段1000 00次:5 l4 ]$ Y$ Y( @\" K l9 ]
- for m = 1:1000 00 L) b6 {9 F1 M, K4 k3 j
- a = rand(5,7);3 n! q T' N\" m. K7 p
- b = rand(7,5);%//生成5×7矩阵a,7×5矩阵b,用0~1之间的随机数初始化, k, `1 @: V) N8 Q4 K\" g# U
- k = k + a * b + a(1:5, 2:6) * b(2:6, 1:5) - a(:, 7) * b(3, :);5 S# ]% q, t4 k( D+ g; t4 s
- end, Z j: D8 ^0 z# `) I
- k
\" h- _9 v- m9 l: s- ]) H3 ]: x( K - toc
复制代码 ' }( n1 E' T6 E0 p) R: Q
Forcal代码1:运行稍快的代码,比matlab约快10%吧?- j4 V' ]2 }0 M( z1 H# `
 - !using["math","sys"];- D9 ?9 {6 D* E) k\\" r
- mvar:
- 9 x9 X6 ?) L0 x9 ?
- t0=clock(),
- 2 m/ b9 l) n3 ]0 D3 I/ P9 X
- oo{k=zeros[5,5]},
- + U1 O9 L2 I- e, C; o
- i=0,((i++)<100000).while{1 ?! Q/ C# r, W$ x; P% H
- oo{7 _$ I' |2 l- v0 p9 W
- a=rand[5,7], b=rand[7,5],
- , W1 a$ k2 i/ }- Q' D1 X
- k.oset[k+a*b+a.subg(0,4:1,5)*b.subg(1,5:0,4)-a.subg(neg:6)*b.subg(3:neg)]4 Z5 i# R8 ?' w7 h\\" F/ _+ e2 Q
- }
- ; Q! ^& S' R+ ^8 N$ G! l
- },
- / a# q5 B! V4 M5 `7 ]2 ]
- k.outm(),
- 5 i' l+ P, ~\\" p, t* R9 n
- [clock()-t0]/1000;
在我的电脑上运行时间为3.344秒。
1 E; @ e( S$ |* c5 f2 v k$ Z6 p H4 ^7 f8 U' c' Y! ?6 N
Forcal代码2:比较好看些的代码,似乎也比matlab稍快吧?0 b* N, i. r. S/ j# c
 - !using["math","sys"];
- ; e4 j& J% o' [$ W
- (:t0,k,i,a,b)=: u3 v. X3 _) q n
- {
- 8 Y5 k9 h; r+ ]! `2 o7 w6 | O
- t0=clock(),
- $ k# Q- r! x. g1 ?
- oo{k=zeros[5,5]},! e8 d! Q6 X' w# u1 Y: ~3 G
- i=0,((i++)<100000).while{
- \\" S. }; B; w, e' z* J
- oo{
- C1 B: ]1 t- L
- a=rand[5,7], b=rand[7,5],
- 5 o8 Z V3 l# \9 U5 ]& y\\" G6 S6 C! ~
- k.=k+a*b+a(0,4:1,5)*b(1,5:0,4)-a(neg:6)*b(3:neg)
- & y, Y0 ?' t' e: a+ H; x( k! H
- }
- * z$ L- T' t+ w
- }, w; x7 W B5 ~; l5 I% Y! l6 t# g
- k.outm(),% Q! w) h: ]1 v# |/ p4 G$ d# T
- [clock()-t0]/1000
- 3 j% [: D& ^ ]& e9 K2 I
- };
在我的电脑上运行时间为3.579秒。2 @0 F) s F- W& u) a3 h2 L
) ?3 \! u l0 }) E
例子2:
: X7 G; O; ^0 s5 f' Y" k* J一段程序的Forcal实现:
$ G, K, Y/ g! o# K- //用C++代码描述为:; y1 C$ r+ h8 b# j9 z
- s=0.0;
: z& l9 U( @! m+ h; s - for(x=0.0;x<=1.0;x=x+0.0011) 9 U: C: W, y3 b' `& d
- {
! r, c% B9 E+ ~% a, P- k - for(y=1.0;y<=2.0;y=y+0.0009); w% A/ `- {) u u5 \/ ~6 [
- {
- c. ?! @; [ d* P+ F - s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))); `- b! g# m9 g& t) V+ M# q
- }
/ ^% W: F: ~. c - }
复制代码 结果:8 z+ v; } C- U/ |. V+ A
1008606.64947441( A- J! q+ ~: F% H* @' ^4 X
0.609 //时间
Q9 c# K0 F3 H. g Z8 C
% m6 M# V+ u+ N: l这个matlab程序段是网友yycs001给出的。
X7 f4 `# S2 z; \5 Z, z) M- %file speedtest.m
' e( F7 @4 j! i, j# \ e - function speedtest ]; i- G/ b0 z\" V+ r. e
- format long, j( U2 }9 Z8 D3 {; w) [* C9 d
- tic' u* w$ e3 m) M\" l
- [x,y]=meshgrid(0:0.0011:1,1:0.0009:2);& _! e+ V7 r8 ^9 x! e% t, e
- s=sum(sum(cos(1-sin(1.2*x.^(y/2)+cos(1-sin(1.2*y.^(x/2)))))))
! @: G! b5 R6 U! ^7 r& R - toc
复制代码
; k7 d+ p, K& p4 ~Forcal代码1:**数组求和函数Sum,完全矢量化的代码8 ~2 n4 U9 f! G" }( I: L
 - !using["math","sys"];\\" p( ?2 m3 G! [& ]* r- [/ X3 e
- mvar:
- 0 c% Z, t& X9 p
- t=clock(),
- $ u2 m$ h+ u/ d. g4 B0 ]
- oo{
- . Y# l2 H4 q5 ^ b
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],
- * o8 Q; }3 @& {0 U
- Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2)))))),0]
- ) i4 J+ A4 { n
- };
- 7 }+ z& t( p/ k8 r$ P8 ^1 L
- [clock()-t]/1000;
结果:
/ N' Z* H% {8 }, D1008606.64947441" x" g1 u; w/ U/ |
0.625 //时间
/ ?: B( J9 h! l/ H. b7 p
3 ~$ v; @* ^. A4 X3 C或者这个,与上面效率差别不大:
" ~+ U# A# V; Q, n4 w+ N2 K - !using["math","sys"]; f, C% G6 T: ?3 e1 z# z
- mvar:# A4 |. e0 [5 s/ ?. P- N
- t=clock(),. I+ T% q+ n1 N- o; x1 h& z2 `. r
- oo{, h: |4 d- s/ J, Y- ]% o
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],\\" s. K1 U- g6 i
- Sum[Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2))))))]]
- ( o' r( q* z) L& ^; B
- };* t8 u' T( i. r; K. ?1 e
- [clock()-t]/1000;
" c! H7 Y9 t& D) `
Forcal代码2:求和函数sum,非矢量化代码& X$ K$ o( l* h5 W5 J" G A$ Q
- f(x,y)=cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))); * [- \\" B: ?% Y& _* n5 D
- sum["f",0,1,0.0011,1,2,0.0009];
复制代码 结果:
+ c6 I; j- K @2 ]0 K' h `# D1008606.649474417 U6 V) w* @) V) |7 Y4 B: |
0.719 //时间8 U$ _! {2 G- q
/ Y& z+ S: ]3 u6 F; U( Y6 W
Forcal代码3:while循环
& J6 }% r' `& b! L ]% U/ C0 e3 `3 u4 D- mvar:
6 c# K: u) p2 B% |! O$ L - t=sys::clock();
- F' D0 [1 n# q! a* a9 } - s=0,x=0,
# R- l4 I+ B h, c - while{x<=1, //while循环算法;
- E\" }- n- U T. S4 M - y=1,
2 A0 W2 A0 E\" { - while{y<=2, , h$ m/ g- ^( P k9 j$ y6 M
- s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))), , B9 P- w\" J t0 w! Y) p# f5 K$ _) N\" ?
- y=y+0.0009
. p/ i3 a% X% ~% n/ X - }, \" J3 |. _* s: I Q- c
- x=x+0.0011
4 M4 a+ x- E9 T. N\" s/ L - }, ' x+ e, \8 ? y* W9 y
- s;
4 T. Y$ R5 p1 U - [sys::clock()-t]/1000;
复制代码 结果:, z, o w' I1 h
1008606.64947441
( c2 j& w7 J& Y0.734 //时间
1 s& ?4 r4 T) A+ F! ?7 B
! `; C) m, v9 n) k0 i' o+ G( s大家可下载OpenFC进行测试:http://www.forcal.net/xiazai/forcal9/openfc32w.rar1 V* _8 y7 Q! |# Y1 c0 u
# A, |5 |1 {: t& m注意Forcal的矢量化代码第一次运行有时效率较低。
$ @- p/ k3 S G8 O3 @/ J1 ?2 }9 g9 M: i
例子1中Forcal和matlab都是矢量化代码,但matlab跑不过Forcal。该例子的特点是函数调用频繁,临时变量生成多,但矩阵很小,矩阵的各种函数运行时耗时较少。故说明Forcal函数调用+变量管理效率优于matlab。
. L! q& B) |/ m( G# j7 W; s$ ~: w- a* [, _2 s( l9 W- j4 z8 z8 W
例子2中Forcal的矢量化代码是最快的,但与matlab的矢量化代码相比仍有差距。该例子的特点是函数调用少,临时变量也少,但矩阵大。故说明Forcal的各种矩阵函数Sin、Cos及矩阵的加减运算等函数的内部设计不及matlab。' r9 O7 E6 h1 C3 C3 v
3 w' j# _; W1 I
如能在函数内部设计上下点功夫,例子2超越matlab也是可能的。在这方面,期待高手们的指点。
4 c) {1 l3 P0 a1 X* p* t5 E2 d7 W) f1 }/ Q$ w: E ^, y( j6 x
如果例子2速度也超越了matlab ,matlab矢量化的神秘面纱就揭开了。4 b: ]+ F& ]; f* v; M
6 L: H! G& t2 C3 c2 o* S- L ~& r
顺便说一下,例子1如果用C++的运算符重载来实现,速度将比Forcal慢一些,也就是说,在涉及运算符重载时,脚本的效率有时比C++还要高些。. ^+ k% k7 v( v$ J/ E5 |4 P. Z
|
|