- 在线时间
- 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 v3 B: Q G' V* B4 b( m% t
2 u& s2 D9 k# L7 c0 I# K: W
我正在练手设计的FcMath库也打算以矩阵运算为基础,设计一些专门的函数对数组元素集中运算,运行效率确实有所提高(甚至有些涉及矩阵的算法比matlab还快),代码也简洁了,但不知这是不是矢量化?
- Z, T C8 ?* O
& P' j. N" s# L- A脚本运行效率应该取决于函数调度效率、对象管理效率和函数内部算法的实现。, Q M$ y' }3 W8 ?' `/ @
3 } I8 o4 [, j1 f
我感觉,matlab的函数调度效率较低,对象管理效率这个不好说,但一些函数内部的设计比较优秀。故有些Forcal代码比matlab快,而有些慢。
|; e% X7 S1 R7 [& _" i% F# B0 @& y4 V, x: Z; b) n; O
以下例子体现了Forcal和matlab的效率差别所在。
4 P: I2 v# U4 Y2 D
- }' n( M2 Q6 U$ j, M这个matlab程序段是网友lin2009 给出的,理论结果是每个元素均为275000。- clear all7 X5 Y7 G! b7 X* ]) y
- clc
7 ^8 O' J$ G% h. k - tic
5 `! ?/ Y% o* T: |1 v1 X0 v: D - k = zeros(5,5); % //生成5×5全0矩阵; ?1 l4 a H! w/ H C
- % 循环计算以下程序段1000 00次:
8 b- e1 P, l }! @9 l& T9 E3 x - for m = 1:1000 00
5 x0 ]+ [% H( a! W3 o - a = rand(5,7);
5 \6 C5 F C/ f% r/ @ _7 z, T - b = rand(7,5);%//生成5×7矩阵a,7×5矩阵b,用0~1之间的随机数初始化
: |6 g& V/ ^4 S. A - k = k + a * b + a(1:5, 2:6) * b(2:6, 1:5) - a(:, 7) * b(3, :);( [+ }+ L3 i( d. v% v+ R
- end8 H% s: i; N# g
- k+ J: J6 h! P$ v2 F7 _7 C
- toc
复制代码
( [3 B" ^1 H! n$ |3 [( f+ eForcal代码1:运行稍快的代码,比matlab约快10%吧?& W( S% o* E& c' o; `. n& \
 - !using["math","sys"];% l+ I- Q# O w! n+ w+ q
- mvar:. z) E. W' F/ n- _8 j5 K F3 k( j7 G) A
- t0=clock(),
- 8 B* P. T: g# w# t0 A: S
- oo{k=zeros[5,5]},
- - [9 W( E* g% c. |+ a3 t
- i=0,((i++)<100000).while{% Z: k& {2 ^7 j8 b( }7 u
- oo{5 ~5 y' A& n% f
- a=rand[5,7], b=rand[7,5],
- ! ]/ k N/ _\\" \; S4 A
- 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)]' f% J3 x\\" C1 s0 s. g
- }
- * T% ~- j+ W& k% c
- },
- - V' v! l# }7 H8 k W) p- x
- k.outm(),
- ' M, }; s( \) e
- [clock()-t0]/1000;
在我的电脑上运行时间为3.344秒。
1 h+ C* R' F3 u, H. v* Y9 Y- V0 ^
Forcal代码2:比较好看些的代码,似乎也比matlab稍快吧?, K$ U# {( q9 d9 R% a, ~
 - !using["math","sys"];% V5 H3 Y$ ~7 q, r. ^\\" }\\" g
