- 在线时间
- 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 编辑 # Q+ p! `$ `. ?9 `3 P$ l# N
9 K' l) P# i6 b" ?$ k j我正在练手设计的FcMath库也打算以矩阵运算为基础,设计一些专门的函数对数组元素集中运算,运行效率确实有所提高(甚至有些涉及矩阵的算法比matlab还快),代码也简洁了,但不知这是不是矢量化?* M1 s. l. x; ]7 X; F3 p$ {
* s" \; n1 W! [( V脚本运行效率应该取决于函数调度效率、对象管理效率和函数内部算法的实现。
' h$ ]! w5 @9 k+ b6 e$ t! J1 z1 z
" j3 U+ |8 @) l* }9 U8 ^0 y6 ~我感觉,matlab的函数调度效率较低,对象管理效率这个不好说,但一些函数内部的设计比较优秀。故有些Forcal代码比matlab快,而有些慢。
; g2 [: K7 M8 z n/ [$ d+ ?4 H+ U$ u$ f
以下例子体现了Forcal和matlab的效率差别所在。
' G# B! i( @/ s D$ h: C: F
7 c# z( @! o6 ^6 n! `这个matlab程序段是网友lin2009 给出的,理论结果是每个元素均为275000。- clear all) Y$ G3 U C0 r$ v# \
- clc
' w4 U( c/ y3 [2 t - tic2 |: B$ r7 l2 z$ \# ^
- k = zeros(5,5); % //生成5×5全0矩阵
: p7 T' K% ~$ _ - % 循环计算以下程序段1000 00次:3 ^6 r6 \! t/ S: Q! Y
- for m = 1:1000 00- X\" W5 J; C- i5 o
- a = rand(5,7);
& ?1 E) Y8 v' O2 d2 i o4 q - b = rand(7,5);%//生成5×7矩阵a,7×5矩阵b,用0~1之间的随机数初始化# @7 e( @. Y+ T$ l* L
- k = k + a * b + a(1:5, 2:6) * b(2:6, 1:5) - a(:, 7) * b(3, :);
+ v5 ]( D1 R. Q3 a - end
$ j F$ v/ G+ a: F. `& S - k
) L( I# F, |+ j0 e' D( W1 v+ y+ L - toc
复制代码 # b2 A. q) L4 v9 G; Y5 E/ F" o, C
Forcal代码1:运行稍快的代码,比matlab约快10%吧?. J8 D' b5 T6 i v6 R$ f8 X
 - !using["math","sys"];
- ) {, W7 N: ~4 x' |% s$ T
- mvar:. [9 |' H: P* w6 }7 ~
- t0=clock(),3 Y: t1 t* v1 @9 H3 {
- oo{k=zeros[5,5]},, }3 o3 t% ~' s5 V2 n; G' u
- i=0,((i++)<100000).while{
- 6 E1 C7 m\\" k' P O% V7 s
- oo{6 {0 a7 i. t* U- D
- a=rand[5,7], b=rand[7,5],
- : ]& v& B\\" N% Z( \8 L% `
- 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 N8 q5 ?! d! A5 q) U
- }
- ; f9 F7 I- H. m
- },: g5 J+ v/ y& f7 N0 r& _+ J: |9 z3 g5 r. k6 j
- k.outm(),
- 3 ~0 t) S$ J; L! W$ H1 h
- [clock()-t0]/1000;
在我的电脑上运行时间为3.344秒。
% v. M# _: i2 A, a" t: j3 X o
# S0 z! c/ s! `6 q9 h( U5 e# tForcal代码2:比较好看些的代码,似乎也比matlab稍快吧?3 G& G) F2 E4 S. C/ q; S
 - !using["math","sys"];+ k, e( e4 P& N y
- (:t0,k,i,a,b)=
- 0 f$ V) D! J0 H/ E5 B
- {2 P% [- V3 d: M\\" }6 L3 k; G
- t0=clock(),
- ; U$ Q# `: v6 o# D
- oo{k=zeros[5,5]},
- 2 J\\" [4 I% j G* M& U7 t( }! x
- i=0,((i++)<100000).while{
- 6 w! r# w. V. t
- oo{
- 9 r3 |* Q* O: D4 r3 h. z/ m
- a=rand[5,7], b=rand[7,5],5 \6 N( K% Q: i M! }8 [8 v0 T
- k.=k+a*b+a(0,4:1,5)*b(1,5:0,4)-a(neg:6)*b(3:neg)8 i' F( E, u' R0 X
- }- ^: A5 y& f' o7 S' X
- },
- $ w# l, Q. |* Q5 M5 u3 m( c
- k.outm(),$ k* T. L; T) Z1 r; k\\" T& Y% ]
- [clock()-t0]/10009 Q4 m5 I. C\\" g/ Y* h% x# [
- };
在我的电脑上运行时间为3.579秒。$ B8 H! r, o& r: s! g. D
: H5 ^2 @! J; D, _+ E+ i
例子2:
9 K6 { ]( }% c7 c+ e6 v0 }, h一段程序的Forcal实现:
# B; a* K8 B# B5 m5 ?1 j5 j- //用C++代码描述为:/ ?\" r7 @ h8 Z- q
- s=0.0;
- D% U4 I6 ?$ L! I- n i+ N - for(x=0.0;x<=1.0;x=x+0.0011) ; {/ h5 P7 F; W
- {
# m z1 U. {9 c: H - for(y=1.0;y<=2.0;y=y+0.0009)% ]/ N* f4 n5 U7 H5 S; P& [, D
- {
9 t* q, h- S, g6 X8 W - s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));
- \4 X3 A! d- m& a( v, X/ K - }5 l. H& H* e+ V2 y
- }
复制代码 结果:% y0 o9 ^! d4 N8 R) L& ~ q1 {" }
1008606.64947441
- W( Z2 ~: q. X, B0.609 //时间
$ r* P9 B6 U+ O+ l
8 S: H( v3 ~# r% c这个matlab程序段是网友yycs001给出的。
: Z) ?* E( @0 v/ g6 z' ^- %file speedtest.m2 [5 x% S2 h4 o& A
- function speedtest
, R) D4 T& {4 R( ^ - format long
, Z2 g0 A* \' H' s1 q% Z5 p2 T z; N% r - tic- A& i7 R& }. ^5 k7 T9 O5 z! W
- [x,y]=meshgrid(0:0.0011:1,1:0.0009:2);1 X M/ g7 W8 ~5 q4 ?& E4 q, p' D
- s=sum(sum(cos(1-sin(1.2*x.^(y/2)+cos(1-sin(1.2*y.^(x/2)))))))
7 T- ~0 \+ i h+ K5 V! K0 N - toc
复制代码 4 C7 [6 t { a, g8 I* b+ k! D
Forcal代码1:**数组求和函数Sum,完全矢量化的代码1 V2 o1 T( f' O' M0 U. `
 - !using["math","sys"];
- 0 d# @. @3 f( S* @
- mvar:
- 7 A, g$ O! t. P( e; a
- t=clock(),
- _1 C0 L# Y' t6 Z6 q% ^
- oo{
- 9 K/ w4 i% J) P
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],
- # _+ ^3 N& |; W: E
- Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2)))))),0]
- & }; i/ ?6 `- j3 K9 W
- };3 K) ~' `$ N' a6 d/ i6 i9 O/ v+ p; x
- [clock()-t]/1000;
结果:7 R) y" ^2 j5 `7 U
1008606.64947441
5 P, u! i8 P8 u0.625 //时间, q- i L7 A. i' ~2 [3 c
, W+ R' c! A9 l) k; K
或者这个,与上面效率差别不大:- w5 g, u4 ~) V4 B" J
 - !using["math","sys"];
- ( x\\" j' V6 ^ m5 k7 z, a
- mvar:3 B/ I. @% c2 J( Q- e& {) b+ L
- t=clock(),9 k7 a* w9 q% E
- oo{
- + |; T I( R3 i( U
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],5 P# H& q* [( W5 ~: V p8 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))))))]]5 s, u# t# A: n% h% ^0 z) D
- };
- 5 V8 |6 H; k* j; I5 g' ^4 ?2 [( N
- [clock()-t]/1000;
& _4 E/ [ n& C1 s) uForcal代码2:求和函数sum,非矢量化代码
) @, D7 S# t: S, R; H- f(x,y)=cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))); 1 W' ?2 I8 S; c; h0 d( [
- sum["f",0,1,0.0011,1,2,0.0009];
复制代码 结果:6 w! F; P' t4 `: F
1008606.64947441
( H: B5 @( s/ _& X% V& h) R0.719 //时间$ F. W- o' ~% G) v/ ?2 F% B
; j) K$ w c+ ^( Q) W ~. ZForcal代码3:while循环( D. p4 Z6 `1 Y4 X- M. r5 O- P
- mvar:- P% `' G0 c+ J+ X/ h
- t=sys::clock();! U0 {+ q3 M8 Y L' v7 R: }
- s=0,x=0, 4 E* z\" Z8 L/ v6 m' d H
- while{x<=1, //while循环算法; b% j\" x& ]\" {+ o2 u7 H! V5 U
- y=1,
* ~1 j1 m& I6 Y# g# W - while{y<=2,
; [# F4 W2 b9 T - s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))),
9 @/ H; K: z. I6 a; J4 y6 y - y=y+0.0009
$ [: o0 j& g' q9 T: M: a/ l, Q - },
. B' L7 U+ }( J( u. v; H. x\" q3 j: B: ?5 U - x=x+0.0011
* j- g4 i8 c1 F2 h( d7 J# W& A - },
* E f$ I+ x+ O - s;
# [3 y/ s0 ]4 N - [sys::clock()-t]/1000;
复制代码 结果:
0 l# u" `* c5 z4 M1008606.64947441
- y8 j; O3 e1 s+ b7 Q, L0.734 //时间
. t- a& y9 {* ~! |1 p f% ]) m8 W8 {4 Q' f# T# }: g
大家可下载OpenFC进行测试:http://www.forcal.net/xiazai/forcal9/openfc32w.rar8 J( B m/ z3 x) s2 J B
6 H s# ~1 B0 z% M" `5 E- V% s注意Forcal的矢量化代码第一次运行有时效率较低。7 G, G# {$ I3 ~! K& J' u
, W! H" T$ K3 l5 q' p5 l2 O/ y8 n
例子1中Forcal和matlab都是矢量化代码,但matlab跑不过Forcal。该例子的特点是函数调用频繁,临时变量生成多,但矩阵很小,矩阵的各种函数运行时耗时较少。故说明Forcal函数调用+变量管理效率优于matlab。7 g/ E" F9 t) V. H, e" [7 K3 r
9 `) ?" [1 ]0 x* `9 L% G+ c3 U
例子2中Forcal的矢量化代码是最快的,但与matlab的矢量化代码相比仍有差距。该例子的特点是函数调用少,临时变量也少,但矩阵大。故说明Forcal的各种矩阵函数Sin、Cos及矩阵的加减运算等函数的内部设计不及matlab。" j# [# \6 Z8 ^' B1 r4 s
: G6 e' e0 p: k! o1 E2 Q
如能在函数内部设计上下点功夫,例子2超越matlab也是可能的。在这方面,期待高手们的指点。
- s* a1 r4 ^- I7 N3 P5 w5 |3 ?4 `2 J# l, D% k6 G' t
如果例子2速度也超越了matlab ,matlab矢量化的神秘面纱就揭开了。
- S5 I) [" _9 |$ r! g* f
% N& E, v. _" k! `; \8 x: I6 g6 X4 h顺便说一下,例子1如果用C++的运算符重载来实现,速度将比Forcal慢一些,也就是说,在涉及运算符重载时,脚本的效率有时比C++还要高些。
0 e* d' T* b2 g% H/ a |
|