- 在线时间
- 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 编辑 + |, L3 L9 c3 \- I: G
' N7 m& W3 E6 j; q q! q4 a/ g
我正在练手设计的FcMath库也打算以矩阵运算为基础,设计一些专门的函数对数组元素集中运算,运行效率确实有所提高(甚至有些涉及矩阵的算法比matlab还快),代码也简洁了,但不知这是不是矢量化?3 W4 t3 z+ t) q$ B
% k/ v; b. z+ p9 U
脚本运行效率应该取决于函数调度效率、对象管理效率和函数内部算法的实现。- w9 }* @+ L+ u
! k0 ? i3 u. k I1 Y
我感觉,matlab的函数调度效率较低,对象管理效率这个不好说,但一些函数内部的设计比较优秀。故有些Forcal代码比matlab快,而有些慢。: m! K$ ?/ Z1 Y
+ t% f$ g0 D; E4 A( f& c以下例子体现了Forcal和matlab的效率差别所在。
0 t# m8 ]. ]. V( p0 H- B6 T3 m0 j
/ r3 x* _" B3 O3 l& O" Y& F这个matlab程序段是网友lin2009 给出的,理论结果是每个元素均为275000。- clear all
( Z\" ?7 g- H4 |: s' O6 H - clc% o: @$ _5 J2 W7 Z! T
- tic\" C, M2 |8 l' t
- k = zeros(5,5); % //生成5×5全0矩阵2 y; m2 O# w4 C; T/ ?4 H
- % 循环计算以下程序段1000 00次:# l7 u, q1 j+ ]+ J, b
- for m = 1:1000 00\" ?2 i( P# T8 F5 Q
- a = rand(5,7);
9 g0 [5 i! l9 O4 ~: n - b = rand(7,5);%//生成5×7矩阵a,7×5矩阵b,用0~1之间的随机数初始化/ R* k: s- P6 e! \0 k Z) a& m& V+ j0 w
- k = k + a * b + a(1:5, 2:6) * b(2:6, 1:5) - a(:, 7) * b(3, :);
\" D+ M1 l/ K\" e8 H7 k; y - end
$ H2 ?( W2 D% [ - k
1 g& p; R/ L\" x3 L. g9 Z/ F( f+ `; Q L - toc
复制代码 2 }' m; t1 d5 N* Q! q8 R/ G" ]. D- L
Forcal代码1:运行稍快的代码,比matlab约快10%吧?
8 r* _' ?7 t2 ~% j p- X* ^7 L - !using["math","sys"];; C' |+ f6 _+ j! D9 o
- mvar:
- 0 `9 @- D\\" Q( ~: Z( U+ @1 y
- t0=clock(),
- $ i! D' p. ]- z% B\\" b1 l
- oo{k=zeros[5,5]},; o8 a, C9 g1 k: V# u
- i=0,((i++)<100000).while{
- ; m( b6 [5 P$ L/ Q6 [9 P/ p, V2 y U7 y
- oo{
- $ S; h: L/ Y- B+ r- S9 @( W+ `9 b
- a=rand[5,7], b=rand[7,5],
- % o* p T0 P- t. k
- 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)]
- # U3 \( h4 W. K; U. s$ w1 ^
- }
- ' s# P r2 d* z0 }
- },7 r# n, v9 u4 A: C( s/ R
- k.outm(),2 f) o+ S$ I; Y6 y
- [clock()-t0]/1000;
在我的电脑上运行时间为3.344秒。
- \1 X* H/ R0 g' ~" k8 r U5 V9 l# i
Forcal代码2:比较好看些的代码,似乎也比matlab稍快吧?
$ r' \. w0 `8 u$ ]6 J: |5 J& ^- ? - !using["math","sys"];2 w+ r\\" Y4 w* ?& B3 T7 \
- (:t0,k,i,a,b)=
- 7 C( {7 @$ \) M9 o/ u7 f
- {3 P5 ?$ [/ C, u% s# b
- t0=clock(),% i. \: }% P6 K Z4 Z: S0 A
- oo{k=zeros[5,5]},
- 8 ^* }) [* K* D/ x
- i=0,((i++)<100000).while{
- ' l$ h* f8 O. c* o T. B) X
- oo{0 K% _/ d$ H* D' J\\" j& h\\" M! z9 t
- a=rand[5,7], b=rand[7,5],
- * X2 n; N8 Z7 f/ ] {
- k.=k+a*b+a(0,4:1,5)*b(1,5:0,4)-a(neg:6)*b(3:neg)
- ; S, j1 S v: X% o7 @
- }$ x$ _6 `/ U ~. q4 d- O2 d+ b\\" q
- },% M6 s9 ]4 y5 G6 B' a
- k.outm(),
- 9 e$ U. t' e0 ^: |% R0 f; A
- [clock()-t0]/1000, }+ P# r6 G6 F( ]
- };
在我的电脑上运行时间为3.579秒。
5 q3 }0 ^6 ^, Y# r' L+ h" m9 p$ n% D1 s# N- y
例子2:: r, [' P7 `8 S9 X8 d4 y0 ^
一段程序的Forcal实现:
6 y- L% @4 F9 A- //用C++代码描述为:
& E5 w# q5 [9 i% R. H. X2 I - s=0.0;
4 l3 l' ^, t4 B# M- L3 ]( O\" y0 q - for(x=0.0;x<=1.0;x=x+0.0011)
b% \# E7 v9 u - {
\" x. l5 s/ b$ y4 y1 T - for(y=1.0;y<=2.0;y=y+0.0009)5 p i ]; l1 L, t6 j9 Q
- {! F( ~1 V0 k) L8 i! i1 ?
- s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));' ^5 `6 s4 F& R
- }2 S: x. T4 q6 F. R( j2 W# L: H3 y
- }
复制代码 结果:
; O; j* j T% V0 M# q1008606.64947441
) P$ Q, o# ]: Z: j# l& ~0.609 //时间: D+ {. N% \$ ^$ @( u& s. i
4 V* L @8 Q3 y, w" c4 M, Y这个matlab程序段是网友yycs001给出的。( m5 _, a3 f1 H3 Z, E* h
- %file speedtest.m
+ c9 H; M1 \' ^) r* T* f\" W - function speedtest
! H( _7 d- `7 V/ j - format long& x1 M- z( s# f' I' ]
- tic
, n. V u0 K% Q& _8 U\" A; d6 C - [x,y]=meshgrid(0:0.0011:1,1:0.0009:2);
% G6 A, I\" T7 { - s=sum(sum(cos(1-sin(1.2*x.^(y/2)+cos(1-sin(1.2*y.^(x/2))))))), b+ r' { F4 h6 U
- toc
复制代码 & `# A9 H3 c- H+ a
Forcal代码1:**数组求和函数Sum,完全矢量化的代码$ j/ n1 ?) I- d8 b" A
 - !using["math","sys"];
