- 在线时间
- 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 编辑
. H+ V% C$ x1 W, e( o% Z" l0 T1 Y7 B. f+ _& m# N
我正在练手设计的FcMath库也打算以矩阵运算为基础,设计一些专门的函数对数组元素集中运算,运行效率确实有所提高(甚至有些涉及矩阵的算法比matlab还快),代码也简洁了,但不知这是不是矢量化?
# k4 h5 `; W0 Y
2 @$ q0 {( b G% u" Z3 c脚本运行效率应该取决于函数调度效率、对象管理效率和函数内部算法的实现。
$ z) N( z: e1 g' d9 s$ @- Z
9 D7 w3 Z' s9 T* ]0 \, H0 A4 f& ?我感觉,matlab的函数调度效率较低,对象管理效率这个不好说,但一些函数内部的设计比较优秀。故有些Forcal代码比matlab快,而有些慢。
, W& T0 K( f+ T, {! Z3 k- s' t" ~ K# [4 P, Y
以下例子体现了Forcal和matlab的效率差别所在。
" a/ ^0 H$ A f/ l7 d7 a( |5 T: h, e8 R1 u8 U
这个matlab程序段是网友lin2009 给出的,理论结果是每个元素均为275000。- clear all
2 B6 s) Q L1 U\" M - clc- ~& j, ?) c/ S% w
- tic' U$ D }1 X* K( A# K5 i0 X
- k = zeros(5,5); % //生成5×5全0矩阵' z a1 {3 Z8 u1 G, Y& l2 q
- % 循环计算以下程序段1000 00次:
3 P/ s2 r2 b# w - for m = 1:1000 00/ {. T\" U$ u% \& \, Y# `
- a = rand(5,7);1 x9 b& E4 g- B9 h& a
- b = rand(7,5);%//生成5×7矩阵a,7×5矩阵b,用0~1之间的随机数初始化# a! j9 e. j\" d- @- W9 G. v
- k = k + a * b + a(1:5, 2:6) * b(2:6, 1:5) - a(:, 7) * b(3, :);2 `+ N, g* t- z# l4 t! I! W
- end( x: x6 N4 a! D0 W1 T) J
- k! x9 o( C$ a+ E
- toc
复制代码
# G" F% Q; V$ J: [; i9 v: TForcal代码1:运行稍快的代码,比matlab约快10%吧?) r1 _. C$ y. k7 ]
 - !using["math","sys"];
- ' F6 P R; S\\" Y) ^6 a1 k* V* R
- mvar:
- 3 S9 g. w( N3 j4 F
- t0=clock(),' k8 [; k) `+ ]0 D
- oo{k=zeros[5,5]},
- ) F! a! n6 w, f/ |
- i=0,((i++)<100000).while{$ T+ X/ H* m8 L' x2 D
- oo{9 U' v+ c( M L' K
- a=rand[5,7], b=rand[7,5],. r8 N7 q0 ]- v1 w% c$ E7 _/ n
- 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)]
- 9 ^) |5 n0 |\\" f) o# R
- }
- 7 U+ e% d* M! K- l* q- R6 G4 Y
- },9 b6 w4 X0 Y1 n) q! @5 ^: M\\" U7 f! G
- k.outm(),
- . [1 R7 `2 B2 n# b) O
- [clock()-t0]/1000;
在我的电脑上运行时间为3.344秒。# s2 m5 ]8 W# h8 Z! R; Y
7 B* \0 P5 c7 P# j# L \
Forcal代码2:比较好看些的代码,似乎也比matlab稍快吧?
/ ?3 I" o$ V* }, v, x5 F k% W - !using["math","sys"];9 g# ]5 o9 }+ r/ j5 l: C
- (:t0,k,i,a,b)=2 u\\" M3 m5 ]; A! T0 H
- {# d$ P! D9 A6 M6 Z1 F
- t0=clock(),
- 2 u6 O8 n* a3 h# m5 x
- oo{k=zeros[5,5]},
- % P$ a, G7 E6 x6 N; C1 ^
- i=0,((i++)<100000).while{
- % b7 A; [& X& y) }% u. f5 v
- oo{
- 9 E5 |5 c: x+ l- T+ `
- a=rand[5,7], b=rand[7,5],
- 2 P0 w( H9 E7 W4 s
- k.=k+a*b+a(0,4:1,5)*b(1,5:0,4)-a(neg:6)*b(3:neg)
- 1 w3 p! |) \. e2 C\\" o: J
- }4 k0 t8 g3 R\\" U' O- t% h$ ~
- },; v8 H: i# l. ?3 H) v+ Y
- k.outm(),
- 8 u/ x8 V7 M. O\\" z- P$ n. q3 |/ p
- [clock()-t0]/1000
- % g2 _/ @+ C n; q7 \! `$ i% n9 D
- };
在我的电脑上运行时间为3.579秒。. {5 [/ x5 X8 L7 G q# r" n9 z1 _
$ b f' F% \+ [7 Q例子2:
, u% F/ _0 K! z一段程序的Forcal实现:
3 x+ R; W' B& W6 w7 F- //用C++代码描述为: J/ J6 f5 }; C5 D
- s=0.0;
\" J2 Q& ~. M' }2 F\" m& l2 c+ X - for(x=0.0;x<=1.0;x=x+0.0011)
* R) Y* V# a5 R - {' b q `6 @# D0 D2 B# I* T1 R
- for(y=1.0;y<=2.0;y=y+0.0009)
. i5 P7 Q/ u( A\" z @! l - {
! h1 g' C) w( i6 Y x - s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));
\" D0 d+ M6 x' X4 a - }. c, K\" W5 Y6 w) B( B m1 V; ~ i
- }
复制代码 结果:
# F7 N8 n1 T1 E2 b+ F1008606.64947441
& Y) [/ o" s4 N2 `8 | i0.609 //时间: v) |& F% M* l7 L7 W' A
8 S5 i* D3 ^ W Q
这个matlab程序段是网友yycs001给出的。
( A. n5 L* L# f, c7 `- %file speedtest.m7 \/ K+ q9 A: z, l\" m0 b2 t
- function speedtest. F) L4 z9 y; M) q
- format long& E _% C' n! U; p9 b\" {
- tic
6 X% C$ I/ [# O - [x,y]=meshgrid(0:0.0011:1,1:0.0009:2);
' R& G, j9 J2 B: U$ I+ @ - s=sum(sum(cos(1-sin(1.2*x.^(y/2)+cos(1-sin(1.2*y.^(x/2)))))))
/ s1 p* A0 O! y( }9 ]; L/ D% i - toc
复制代码 7 k0 g/ h$ D @ O; Z9 I* ]
Forcal代码1:**数组求和函数Sum,完全矢量化的代码' P; ]) V3 G/ C4 w0 U+ l
 - !using["math","sys"];
