- 在线时间
- 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 编辑 2 `1 f1 C F5 O6 N: [, g& w
3 _5 P. _, L; D4 |# ~
我正在练手设计的FcMath库也打算以矩阵运算为基础,设计一些专门的函数对数组元素集中运算,运行效率确实有所提高(甚至有些涉及矩阵的算法比matlab还快),代码也简洁了,但不知这是不是矢量化?
- E3 G" e" `: t: E. i5 m1 V, b, p( v# O: _
脚本运行效率应该取决于函数调度效率、对象管理效率和函数内部算法的实现。( K" p" \5 U4 v/ G9 u
+ t" v! _9 N. j0 @" f( R$ m
我感觉,matlab的函数调度效率较低,对象管理效率这个不好说,但一些函数内部的设计比较优秀。故有些Forcal代码比matlab快,而有些慢。
* \5 c; J6 Y. o. w) v2 A6 p5 x i
3 u+ Q1 s$ D8 T+ g' G以下例子体现了Forcal和matlab的效率差别所在。" v. i% _0 M, k$ `9 l
$ t: b( _! k/ W8 v6 b! S/ k2 d这个matlab程序段是网友lin2009 给出的,理论结果是每个元素均为275000。- clear all9 d# ]) C+ a1 K\" t1 z
- clc
1 w8 I+ ]2 {$ K/ Q5 Q - tic# g9 T+ i0 U, C, O' H# N0 W, `
- k = zeros(5,5); % //生成5×5全0矩阵, Z9 y, B9 o+ w- {
- % 循环计算以下程序段1000 00次:' X) T+ h! K( d9 T* i
- for m = 1:1000 00
4 m1 J9 J9 ^+ K! u. I6 o - a = rand(5,7);
9 E- O# v\" a3 U( j4 k# w - b = rand(7,5);%//生成5×7矩阵a,7×5矩阵b,用0~1之间的随机数初始化
\" {3 x! W) D, N; @ - k = k + a * b + a(1:5, 2:6) * b(2:6, 1:5) - a(:, 7) * b(3, :);/ {8 D3 p- t# ~4 Z) R4 ^
- end5 a+ Y3 Z' \( A9 o2 X! W' ~5 R
- k4 v* g- Q% X6 L6 d
- toc
复制代码
9 ]) k. F e3 w. Z. `Forcal代码1:运行稍快的代码,比matlab约快10%吧?
" q( D v8 f9 E5 G2 ^; [ - !using["math","sys"];
- 4 p- b\\" E; e0 h% {% Y
- mvar:( N7 p: J. r- V z& `. O; _% @
- t0=clock(),
- 4 L. h3 ~) R3 N
- oo{k=zeros[5,5]},
- : W9 W0 N) P% {0 f0 K `
- i=0,((i++)<100000).while{- c8 ~: Q7 B5 \& [$ I
- oo{- h) D4 |: T- q- M
- a=rand[5,7], b=rand[7,5],9 o! l% m4 o5 E$ g
- 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)]
- 7 R) Y\\" B0 B$ S\\" W) R
- }' D6 a7 Q, T `* o; n9 t
- },$ j2 ~\\" R\\" b4 k. |( T' n
- k.outm(),
- 9 |8 {* ?1 A! \! V
- [clock()-t0]/1000;
在我的电脑上运行时间为3.344秒。
+ X# F7 G8 I' B( J8 r' d
; B( @& t, Z, n6 bForcal代码2:比较好看些的代码,似乎也比matlab稍快吧?
% V2 f& x& U6 q: o8 |0 L/ [ - !using["math","sys"];! q( p0 }; c. T# F. X
- (:t0,k,i,a,b)=
- 9 P& E( t Q0 o
- {
- 0 w# Y3 A8 ]5 l. b, e1 s
- t0=clock(),) w) G& M2 r. D) @* R8 V
- oo{k=zeros[5,5]},
- ; e# E) r7 v! M% T+ P
- i=0,((i++)<100000).while{+ p* N% O1 k9 d2 D6 q
- oo{\\" N$ v3 `# Z: W# P+ Z8 ]6 i
- a=rand[5,7], b=rand[7,5],
- & R2 v4 ]- x- M3 S* q5 ]
- k.=k+a*b+a(0,4:1,5)*b(1,5:0,4)-a(neg:6)*b(3:neg)
- . T! _/ v @; T% Y& g- E {
- }
- [ w' l0 N: K5 Y0 u- H' ]3 E; l
- },$ x. P8 Y5 R- m6 X( z/ Q% y$ \
- k.outm(),/ z& Q( D. a D
- [clock()-t0]/1000
- ) B6 }# v# ^\\" g; h1 Q4 R
- };
在我的电脑上运行时间为3.579秒。
l; [4 }% O' T
# Y; P \! l @, E例子2:3 A' `6 \4 Q% U
一段程序的Forcal实现:
* X% D; ]' d! \! F. l+ P- //用C++代码描述为:! o) d$ k4 z4 h9 u0 x
- s=0.0; # F! K8 |- k8 k0 U$ @2 @
- for(x=0.0;x<=1.0;x=x+0.0011) 0 T) O9 E& D! |
- {3 Q2 N: K& j$ @* k/ a7 }( p! a' b
- for(y=1.0;y<=2.0;y=y+0.0009)
+ _0 Z I' A8 ]4 m\" Q4 h\" s) B% o# z - {
7 K0 o0 \! ~' J+ m - s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));% ~. H- P% t) s. ~/ G
- }& J# Y\" p+ W4 X2 V8 e6 S# `3 ]
- }
复制代码 结果:
! P! P# k9 y5 t* G! A- x- k# N, w3 p1008606.64947441/ k7 {; @" l+ v% \8 z3 Q1 |% L- X
0.609 //时间
1 m7 f/ |3 c& q# X7 B
/ g4 m# e% F3 p' A这个matlab程序段是网友yycs001给出的。 S. j9 [- U- ]' a! L
- %file speedtest.m: e0 Y) C( a' W( n- b; t3 l\" p8 P$ m
- function speedtest
4 \6 \* i6 f' {% b7 O, Q - format long\" ]% J: m% ~( W0 ~1 j/ ? U
- tic
' u9 X% U# l! B\" b2 ~# U0 v - [x,y]=meshgrid(0:0.0011:1,1:0.0009:2);
% h\" e) P/ G$ l\" Q% z - s=sum(sum(cos(1-sin(1.2*x.^(y/2)+cos(1-sin(1.2*y.^(x/2)))))))
) |$ g3 m( G4 @+ }6 ^& y - toc
复制代码
4 s& Q& K$ \5 g% uForcal代码1:**数组求和函数Sum,完全矢量化的代码
% \! W; d7 B2 l* F8 d8 e+ [ - !using["math","sys"];
- + G5 f5 }0 G& e! e) l, t: Y# g
- mvar:
- 4 M; b- U( }) n7 C. D* S( s
- t=clock(),* Y6 H5 p1 v- i/ Q4 T
- oo{
- 0 [ s: R% I8 O6 }8 B
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],5 c: t' {2 e; R' h# b$ o\\" s
- Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2)))))),0]
- ) `# E; F, P# i) `) R
- };! z2 W5 E# y# X, [3 f
- [clock()-t]/1000;
结果:
% m7 t" M0 X! o+ {5 ?1 W' j1008606.64947441( D0 q V. s- i; [0 Q6 X
0.625 //时间
) ~3 o9 t6 [6 G. e0 F; E' B/ b1 O3 B! @
或者这个,与上面效率差别不大:4 [4 J9 A- Z9 w" w, O& I9 c8 y
 - !using["math","sys"];$ |+ b3 S) g. C- L2 r
- mvar:. E) ?- ^. j+ r d
- t=clock(),
- 3 c$ O9 u/ S5 N9 ?\\" D* a7 K
- oo{2 ~6 q& ?6 v) E( x+ k) Y
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],
- # X/ U8 u7 X/ d, V! V
- Sum[Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2))))))]]% F% r\\" v\\" `5 T\\" Z4 F\\" F6 L: Q
- };
- 9 P; n& D0 H$ \
- [clock()-t]/1000;
9 v u- A4 ?3 E5 J/ n( O# `
Forcal代码2:求和函数sum,非矢量化代码
* a: T' E: a6 F( ?( L) z- f(x,y)=cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))); % n0 I+ \( [/ ^5 A% w# `. m7 t: E
- sum["f",0,1,0.0011,1,2,0.0009];
复制代码 结果:' n1 j0 d: r6 O
1008606.64947441: ]% q3 n8 J5 q4 o [0 O
0.719 //时间# o5 Y( O- j: s& v) x$ R; B
6 `4 V2 ^1 ^" YForcal代码3:while循环
( |4 f) _* K* C2 I0 d! ?- mvar:
5 I& \0 j b- V) d c - t=sys::clock();
# h. c D5 c* o$ L/ ]: v/ a) G; A - s=0,x=0,
- Z: v; b! ]\" ^/ b- ?8 G, k2 p - while{x<=1, //while循环算法;
4 z! \1 b( b) Z. P3 z$ a - y=1,
) {0 A\" Q) P: ^. b( a% u) f$ I - while{y<=2, 3 e+ W\" ^# k' Y! Y* M2 O' |
- s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))), y; I0 f# X7 \% \: n
- y=y+0.0009 % M. O# {9 N. |
- },
+ ~: X% u1 P! K2 w. A7 L. n: n - x=x+0.0011 / J0 x( t! `; r& ]5 i3 B
- },
* z1 F7 r6 x( Z - s;
! u( ^6 ?7 s5 n _ - [sys::clock()-t]/1000;
复制代码 结果:8 Z8 k; a; O$ [0 x# i$ w
1008606.64947441
/ H( v" i+ a) A0.734 //时间
* E# O0 s/ |3 I+ a- ]. K; k5 o6 o+ S) }/ t$ t+ o
大家可下载OpenFC进行测试:http://www.forcal.net/xiazai/forcal9/openfc32w.rar
0 h( }4 H6 N" U' D! D' t) `
4 R' Z: I; T5 c7 `. v4 u0 @注意Forcal的矢量化代码第一次运行有时效率较低。' |1 o1 e9 c8 o
' f0 O" D3 O5 s' k; s) D例子1中Forcal和matlab都是矢量化代码,但matlab跑不过Forcal。该例子的特点是函数调用频繁,临时变量生成多,但矩阵很小,矩阵的各种函数运行时耗时较少。故说明Forcal函数调用+变量管理效率优于matlab。- s# V8 E" w/ x* \6 v9 n! m
& O. }0 e3 a- @2 D' d1 w
例子2中Forcal的矢量化代码是最快的,但与matlab的矢量化代码相比仍有差距。该例子的特点是函数调用少,临时变量也少,但矩阵大。故说明Forcal的各种矩阵函数Sin、Cos及矩阵的加减运算等函数的内部设计不及matlab。9 g4 v/ z7 t) O6 k
) w3 K* k: N% z3 B- g
如能在函数内部设计上下点功夫,例子2超越matlab也是可能的。在这方面,期待高手们的指点。
2 |1 T2 ~5 ]7 N. A2 r6 w. E" s+ G
2 r* e. _0 V" q, E如果例子2速度也超越了matlab ,matlab矢量化的神秘面纱就揭开了。5 z& z% r) ]" W# V
) x" F- z, ^6 J; K/ `& y
顺便说一下,例子1如果用C++的运算符重载来实现,速度将比Forcal慢一些,也就是说,在涉及运算符重载时,脚本的效率有时比C++还要高些。
: B% V. y, k( I& v2 q! y+ ^ |
|