- 在线时间
- 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 编辑 & p4 D0 z6 c6 P; P3 d
$ \# N9 a7 b' j. q3 h我正在练手设计的FcMath库也打算以矩阵运算为基础,设计一些专门的函数对数组元素集中运算,运行效率确实有所提高(甚至有些涉及矩阵的算法比matlab还快),代码也简洁了,但不知这是不是矢量化?' c s& e- N, H, ~- z5 u
& O. }" g" T. U% W% r脚本运行效率应该取决于函数调度效率、对象管理效率和函数内部算法的实现。4 j7 `, L- P3 _. G
6 n l5 K) c1 E7 h6 S/ W! O我感觉,matlab的函数调度效率较低,对象管理效率这个不好说,但一些函数内部的设计比较优秀。故有些Forcal代码比matlab快,而有些慢。/ o+ r. {# e2 F( ~# m" U1 i$ j
2 q( I% x' ^; Z7 ?
以下例子体现了Forcal和matlab的效率差别所在。( K, W! {+ ?' o& B& Z- G
v) O& `$ k8 P' S0 b这个matlab程序段是网友lin2009 给出的,理论结果是每个元素均为275000。- clear all# a `\" J* |3 i\" w `
- clc
: O8 B0 A; w) ^& e/ a - tic5 x: K0 } m' q. t5 g
- k = zeros(5,5); % //生成5×5全0矩阵
\" L\" V9 x8 `: [3 p+ _- h( } - % 循环计算以下程序段1000 00次:
% P1 M* e1 A7 I( O0 @7 {\" L - for m = 1:1000 004 \ h4 o1 o6 P% t, z
- a = rand(5,7);
) e+ I$ l c2 j! c' V( H2 a - b = rand(7,5);%//生成5×7矩阵a,7×5矩阵b,用0~1之间的随机数初始化
/ n+ {! D' w% e( R - k = k + a * b + a(1:5, 2:6) * b(2:6, 1:5) - a(:, 7) * b(3, :);
' ^/ G5 Y( A6 y! p$ {. j - end0 l. o9 i8 m- T: m4 S
- k# V# X. |9 H* }& ]/ h& G c
- toc
复制代码 ?9 d, | B4 u( k: t
Forcal代码1:运行稍快的代码,比matlab约快10%吧?
4 Y. ]' q% j& G, h7 d - !using["math","sys"]; [\\" Q9 p- u\\" X8 a' k% _8 L
- mvar:# P8 Q( K7 |! F$ p1 O! g
- t0=clock(),/ B- t2 ^/ X9 M
- oo{k=zeros[5,5]},
- - _% M9 @$ y; U5 N Y+ E) Z
- i=0,((i++)<100000).while{
- & Y7 [- A) ]/ W4 k
- oo{
- 4 T: A: B\\" z! R J0 J3 ~3 Z5 W
- a=rand[5,7], b=rand[7,5],
- 5 W# s! p' V& |& ^7 ?4 y- Y! Z
- 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)]
- . F5 b- y; A; h% `+ Y5 h\\" t# o
- }
- ! ~, \; C; |/ `. a1 F
- },6 }( u$ D, ^% ]* C# [
- k.outm(),
- 5 \. Z5 ~; _# A! H8 }% k9 _
- [clock()-t0]/1000;
在我的电脑上运行时间为3.344秒。/ v+ w) w$ Y- }
$ M* A) l7 O1 D/ ^8 a1 p3 HForcal代码2:比较好看些的代码,似乎也比matlab稍快吧?
3 E% ?. Z/ ~% C- p6 ^ - !using["math","sys"];
- ; r* S8 L4 G% v+ }' e
- (:t0,k,i,a,b)=; |. u1 V* ]6 l; E; h$ U
- {. Z# e x- e3 X' _# g
- t0=clock(),
- / B( [# V( |* I. Z# J; q
- oo{k=zeros[5,5]},, Q4 w. G: A' Y, S/ m
- i=0,((i++)<100000).while{2 \6 j9 ~! ?1 `\\" C1 P }& `% T
- oo{! c1 `. O) J6 o1 }& G9 H! e, @
- a=rand[5,7], b=rand[7,5],! k% |0 T+ m, A5 x4 p0 ?2 k. m
- k.=k+a*b+a(0,4:1,5)*b(1,5:0,4)-a(neg:6)*b(3:neg)
- - p V1 [! O& e4 Z j; {6 j( X
- } w; t+ p$ R6 N: N# ~- u
- },
- 1 X' N9 z/ [4 b* t\\" k7 _' `
- k.outm(),
- ! u. X1 I# Z5 g5 L& K
- [clock()-t0]/1000
- 5 U! Z+ N* }6 `- a3 v
- };
在我的电脑上运行时间为3.579秒。
4 P" r0 O8 R, C* T! x/ X9 ?& H9 }3 i' W9 B7 I) [7 J
例子2:
( N. M) S. c/ Q! a一段程序的Forcal实现:
' l/ a% t' B8 s8 I- //用C++代码描述为:
4 ^& V3 @, w4 h - s=0.0; : [3 g; X2 z7 c7 N3 h
- for(x=0.0;x<=1.0;x=x+0.0011)
$ ]. t. L9 H* X/ ?) n - {
4 @$ A# w3 N; E( ~ - for(y=1.0;y<=2.0;y=y+0.0009)
/ G& e; Y0 S8 p3 ] - {
7 F- t; G( n: b0 C- F; t - s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));$ |5 M g: \9 g' Q# P& l% a! R* S
- }
5 S: Y6 ?+ u9 x- |* t5 \, l F\" u - }
复制代码 结果:
8 ?* }6 _: j' Z# r8 C% c8 n4 q1008606.64947441
+ M; T# w4 t, H1 D$ ?" \2 A. z! K0.609 //时间
7 R6 d$ V8 t- f5 k3 [* \5 X( D
; t" r' x( t$ C这个matlab程序段是网友yycs001给出的。- I0 E9 d1 |; ?) i; p& j! e! L: L
- %file speedtest.m! b. j1 T1 C3 S! ^# t
- function speedtest
5 E+ u0 v1 L9 j& [- i! L& C4 p - format long; a8 y\" ^. f* G2 Y$ f6 q$ E
- tic
# }5 y7 c2 Q o: U - [x,y]=meshgrid(0:0.0011:1,1:0.0009:2);\" ^8 f/ v8 K+ z7 n6 E' K& \
- s=sum(sum(cos(1-sin(1.2*x.^(y/2)+cos(1-sin(1.2*y.^(x/2)))))))' o- y1 d7 f. k7 [9 i7 R6 }: a0 p& Y
- toc
复制代码 6 G7 i" o) \3 L; O$ y
Forcal代码1:**数组求和函数Sum,完全矢量化的代码5 R, Q/ B* r4 F/ W- f
 - !using["math","sys"];
- ) s$ U% L! G& h' K
- mvar:% e; l* I Q& c- D
- t=clock(),& C8 b2 m+ W' x2 Z6 C
- oo{1 H* P. _6 p5 A- x2 h6 T/ b; _
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],
- ! j2 l) z4 F F2 i& p( t6 M* P
- Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2)))))),0], G* q9 j7 ^2 ^8 x\\" E
- };3 ~- }6 G: ]3 p( i0 L
- [clock()-t]/1000;
结果:
4 E5 f2 B0 ?4 O! C. } L1 S1008606.649474415 J1 l$ |; [! \6 z
0.625 //时间
d) m4 S% _, ?# i A l5 I9 |+ F' t3 @2 X. l* e& p# X) x6 n
或者这个,与上面效率差别不大:: [; s# w1 i: n( I$ ^' w# }
 - !using["math","sys"];
- + e, {/ U% ?) n/ t2 U& s
- mvar:$ P. C' x% K5 y& f! A
- t=clock(),5 U3 F) S/ ^# p
- oo{; s1 |- ?! w& X3 d$ @
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],
- 1 G* u I/ r1 E) B
- Sum[Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2))))))]]% O\\" `% N% b5 @. ?
- };
- 9 M7 ]% ]! p0 r# |
- [clock()-t]/1000;
4 U+ O- ^1 ~3 U5 }1 xForcal代码2:求和函数sum,非矢量化代码
5 J/ i" q* a2 a: m8 y- f(x,y)=cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));
]5 {7 T7 v$ K6 Z6 o - sum["f",0,1,0.0011,1,2,0.0009];
复制代码 结果:
# J7 n# x/ K4 ^ _9 R- z1008606.64947441
% F3 J, J$ f, b0.719 //时间
, x6 \% a1 F# _# h
8 s" o# ?' F2 i/ t) f$ `: GForcal代码3:while循环) L; L! M/ d$ i- a% @: T U7 I+ Q# Y
- mvar:
( p5 d& Q2 \, Z1 l: k, d - t=sys::clock();- p& o, `+ \+ K% @; i: W
- s=0,x=0,
- C% `; F3 q( @ - while{x<=1, //while循环算法; * E; \, w7 f. }4 ^3 H
- y=1, 9 _ O. l6 K% w) }\" c6 o7 M
- while{y<=2, ) V; o7 Q9 |! R4 S' \6 ?
- s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))), # r8 i5 {! z- L
- y=y+0.0009 / ^4 m& O) |; ~/ T
- }, 8 u$ A' ]$ R8 l: |* t0 A
- x=x+0.0011
0 ]7 e( B6 m0 M0 q4 u: g - }, 6 F; {, d$ E\" I* t
- s;
' M6 F! k' N\" h. Y5 F* Y - [sys::clock()-t]/1000;
复制代码 结果:
& q2 @7 X4 g; D$ p8 Z8 G1008606.64947441$ ]* @- e, ?: r: f6 T; }& b O
0.734 //时间& E5 d `8 [- T1 H/ Y
3 d; n& q3 Y+ j. t" R& b& k: |! a大家可下载OpenFC进行测试:http://www.forcal.net/xiazai/forcal9/openfc32w.rar
" `5 u. d; C, q' O( c b5 x4 u# x- b
3 [& f$ M( z0 }. b/ J- s注意Forcal的矢量化代码第一次运行有时效率较低。
9 k1 X7 X- p- E5 f
?5 C2 a) T. i# a$ j+ e例子1中Forcal和matlab都是矢量化代码,但matlab跑不过Forcal。该例子的特点是函数调用频繁,临时变量生成多,但矩阵很小,矩阵的各种函数运行时耗时较少。故说明Forcal函数调用+变量管理效率优于matlab。* P& l, Y7 q0 E
+ B+ o3 L: i: o9 R: t例子2中Forcal的矢量化代码是最快的,但与matlab的矢量化代码相比仍有差距。该例子的特点是函数调用少,临时变量也少,但矩阵大。故说明Forcal的各种矩阵函数Sin、Cos及矩阵的加减运算等函数的内部设计不及matlab。
4 K& M0 q6 u9 v0 z$ j" M+ J2 ^8 P0 a9 \+ ?
如能在函数内部设计上下点功夫,例子2超越matlab也是可能的。在这方面,期待高手们的指点。+ I6 c3 D3 j* o) y) {- [. ^8 Y
* K$ h5 G, z, I+ z
如果例子2速度也超越了matlab ,matlab矢量化的神秘面纱就揭开了。
" t7 _( f# U2 y. ~8 n Z+ m: F% z! ?, x7 H; B. p
顺便说一下,例子1如果用C++的运算符重载来实现,速度将比Forcal慢一些,也就是说,在涉及运算符重载时,脚本的效率有时比C++还要高些。
! H9 w; b) B" F4 \+ X8 O; \6 H |
|