- 1 d% Q9 y+ j1 X+ Q
- mvar:
- k& Q9 S. B+ O3 B9 e% m& Y2 V
- t=clock(),5 Q4 N: o- D& h' x& U\\" E# N
- oo{3 h\\" T% z' j$ U
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],
- # i* b' h. [0 \6 w
- Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2)))))),0]
- 6 F* k8 x, A; b
- };: }5 @0 r( C) O/ [. G$ k; f
- [clock()-t]/1000;
结果:; B% N, q9 s8 P/ }* q: t
1008606.64947441& E+ o) d7 z- ~; R
0.625 //时间
" Y# k1 `' o3 e- P% p
- E; i! p0 n8 |9 G/ T" F或者这个,与上面效率差别不大:
! B" b6 C' D7 u - !using["math","sys"];! A7 F$ \7 i9 [5 n# s O
- mvar:* h\\" L& C1 H% o; o/ o5 `
- t=clock(),; N$ F1 ^9 ~/ G! S6 ^
- oo{
- # ]- r0 O; ~$ u, `' J+ b
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],* }- H8 y' `* Z; g0 C# p
- Sum[Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2))))))]]9 z0 d4 @9 d9 f& X; q
- };
- * q2 G8 \0 S$ t8 B9 u
- [clock()-t]/1000;
: n7 r3 k) J9 Z8 ?: J' `; wForcal代码2:求和函数sum,非矢量化代码
6 ]& t- O. i/ @5 r# m) a6 T8 G' M- f(x,y)=cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));
/ x7 _% q+ I0 U# w2 W - sum["f",0,1,0.0011,1,2,0.0009];
复制代码 结果:
/ D; K* _' ?: K$ m0 ~% r1008606.64947441
' {$ I# G+ x* B* i% X9 z0.719 //时间& P. ^3 O- q8 ~/ |$ Z% j
& l7 x& o7 R7 \7 k
Forcal代码3:while循环 q V9 f( l1 U- j" _5 S& ^. }
- mvar:8 k; G3 L# t! N: t
- t=sys::clock();
. M, l. s/ T6 k, i, H - s=0,x=0,
0 s9 \# t8 |: G) E - while{x<=1, //while循环算法;
# M/ w) C- E/ M, j% b5 V - y=1, 3 X' l( _8 q6 _& |( H/ ^7 v
- while{y<=2,
& ]3 ^1 Z4 q5 j( v6 w4 H, g - s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))),
' `! ^3 N9 H, j' z; [ - y=y+0.0009
3 B8 x& s( Y4 r8 C\" p7 T0 N - }, \" f$ }+ e3 l2 s: c: _8 I( ^8 E3 ?3 J
- x=x+0.0011
) O& l. w- J0 }3 } - },
5 _# M- s9 \, Y7 N - s;
4 D: u; c; b7 d - [sys::clock()-t]/1000;
复制代码 结果:$ M2 a, j* t3 E" y$ T0 O N
1008606.64947441
/ _ Y0 p1 c/ a! G1 H4 i0.734 //时间; n8 p W, r n" c! q- A2 \9 ?) }
& ?/ s+ ^4 z& R( h& Z' m5 U
大家可下载OpenFC进行测试:http://www.forcal.net/xiazai/forcal9/openfc32w.rar0 N0 d N. j7 t% K
' u R2 r: m8 z2 ^, R g8 u" M注意Forcal的矢量化代码第一次运行有时效率较低。3 t, T- L% ]( n; i( _
5 p/ \2 n2 K* K: g0 v4 z5 c! n
例子1中Forcal和matlab都是矢量化代码,但matlab跑不过Forcal。该例子的特点是函数调用频繁,临时变量生成多,但矩阵很小,矩阵的各种函数运行时耗时较少。故说明Forcal函数调用+变量管理效率优于matlab。
5 F% g8 F+ ^$ k; N7 e" y. c& Z' o) M7 H) _
例子2中Forcal的矢量化代码是最快的,但与matlab的矢量化代码相比仍有差距。该例子的特点是函数调用少,临时变量也少,但矩阵大。故说明Forcal的各种矩阵函数Sin、Cos及矩阵的加减运算等函数的内部设计不及matlab。
8 K6 d. g. Q" i) s
8 _8 }; A9 [8 r8 L! {; Z" X' w: J如能在函数内部设计上下点功夫,例子2超越matlab也是可能的。在这方面,期待高手们的指点。
2 r1 z* r: r: _) [+ R1 N1 p5 K$ V# _: [
如果例子2速度也超越了matlab ,matlab矢量化的神秘面纱就揭开了。- `' ?0 V- D, y+ m
' p# H! Q+ [+ `: x8 L$ w顺便说一下,例子1如果用C++的运算符重载来实现,速度将比Forcal慢一些,也就是说,在涉及运算符重载时,脚本的效率有时比C++还要高些。
: S2 o1 B0 A7 z+ R( {) y. S. I$ b |
|