- 2 H! f9 D2 o( n; S4 X Z
- mvar:% e& f3 ?1 S2 ~ Q( E1 ~$ \
- t=clock(),
- % |! u) D& R4 F5 \! h+ q3 v$ m* q* h
- oo{/ h0 f3 B( _- L# P1 g
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],8 W- l7 X6 X, ]2 y
- Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2)))))),0]- N% o! Y. E' i6 i: _
- };8 P% b7 c& }2 ^! S( S
- [clock()-t]/1000;
结果:
- v9 J0 i& m( e$ L. P' N1008606.649474419 X, H0 Q, E; A/ y. W, R" B* Q$ p
0.625 //时间1 Z3 g+ d4 `+ z( [( M! O) Z
% w) C1 {4 ~9 T2 U N0 a% z或者这个,与上面效率差别不大:; ^, _( M9 G9 V d/ A1 y3 i% |
 - !using["math","sys"];# |8 i. J4 ~2 O# L8 T. Z( d5 x0 e5 C
- mvar:, M9 P r& l7 c$ Y. @7 Z( O# l
- t=clock(),6 O5 @9 m: S6 W8 H/ I' e' V* j
- oo{: |* x# H\\" o N, J
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],
- 4 W8 u% L( A% O+ \0 }5 L8 Y- |
- Sum[Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2))))))]]
- : N4 s\\" V/ I# w* F\\" w9 e' O
- };
- , y( B2 p0 E) d8 @9 @5 P
- [clock()-t]/1000;
# P4 X9 [! E( J8 d8 b [3 Z* WForcal代码2:求和函数sum,非矢量化代码
W1 m: x- S4 b- f(x,y)=cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))); 0 @4 {0 @/ [7 W; W3 x$ o% }
- sum["f",0,1,0.0011,1,2,0.0009];
复制代码 结果:
, Z0 s3 h6 v5 Z: }4 c! T1008606.64947441
0 `7 k$ P* a# S8 E$ `0.719 //时间. y: y- h) Y0 a6 @5 C
( C1 I- N. ^/ V& B# \; [8 sForcal代码3:while循环
* c. Y$ Z: V+ P- C. b1 Q- mvar:, S; r# T% m& B9 g3 i9 F4 n6 j
- t=sys::clock();
# I& L2 I+ V3 \# G- u - s=0,x=0,
$ I2 [; ]4 [/ r% t% V+ y R% N - while{x<=1, //while循环算法; , a5 Y- o4 G6 D' w) F
- y=1, 9 t% m4 y+ N- l! A7 k7 G/ M$ U' O' W
- while{y<=2,
, N% X* F. T( b$ M - s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))),
9 i( F) j8 W$ N+ _; g) H7 q - y=y+0.0009
9 ^+ n c8 r$ g0 w9 E2 V, t, a8 k - },
. C' Q, G/ E: Q; c; E. `2 B - x=x+0.0011
5 s2 w. J$ o1 a: M! t+ ?# D - },
- O/ h4 P! K+ g' z; u; e3 v - s;& V8 J3 _6 y2 Y* b* C8 B
- [sys::clock()-t]/1000;
复制代码 结果:
9 `1 U0 i0 I) ]# m( }1008606.64947441; r: c1 r; @) U9 ?8 f
0.734 //时间" h/ e9 s3 [# e' Q0 r2 r: I
& }* Q9 |5 r% ]- V- T. Y* H, }; r N
大家可下载OpenFC进行测试:http://www.forcal.net/xiazai/forcal9/openfc32w.rar
: z* \, l5 ?8 P, g) M6 v, H: R8 r0 R
+ ]) s- l4 H& Q8 R) H注意Forcal的矢量化代码第一次运行有时效率较低。
@* L1 M: ^9 p( ?. x6 S" z" t4 h; A" Y- `# t8 i
例子1中Forcal和matlab都是矢量化代码,但matlab跑不过Forcal。该例子的特点是函数调用频繁,临时变量生成多,但矩阵很小,矩阵的各种函数运行时耗时较少。故说明Forcal函数调用+变量管理效率优于matlab。
$ x W$ W1 X0 b3 V" i
# z" e+ M3 N8 w, e例子2中Forcal的矢量化代码是最快的,但与matlab的矢量化代码相比仍有差距。该例子的特点是函数调用少,临时变量也少,但矩阵大。故说明Forcal的各种矩阵函数Sin、Cos及矩阵的加减运算等函数的内部设计不及matlab。
. t* o$ D- \- k" C/ o+ x$ {# i7 i. x: W. ~) H, Y5 K- f: r1 e
如能在函数内部设计上下点功夫,例子2超越matlab也是可能的。在这方面,期待高手们的指点。
8 H( e7 ^. E5 C0 \9 I
. ~; U* v1 t: t9 c1 ~: r如果例子2速度也超越了matlab ,matlab矢量化的神秘面纱就揭开了。1 }/ }; z5 ]$ a
' F( { {# H2 _% i4 t Y顺便说一下,例子1如果用C++的运算符重载来实现,速度将比Forcal慢一些,也就是说,在涉及运算符重载时,脚本的效率有时比C++还要高些。+ W& b3 @# v( B8 ]/ {, E9 j _
|
|