- 在线时间
- 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 编辑
8 b5 {5 d) f$ V" `" S% e' r! H# s% J5 W
我正在练手设计的FcMath库也打算以矩阵运算为基础,设计一些专门的函数对数组元素集中运算,运行效率确实有所提高(甚至有些涉及矩阵的算法比matlab还快),代码也简洁了,但不知这是不是矢量化?
% [2 n% ]; |. w* Z/ f! Y9 _
+ q- z5 E" d2 b& m e h脚本运行效率应该取决于函数调度效率、对象管理效率和函数内部算法的实现。
% ?, c4 f9 T) s" C# h. L6 |, Z* ]# \7 ?7 b7 n" O
我感觉,matlab的函数调度效率较低,对象管理效率这个不好说,但一些函数内部的设计比较优秀。故有些Forcal代码比matlab快,而有些慢。
6 M/ X. X. B8 R' }& b2 U5 T1 A3 |, W2 b) o5 q' ?
以下例子体现了Forcal和matlab的效率差别所在。
4 x0 }7 i4 d9 a% q2 H, F/ L2 h$ V' s# x# @, ^2 G; A9 b
这个matlab程序段是网友lin2009 给出的,理论结果是每个元素均为275000。- clear all
& E5 M/ _8 L& q8 t1 l- }& J - clc! H2 H& K\" v8 y6 J. ~ C/ z
- tic
$ C- [! t4 ^4 v+ L: v& ]0 C' u. l - k = zeros(5,5); % //生成5×5全0矩阵6 N! k0 F- x! T! w8 f8 N, ?, q
- % 循环计算以下程序段1000 00次:5 i7 @\" D8 [/ F$ ?6 p
- for m = 1:1000 008 T/ }+ D6 `! g$ i; W9 G# U; Z
- a = rand(5,7);
& @! _4 X- J9 \' ~3 m8 W - b = rand(7,5);%//生成5×7矩阵a,7×5矩阵b,用0~1之间的随机数初始化
/ K) \/ Q\" ]* O; g3 d - k = k + a * b + a(1:5, 2:6) * b(2:6, 1:5) - a(:, 7) * b(3, :);1 j9 y0 l5 y# m: I
- end
( ?5 J3 M2 ?5 }) a6 i6 j) f/ ` - k- f2 @) H0 ?( s5 z* t
- toc
复制代码 ! |$ \" D o: J- n; M3 U, v$ s. g }" j
Forcal代码1:运行稍快的代码,比matlab约快10%吧?
/ _ Y, X( y' \0 h2 j; H0 T - !using["math","sys"];8 P% P\\" Y( o9 I
- mvar:. t+ m) T6 r3 _4 [
- t0=clock(),
- 5 J/ u | a: G! E\\" v3 h
- oo{k=zeros[5,5]},
- 2 H% ^2 R y4 r. }1 @ x8 W; W
- i=0,((i++)<100000).while{. z. N$ i' ]% h! f
- oo{' b3 L0 c( R- h9 n: H8 R9 [5 r
- a=rand[5,7], b=rand[7,5],) K! n4 F. l: T2 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)]. O* c# V/ V5 R. I$ P. r
- }
- 7 F\\" f. F# X; Q, p& }0 G\\" c
- },
- % C& }; E, R4 j; \5 y/ l
- k.outm(),% m+ { m, }\\" H a3 G6 d
- [clock()-t0]/1000;
在我的电脑上运行时间为3.344秒。) H, X3 s5 z5 n. D- l9 [4 J( e
0 l4 [, n( w( GForcal代码2:比较好看些的代码,似乎也比matlab稍快吧?2 G8 T' ~9 a" r
 - !using["math","sys"];' J4 ]! Q0 b' G* Y3 X$ i
- (:t0,k,i,a,b)=
- 4 V/ ?$ i. e# a) e( ~
- {; q5 I- Z6 f0 B, j5 l
- t0=clock(),
- ( E+ J& R5 b8 I7 U+ _! ~
- oo{k=zeros[5,5]},+ T( h* s M; G5 X( h
- i=0,((i++)<100000).while{
- $ U7 r8 m: G2 K
- oo{
- 4 b% H0 w9 l* S: l1 w
- a=rand[5,7], b=rand[7,5],
- 0 J; {, x+ r) T
- k.=k+a*b+a(0,4:1,5)*b(1,5:0,4)-a(neg:6)*b(3:neg)
- ' T\\" }' {; c3 p8 D' B
- }. u) }. A2 I) l
- },
- 7 l: b' v8 a! x* \- F1 P
- k.outm(),
- ; S8 y( Z\\" d) {& c
- [clock()-t0]/1000
- * O. @- V* W; m5 \; O5 |# J
- };
在我的电脑上运行时间为3.579秒。, P: ?( ^ H" q6 K
% o; D5 L; H; s! u0 B
例子2:6 Q- l3 T# Q) r" O- t
一段程序的Forcal实现:
( H+ p/ z7 k1 }" I0 q* D- //用C++代码描述为:
3 m6 p9 b( w% c6 Q% z - s=0.0; \" Z6 D2 r: ~5 [8 c. d+ r
- for(x=0.0;x<=1.0;x=x+0.0011) 3 h\" T0 S$ Z6 S. A, y! p8 B
- {& }! f# e9 m: _
- for(y=1.0;y<=2.0;y=y+0.0009)7 Z3 r. v1 ]- p0 A& E
- {! f( \5 a3 N4 D\" r$ a
- s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));1 ?7 g) A Y3 }/ K, ^\" Q! C
- }
$ N/ `; [# A1 ?, J7 i - }
复制代码 结果:
4 F T% x' W e6 f0 B0 e1008606.64947441
* m v8 @6 p1 O; _0.609 //时间2 K; j9 G7 u% w* Q" _- Y# b
: T2 V- T0 v; ^* A这个matlab程序段是网友yycs001给出的。. V4 K6 `- ~, [ U
- %file speedtest.m
) x! G/ I- v' u9 A+ r0 v6 D - function speedtest
- H$ @+ u* ]' V' W& A5 E0 o - format long
, C! L+ `: D: ^- w - tic$ ]# Q$ D, R. [9 V; ?* i) Y! y* h
- [x,y]=meshgrid(0:0.0011:1,1:0.0009:2);; r8 e/ ^\" H& q6 Z* Q
- s=sum(sum(cos(1-sin(1.2*x.^(y/2)+cos(1-sin(1.2*y.^(x/2)))))))7 o0 I# H. T; @! E# A3 @; M$ y: G
- toc
复制代码 3 k3 o$ H; }6 f
Forcal代码1:**数组求和函数Sum,完全矢量化的代码
# n6 p q0 d" Q: c+ n - !using["math","sys"];
- * E3 ^5 r. z0 [7 g
- mvar:# ?! H0 R( b i* w2 N% Y
- t=clock(),' T\\" q: v/ Z v2 g0 \8 e
- oo{
- 8 \8 `; `7 s$ j! u! e. f, j
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],
- ! Q5 l- E4 v9 Q0 }( [
- Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2)))))),0]& b; W5 B4 T3 |* L3 \
- };
- / J, K! K: t2 x% F) `8 d, |( g: [ l
- [clock()-t]/1000;
结果:6 ]+ l v- v2 P
1008606.64947441* C; p: V1 b: m8 V7 J
0.625 //时间
5 f9 c- g: \7 q& X% p9 d# f; G/ }! {6 U
或者这个,与上面效率差别不大:* S% f6 e* K" |- f3 I; A
 - !using["math","sys"];
- 1 W4 t$ D) G( C) [
- mvar:& ~- N2 _% ~, S0 k h
- t=clock(),
- \\" N9 R) R I; \8 |# Y( h9 B! I
- oo{* [0 A1 G1 S; ?
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],
- 5 G Y; p5 h+ k/ u\\" P% Q7 U! d
- Sum[Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2))))))]]
- % j# u! F9 I- \( S) M
- };
- . \# X1 D2 u\\" Q5 R* a
- [clock()-t]/1000;
" i% }& g7 G8 d3 L
Forcal代码2:求和函数sum,非矢量化代码7 `' i9 L+ F! O# O! g9 M$ Q
- f(x,y)=cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))); % O9 t; C# g! ^2 h2 ^( f
- sum["f",0,1,0.0011,1,2,0.0009];
复制代码 结果:9 u0 P* i% q, b n3 ]! R* C* i
1008606.64947441
* u+ l& p! W9 T0 ]0.719 //时间5 u, K+ U( S( t3 V: M5 ^
# b1 m+ }0 j# {6 ]) pForcal代码3:while循环( \! U# L6 X; X5 d
- mvar:3 J) p( e& }+ [- n, H: |
- t=sys::clock();
% @6 E+ C. E( f' r |: [+ A: j - s=0,x=0,
/ S6 p5 f$ k. F1 T( K8 F7 G( j - while{x<=1, //while循环算法;
6 n7 x/ r( w4 G6 Y( U$ {1 M - y=1,
. N d. A: r( F5 s - while{y<=2,
5 _% y# P# i1 e7 }# o) @ - s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))),
, b8 u3 u( l( i7 i, c$ V) _# l - y=y+0.0009 - Z1 l u/ D' O; i* G
- },
0 N# v) F) s- h, \ - x=x+0.0011 3 h2 w& l% }) x
- }, ' d7 t7 g4 W* Y1 }
- s;4 P D7 |& I8 d+ T, |; S
- [sys::clock()-t]/1000;
复制代码 结果:; H, P" j5 _, D2 |1 Y' C: ?
1008606.64947441: E6 B E7 D1 M& w# @1 @3 v
0.734 //时间
, J$ A3 p+ _) U2 u
0 I4 k- Y% x3 I' n# R* W- x大家可下载OpenFC进行测试:http://www.forcal.net/xiazai/forcal9/openfc32w.rar# ^# u6 Z$ Z4 R( _" G& ~& ~
, b8 c7 k, R9 K' x. ~" @- j; z i4 U注意Forcal的矢量化代码第一次运行有时效率较低。2 C3 k, U( `4 |( y! X
5 ]/ M9 a, n* [& O: S: `( C例子1中Forcal和matlab都是矢量化代码,但matlab跑不过Forcal。该例子的特点是函数调用频繁,临时变量生成多,但矩阵很小,矩阵的各种函数运行时耗时较少。故说明Forcal函数调用+变量管理效率优于matlab。
- C0 p0 n: ?+ t9 m( [: b" K L0 O1 i5 o9 U9 j6 W
例子2中Forcal的矢量化代码是最快的,但与matlab的矢量化代码相比仍有差距。该例子的特点是函数调用少,临时变量也少,但矩阵大。故说明Forcal的各种矩阵函数Sin、Cos及矩阵的加减运算等函数的内部设计不及matlab。- h7 M* H! L: ~$ G
% w6 p# Y$ Q2 ?如能在函数内部设计上下点功夫,例子2超越matlab也是可能的。在这方面,期待高手们的指点。
3 _; B/ }: c1 E5 w" t: x7 t f1 m0 _
! `& @% |- ^6 N' a1 y( O6 D如果例子2速度也超越了matlab ,matlab矢量化的神秘面纱就揭开了。
% M0 W/ ?6 h$ {" q; ~1 W" o" U- s- v/ n/ |( S
顺便说一下,例子1如果用C++的运算符重载来实现,速度将比Forcal慢一些,也就是说,在涉及运算符重载时,脚本的效率有时比C++还要高些。7 h2 \" V# G1 p; k/ z) G
|
|