- (:t0,k,i,a,b)=
- , B8 u\\" A7 T2 c6 m9 e- h
- {# v# q$ N2 f- k7 E\\" B8 F5 Y# n* N
- t0=clock(),; G* j% B- \! g9 F
- oo{k=zeros[5,5]},& @ u& s& f: h; H2 _7 j
- i=0,((i++)<100000).while{
- ; x; Y ?6 n4 {9 m( { l% Q
- oo{% n9 c3 W, e d7 X: W$ x
- a=rand[5,7], b=rand[7,5],
- \\" ~: ]* @6 x% V+ z
- k.=k+a*b+a(0,4:1,5)*b(1,5:0,4)-a(neg:6)*b(3:neg)
- E9 Z- O) M7 E4 {: S8 `5 {
- }9 g; K! @8 G1 J# h5 D
- },- M4 y9 L4 ?* @
- k.outm(),
- 5 o# d- M6 m, g C
- [clock()-t0]/1000
- ' A3 U, d( B9 Q, q3 b0 D+ u\\" x o
- };
在我的电脑上运行时间为3.579秒。
! [4 y! o" G4 U8 X$ t9 Z8 a) d/ ~1 l; |3 d! R2 r4 z- C4 @
例子2:
0 u3 L' S7 S7 q一段程序的Forcal实现:$ q2 Z9 Z& ]/ j) r! q! K B: d$ x; Y
- //用C++代码描述为:
* S. K\" H/ ?4 U9 z. m# P/ @ - s=0.0; : t, H5 w7 G8 X# H
- for(x=0.0;x<=1.0;x=x+0.0011)
) r l' t2 D- n0 y - {
\" E6 M8 w K& h0 q) t( x# S - for(y=1.0;y<=2.0;y=y+0.0009): m! W% G3 q# Z8 E
- {3 Q; q* R5 f, o! ?8 }1 i. R! q
- s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));+ i+ ^4 }7 {4 B2 J' M7 m |, `
- }: {9 K4 a$ w! O/ l+ Z\" `
- }
复制代码 结果:
O' }2 [( R5 \4 ]) v# P1008606.64947441
8 V% R; X. d% R, ?- O' T9 j0.609 //时间# J( J6 b: [- ?( A0 r4 p' i/ [
" W' E' ^0 v6 Z) O# M$ l) q" r这个matlab程序段是网友yycs001给出的。6 W _( h2 B w: b8 ?
- %file speedtest.m
. p# A) ?2 b2 ? - function speedtest
5 c0 h+ [, I& c/ ` - format long
9 L: I6 D2 ?6 g8 A: s: _1 O5 m - tic3 f4 d8 S x2 t+ r) h0 h7 M
- [x,y]=meshgrid(0:0.0011:1,1:0.0009:2);
8 Z/ X/ F3 Z! W1 x4 M - s=sum(sum(cos(1-sin(1.2*x.^(y/2)+cos(1-sin(1.2*y.^(x/2)))))))
^3 c5 |3 d; T - toc
复制代码 & n2 y3 v) l3 J! l4 J8 n
Forcal代码1:**数组求和函数Sum,完全矢量化的代码
& X3 y5 `" u: ?( V4 S6 j - !using["math","sys"];2 b B( b\\" D% F; d0 |) K
- mvar:) {# y* R! g' A5 ]8 w& t
- t=clock(),7 B1 Z$ j9 T4 y( f/ C' I
- oo{1 t* W$ ?8 E7 Q9 q6 J
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],
- 7 G! u& N R- g; F: c- c
- Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2)))))),0]% D5 x5 o6 Y\\" L9 N! m) m
- };
- ) R) [* ^3 i\\" I2 _9 p' T
- [clock()-t]/1000;
结果:
1 U1 ~2 H8 {; l( a4 D1008606.64947441
/ S# j; c4 h' W' I8 H0.625 //时间
) g" h" r8 A5 q6 ?$ _. o1 x7 @+ d0 w2 ]
或者这个,与上面效率差别不大:
- B* J' i& \ y0 k, F, ~ - !using["math","sys"];6 ~' W: Y6 X4 O2 K2 z3 j. z+ R T
- mvar:9 w+ _6 S# \3 n {, a
- t=clock(),1 v1 V9 c\\" H) t& A
- oo{) _! s/ A9 A$ w/ U
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],
- % H {# |* I8 K. Y- O! \
- Sum[Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2))))))]]
- . E% c2 T: J- R' x5 q
- };) X+ B1 v* x+ r( F+ e
- [clock()-t]/1000;
. e7 A) t' w5 q' p* k5 jForcal代码2:求和函数sum,非矢量化代码
8 y% d) e- q1 ]8 u- f(x,y)=cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));
, ?1 K+ c2 Z- }- i2 l3 G* { - sum["f",0,1,0.0011,1,2,0.0009];
复制代码 结果:; |/ b3 L) X; f
1008606.64947441% w7 `7 K$ [( ?6 e
0.719 //时间
# \3 C, o. J' \8 ~( q* x& g5 V1 b/ \7 _# p' k8 E" X
Forcal代码3:while循环
% B7 ^& j9 y8 R# @6 Y- E+ A- s- mvar:
' t3 @4 o% i/ i: \8 D\" L - t=sys::clock();# c* b r; @( m/ U6 C) W0 o$ v
- s=0,x=0, ' h5 ?' o7 E( U M/ z( J5 K
- while{x<=1, //while循环算法; ) ^) b* \/ V% _: S; _1 @; y# B
- y=1,
; s# W# ]! I5 \/ h: p - while{y<=2,
9 M( l8 o5 T/ i8 L- ~8 [ - s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))),
0 b\" K! ^4 i2 `. M: p% K - y=y+0.0009 3 D9 d+ M9 e\" ]. Y& r. R! z
- },
- o9 j2 j9 X) g2 ~4 I - x=x+0.0011
! Z6 q4 }$ k3 h3 C+ h1 i, p - }, & C2 ^3 S6 o1 N/ q+ j
- s;0 C% M4 y- s! P2 s6 y
- [sys::clock()-t]/1000;
复制代码 结果:. \, N3 L9 ]3 g" P. c, n
1008606.64947441
& N1 B) ?/ ]# h# v2 g( E. N" E* E0.734 //时间
8 S+ i" k8 S* ~# M& ]
, ? Z/ c6 N+ u! Z大家可下载OpenFC进行测试:http://www.forcal.net/xiazai/forcal9/openfc32w.rar% J+ o* r; c$ F% b
7 j! n3 B) h4 A a1 k$ }. C9 B: f注意Forcal的矢量化代码第一次运行有时效率较低。7 ~4 C; `; R& M+ X N* d
% k5 H$ e( v% p1 c" |1 X
例子1中Forcal和matlab都是矢量化代码,但matlab跑不过Forcal。该例子的特点是函数调用频繁,临时变量生成多,但矩阵很小,矩阵的各种函数运行时耗时较少。故说明Forcal函数调用+变量管理效率优于matlab。
/ U D( p8 e N! X' e/ p7 w' _: `( Q, L8 _8 P; F& W1 {3 Z6 T0 q* U1 N
例子2中Forcal的矢量化代码是最快的,但与matlab的矢量化代码相比仍有差距。该例子的特点是函数调用少,临时变量也少,但矩阵大。故说明Forcal的各种矩阵函数Sin、Cos及矩阵的加减运算等函数的内部设计不及matlab。
$ Q) n% C! b7 r. x" P& f3 r
3 b9 O6 y, x$ n/ }# }' S如能在函数内部设计上下点功夫,例子2超越matlab也是可能的。在这方面,期待高手们的指点。/ ]9 [- M4 D5 L0 K, X
! u9 Q. M% F: w- h! P如果例子2速度也超越了matlab ,matlab矢量化的神秘面纱就揭开了。
3 ]# {; v2 [& _3 ^ _" `6 Q7 Z6 r: H
2 N1 [4 G! Q7 S6 `/ s$ v+ }* f; h顺便说一下,例子1如果用C++的运算符重载来实现,速度将比Forcal慢一些,也就是说,在涉及运算符重载时,脚本的效率有时比C++还要高些。2 R; T) o1 G+ i( ^7 h' X8 i
|
|