- 在线时间
- 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 编辑
7 O) L- W" m. G" A1 F# P& O3 K1 _% m
& m) b: V. D+ t, M我正在练手设计的FcMath库也打算以矩阵运算为基础,设计一些专门的函数对数组元素集中运算,运行效率确实有所提高(甚至有些涉及矩阵的算法比matlab还快),代码也简洁了,但不知这是不是矢量化?
3 T! B+ t! T( J3 I5 i0 }7 u& B+ R; p9 {, J- i |5 K* |# M C6 O
脚本运行效率应该取决于函数调度效率、对象管理效率和函数内部算法的实现。# v# G! }4 u1 Z6 k$ y. u, d4 V# u
1 B) V+ |0 }. _0 \6 a# i9 ?我感觉,matlab的函数调度效率较低,对象管理效率这个不好说,但一些函数内部的设计比较优秀。故有些Forcal代码比matlab快,而有些慢。5 _7 k# l6 P9 f/ L( y! W6 Y
8 U/ e* S* M0 R' k
以下例子体现了Forcal和matlab的效率差别所在。7 l }" ] k3 k7 [0 p; B7 v
/ I" j- p7 s. i1 D6 F( d
这个matlab程序段是网友lin2009 给出的,理论结果是每个元素均为275000。- clear all5 Z( v+ H9 d9 t1 W. d) P7 U
- clc1 J, v\" u5 z( H: Q4 k
- tic/ R\" V) D8 U* X: X9 ]
- k = zeros(5,5); % //生成5×5全0矩阵
% ]: ~5 X, S: u2 @6 U - % 循环计算以下程序段1000 00次:8 z3 J: S, o/ V9 k
- for m = 1:1000 00% I/ F0 e4 P! W( K7 A- l# f
- a = rand(5,7);
8 x% W8 B) }9 _ { - b = rand(7,5);%//生成5×7矩阵a,7×5矩阵b,用0~1之间的随机数初始化/ Z0 R\" ?/ e; [1 Y) E
- k = k + a * b + a(1:5, 2:6) * b(2:6, 1:5) - a(:, 7) * b(3, :);
4 N7 `/ ~; }+ }6 a) V6 [* ~* O - end# A3 F7 q: w) ^9 o
- k! R/ D$ \+ U8 u
- toc
复制代码
4 c e, w1 x7 m( _& d* H9 JForcal代码1:运行稍快的代码,比matlab约快10%吧?
/ C9 c! ^) U$ J% b! h+ i* m - !using["math","sys"];
- - P/ n a7 k3 M( V; A- f% V
- mvar:* s2 Q) H3 l* ` E, u1 D
- t0=clock(),- P4 Y% L$ l0 d: c\\" [
- oo{k=zeros[5,5]},% g2 X5 w- e4 \4 `* F N$ i
- i=0,((i++)<100000).while{3 a t* x. ~ W3 \, {
- oo{
- ; O: q0 W4 a1 P
- a=rand[5,7], b=rand[7,5],0 U ^. d1 |$ u+ I1 }% c4 Q, _
- 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)]3 \3 z* E: q, [7 h0 K2 i* u
- }8 W2 Y$ ?1 j1 y8 b
- },
- + r4 h7 m+ P3 j W% j
- k.outm(),
- 7 r, {& B) C! Q* Z
- [clock()-t0]/1000;
在我的电脑上运行时间为3.344秒。( L: F" g2 F/ h1 S- t
* ]- m h5 j+ @) `2 JForcal代码2:比较好看些的代码,似乎也比matlab稍快吧?2 W; S1 U2 t9 ^0 ~* V- l$ P x
 - !using["math","sys"];; k- j+ P8 e- O& K, o
- (:t0,k,i,a,b)=
- 6 g3 m8 i7 n; o( Y- k- `\\" y0 x( B
- {5 P, A# R$ ]9 F- W9 B. _' n
- t0=clock(),4 y2 m) B8 ]3 C& f\\" P8 `- |
- oo{k=zeros[5,5]},; W; Y: h- e8 w- c9 E- z* c
- i=0,((i++)<100000).while{
- \\" H# {8 S& P) g$ }2 V
- oo{( a& d. N+ p3 d0 U& s
- a=rand[5,7], b=rand[7,5],
- 8 A\\" B2 Y6 R) N7 I. j
- k.=k+a*b+a(0,4:1,5)*b(1,5:0,4)-a(neg:6)*b(3:neg)& _; w+ Q, f\\" P/ @/ f8 w\\" ^& u
- }
- . ?- r\\" l8 }# l2 Z s1 Q4 n& F7 n
- },
- 3 W4 \4 P8 x0 K: p% ?' }0 G
- k.outm(),4 _# v0 D E& U
- [clock()-t0]/1000$ S9 I0 p! u4 e& z. U. e
- };
在我的电脑上运行时间为3.579秒。" @, g& `# |0 }8 @' i
9 _1 Q& r9 f* N; H0 u4 Y例子2:$ ^! m1 X) k H, p! `2 D: I( J
一段程序的Forcal实现:
& {; u6 V {8 a8 r- //用C++代码描述为:
' h g P( c+ ]4 }& `$ ` - s=0.0; 5 n2 a3 L5 y! o. L! w
- for(x=0.0;x<=1.0;x=x+0.0011)
+ h7 V- E+ C1 ~. N, p' I7 u) ? - {5 I* {! O2 F% i8 y; T/ Q. a
- for(y=1.0;y<=2.0;y=y+0.0009)2 m3 K0 y# @# J4 N\" }0 [
- {$ }( ^* ?/ t/ Z4 A
- s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));
. l, v* [& W: G- r% I% ^ - }
3 ]) `3 m% D5 ]9 y - }
复制代码 结果:9 ~: F6 Y* T( Q- `5 c
1008606.649474418 z; k# Q! t* {# y* Z G; \' V
0.609 //时间4 x$ A1 l7 e5 F, R7 g6 H
" z8 A" v/ } c% ]3 T
这个matlab程序段是网友yycs001给出的。+ R; U m( A& X, ~1 v* k" v
- %file speedtest.m
. ~- E' L* q% v; G - function speedtest
* Q, w8 w3 _6 ?6 J' T - format long* Y) g* ?6 K2 o/ K\" A6 \( f
- tic6 B3 q/ u/ l\" }- l# O
- [x,y]=meshgrid(0:0.0011:1,1:0.0009:2);
) b+ x6 `8 e9 P. s% ~0 }; j\" O - s=sum(sum(cos(1-sin(1.2*x.^(y/2)+cos(1-sin(1.2*y.^(x/2)))))))/ \/ G/ }* e+ C
- toc
复制代码
( [4 w# i+ i4 l3 U3 wForcal代码1:**数组求和函数Sum,完全矢量化的代码% r+ u7 U" r9 v! m
 - !using["math","sys"];* z* L- g: O- W* I: k
- mvar:- v7 X9 F( R' |% d
- t=clock(), c+ Q4 A3 G& _& y# E C
- oo{- z) N* }0 q\\" K+ ^
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],
- : P' N: P6 Q8 v, F3 K\\" G+ o
- Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2)))))),0]
- O; U0 r% J, o
- };
- 7 I$ y, ~6 D0 }( F5 D3 c$ H
- [clock()-t]/1000;
结果:
( K2 |7 C" I0 \1008606.649474418 V4 k* z, {: C1 }4 J: q6 w: `4 X
0.625 //时间
8 q0 n8 f" V; F: k8 G! M
# P1 w, @, `& [' V* E5 |或者这个,与上面效率差别不大:. t- y1 ^3 p, i7 d7 `% w
 - !using["math","sys"];7 G) R4 z! N9 _. p! g4 r
- mvar:
- 9 s$ f8 U& \. ~- U5 @! E4 D6 F
- t=clock(),. G( T/ [' R/ r5 | n\\" C0 U9 T
- oo{: P+ C' l2 ^ C
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],
- ( R& C' j' x5 ^2 W
- Sum[Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2))))))]]# ~% Y4 [0 y5 e {$ u6 L1 Q2 W\\" j+ a
- };
- 6 e+ d7 Z' ]7 h# k
- [clock()-t]/1000;
" Q/ y o# h; mForcal代码2:求和函数sum,非矢量化代码( C3 Q, y- ?* \3 d
- f(x,y)=cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));
& B0 `9 }4 ~1 C1 ~. \$ b - sum["f",0,1,0.0011,1,2,0.0009];
复制代码 结果:
3 w- Y. G# n1 Q1 i7 F1008606.64947441# h, O) z$ J+ |
0.719 //时间- J( @* C1 R& N
: f* R3 U) c9 E8 \0 F; Z8 f+ t; fForcal代码3:while循环0 i3 n: q* t- d! B9 e8 P
- mvar:) v @0 @' x3 Y& E; r
- t=sys::clock();
! Z4 D\" Z) {- k8 q! B/ Z - s=0,x=0,
% i2 u+ c9 W+ b( T' B - while{x<=1, //while循环算法;
\" n6 \; L$ B1 {$ D! y5 P' n9 F - y=1, 6 P& b8 `* z+ |5 ~) |6 j$ T
- while{y<=2,
1 i; _8 s\" o$ ~. w - s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))), 6 G+ e1 B( F# U; i7 R! _9 ?# n
- y=y+0.0009 5 R! f2 D6 h- y1 m
- }, % [4 P1 b1 G+ K' ^
- x=x+0.0011 : _# ~& ]1 @\" u9 P/ P9 x1 V8 [. a
- },
K: `$ G, D, C8 F/ u1 t, H# Y - s;. E) Z; V2 R/ z
- [sys::clock()-t]/1000;
复制代码 结果:8 L1 m0 [' v! i( Q; `3 l! Q( {
1008606.64947441
' M1 x2 o- d1 P Z0.734 //时间9 l* L. r1 G0 e. @! \7 u+ ?
; p8 }# V: _7 q3 u3 ~
大家可下载OpenFC进行测试:http://www.forcal.net/xiazai/forcal9/openfc32w.rar- T" B3 E# y) v: [ ]
& @# H3 `7 x, t( v& c注意Forcal的矢量化代码第一次运行有时效率较低。
+ Y/ g6 o) G5 x3 b1 P; l8 r' c2 m1 d! F( h1 T9 w4 m
例子1中Forcal和matlab都是矢量化代码,但matlab跑不过Forcal。该例子的特点是函数调用频繁,临时变量生成多,但矩阵很小,矩阵的各种函数运行时耗时较少。故说明Forcal函数调用+变量管理效率优于matlab。% B: E% k e* R4 R- [$ E( q
* Q0 m( o# {" W# m例子2中Forcal的矢量化代码是最快的,但与matlab的矢量化代码相比仍有差距。该例子的特点是函数调用少,临时变量也少,但矩阵大。故说明Forcal的各种矩阵函数Sin、Cos及矩阵的加减运算等函数的内部设计不及matlab。& i8 v, a, u) ?4 B7 \: x& m
) P9 U& P! v; b8 ^$ E
如能在函数内部设计上下点功夫,例子2超越matlab也是可能的。在这方面,期待高手们的指点。
: R% W9 z: H. U# e5 [5 q5 J, S- X u) O0 d
如果例子2速度也超越了matlab ,matlab矢量化的神秘面纱就揭开了。; D3 C5 j6 M% `: _1 \
8 \: n$ O* B% ~- {# p顺便说一下,例子1如果用C++的运算符重载来实现,速度将比Forcal慢一些,也就是说,在涉及运算符重载时,脚本的效率有时比C++还要高些。
8 N+ f5 m& E6 c# _* o8 ` |
|