- 在线时间
- 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 编辑
$ w+ j6 d( G: w3 ^7 ^/ L7 t7 o: x! W
我正在练手设计的FcMath库也打算以矩阵运算为基础,设计一些专门的函数对数组元素集中运算,运行效率确实有所提高(甚至有些涉及矩阵的算法比matlab还快),代码也简洁了,但不知这是不是矢量化?
$ p, |0 o( t y A* h) m8 B; s9 u2 @( B$ m! M# f
脚本运行效率应该取决于函数调度效率、对象管理效率和函数内部算法的实现。
6 D7 {" Z- H, y9 [! L7 K
2 v8 x8 ?3 w. Y( m5 `我感觉,matlab的函数调度效率较低,对象管理效率这个不好说,但一些函数内部的设计比较优秀。故有些Forcal代码比matlab快,而有些慢。+ ~/ g. D' K( d5 \8 y
/ E: X. H7 P+ ]! }! U9 k! r& z以下例子体现了Forcal和matlab的效率差别所在。
. u; m# \% `0 [% p8 b1 i, L# @1 q+ P3 C* z
这个matlab程序段是网友lin2009 给出的,理论结果是每个元素均为275000。- clear all* G2 t\" v6 w4 h7 w2 E
- clc3 f0 W* T- s2 d5 }
- tic; j8 [. \5 i$ q5 q7 G1 T
- k = zeros(5,5); % //生成5×5全0矩阵3 o4 d' |, t% x8 n$ l
- % 循环计算以下程序段1000 00次:+ C2 v\" k$ {4 [
- for m = 1:1000 00: {# q% m+ t\" ] A& O! V- p7 F
- a = rand(5,7);. R: |/ U# x& R- l0 b, h( T/ f
- b = rand(7,5);%//生成5×7矩阵a,7×5矩阵b,用0~1之间的随机数初始化
) o+ [' _ q- Q5 ` B7 e; k) k - k = k + a * b + a(1:5, 2:6) * b(2:6, 1:5) - a(:, 7) * b(3, :);
0 ?: K7 R0 t$ h\" D) a- T - end
5 i1 x8 s, H\" }8 [ - k c5 B3 h- z4 D5 c- N
- toc
复制代码 7 I+ P; Z5 c9 Z% ?6 N' h; @
Forcal代码1:运行稍快的代码,比matlab约快10%吧?
1 ~, N: q. j! Z - !using["math","sys"]; o- Q1 v2 a3 a
- mvar:
- / O, H1 S; @; f
- t0=clock(),
- * [$ v% T$ Q# C3 ]/ K- Q' D, c
- oo{k=zeros[5,5]},
- + {0 Z5 c* o. E: Q& X% ?; M' n. F) P
- i=0,((i++)<100000).while{
- % H) @% i3 ], ]\\" J4 A
- oo{
- - A0 b* x% ?4 m7 C: E
- a=rand[5,7], b=rand[7,5],
- # Z4 ?7 F% V0 U+ 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)]
- ' u# G9 f! U/ Z9 s+ W2 J$ V/ G
- }9 U8 A: o+ s6 k
- },6 ~\\" B* a/ K- d\\" Q4 U+ M5 G9 h( T
- k.outm(),
- 6 ]- N+ z$ l. W/ [9 U
- [clock()-t0]/1000;
在我的电脑上运行时间为3.344秒。
* c. o3 s3 G5 W: F4 }
( w. [: _& l) h: {& |Forcal代码2:比较好看些的代码,似乎也比matlab稍快吧?
3 Y, |. v4 \- t7 C/ t - !using["math","sys"];
- : x+ t- v+ p, c# R( g+ W6 l
- (:t0,k,i,a,b)=4 r' G9 @6 H3 w
- {
- \\" g( s7 I8 k, u
- t0=clock(),3 _( d- l) x' f: f$ n8 F
- oo{k=zeros[5,5]},
- 8 |9 q! ^9 ?0 h
- i=0,((i++)<100000).while{
- * Q' W8 Q\\" `8 \- a9 ~7 \
- oo{
- $ V& ?2 O: ~1 ]\\" w8 W; S0 u' A6 e
- a=rand[5,7], b=rand[7,5],
- ) q\\" T! |$ o* b/ P& i
- k.=k+a*b+a(0,4:1,5)*b(1,5:0,4)-a(neg:6)*b(3:neg)1 O2 M; x( P: W+ K' f3 Y1 o
- }
- ; ?/ F4 C% W9 I* e+ i3 g5 B
- },
- ' E+ s- U# n# M: S
- k.outm(),9 ]+ S& w' N% i3 \3 ^$ k3 y
- [clock()-t0]/1000
- 2 I7 h! e$ }/ y2 Z+ {$ K
- };
在我的电脑上运行时间为3.579秒。5 k$ R* r3 T! X+ ]8 @/ C1 o
2 w$ L) q' g# L: N# |% L1 O1 }# p( ?
例子2:
, u4 @% s% m, D8 A( Z一段程序的Forcal实现:
/ r! A0 ]' S( D6 P& r+ O0 M- //用C++代码描述为:\" a6 K) D5 U7 s/ H3 A
- s=0.0;
- v3 _! Z4 Q& n0 a - for(x=0.0;x<=1.0;x=x+0.0011)
) m7 O2 {* `% {\" z( p6 ? - {$ E$ e8 I4 ~: d- o* M
- for(y=1.0;y<=2.0;y=y+0.0009)1 H2 z* b: F, }) l. g
- {6 z; Y v2 ]+ F
- s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));
4 [7 S\" g7 G6 n0 a; I- J* ~ - }
2 {/ n5 H* \7 H3 C1 B - }
复制代码 结果:0 `! D2 N& ^) [
1008606.64947441
- w" r' }" J7 B) v3 X/ s' ?0.609 //时间
) L3 b$ W; A$ \. f" w) p3 Q" x7 U8 [4 c& }
这个matlab程序段是网友yycs001给出的。
' M7 s1 L6 X6 E/ B( g2 A5 f- %file speedtest.m
: |8 [3 O4 K o; ]7 L9 x, i - function speedtest
- J3 n6 \\" W& I\" z0 A4 i% ]8 B - format long
/ r. I\" r* a\" c( h! O1 R - tic3 s* Y) p$ ~$ K1 L& q* N\" F: h
- [x,y]=meshgrid(0:0.0011:1,1:0.0009:2);
& y4 x* ^3 y2 ]3 ? - s=sum(sum(cos(1-sin(1.2*x.^(y/2)+cos(1-sin(1.2*y.^(x/2)))))))
# |0 o; [! L { - toc
复制代码 / ] V7 M" Q9 ?9 C' K0 H- D
Forcal代码1:**数组求和函数Sum,完全矢量化的代码9 ]5 P& }5 z; P
 - !using["math","sys"];( K4 h8 Q6 _+ u' L) K, e
- mvar:
- ! B/ |, W H/ B8 C
- t=clock(),
- 7 N; ^8 p' Q* ^
- oo{3 m/ O& A3 J0 K6 f3 j5 d\\" Z
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],
- {& v+ F/ E3 M, y {
- Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2)))))),0]
- . F) ~# N p+ a O) ]4 B6 o
- };/ p- q7 h3 l\\" R8 H s% X7 k
- [clock()-t]/1000;
结果:# C9 p: F, h0 j
1008606.64947441
" [6 ~1 W9 o/ q9 {7 g3 i0.625 //时间1 f9 j D$ E$ b# j' k [! W
) W1 \) z; o6 V% k或者这个,与上面效率差别不大:- P W& G6 M; N# b
 - !using["math","sys"];
- 0 ?6 J, x6 V: \; b' G: h
- mvar:! n2 ]9 \4 e5 u' V
- t=clock(),, Y1 H, {8 n# B) a5 c
- oo{
- 7 J# Y3 f/ O/ Q; B& M
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],
- 3 Y6 A% D5 W( R$ b/ V
- Sum[Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2))))))]]( K7 l5 o/ p5 Z7 i, O
- };
- 1 h2 h. u7 r3 e E
- [clock()-t]/1000;
. c. Y- |4 l3 H- }4 ^% m
Forcal代码2:求和函数sum,非矢量化代码
! W7 t* n j6 e( v- f(x,y)=cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))); 9 ?7 t6 X8 T2 b, p$ U8 E
- sum["f",0,1,0.0011,1,2,0.0009];
复制代码 结果:* X4 {& j- `. v+ O/ Z/ v- d$ m
1008606.649474419 l* T6 v$ e. p
0.719 //时间
; ~6 ` V& K* y: C
8 \+ u6 I- h# Y" pForcal代码3:while循环# f# x4 n# r* S2 a. w
- mvar:
8 Z- Q' i2 i+ s( ~0 j - t=sys::clock();
8 e\" v0 X: ^$ x) T* b - s=0,x=0,
5 c+ N7 B/ n1 G9 a; G8 E - while{x<=1, //while循环算法; ' F+ X) o) \. j; {3 D
- y=1, ! [/ R7 _+ F+ p% Y( ], [* r
- while{y<=2, 3 J. k3 J# b5 G
- s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))),
9 K$ E$ _* a! `/ ~, p5 F1 [. ~7 { - y=y+0.0009 7 Z- D\" y$ w1 x7 C/ S
- },
3 N! n$ _% f0 y2 _ - x=x+0.0011
\" ^\" \# l; w. ` - },
- G5 z! J- e4 G! _6 k - s;
5 m2 Z1 E' d. m4 R - [sys::clock()-t]/1000;
复制代码 结果:/ w& N" y( A1 u. E) T) T" Q6 e4 E: _
1008606.64947441
2 g$ ^# Y; O' p* \: D0.734 //时间 K& W L! I. U% |
0 Q4 S* `& w6 @; E# X
大家可下载OpenFC进行测试:http://www.forcal.net/xiazai/forcal9/openfc32w.rar' A# }' y1 H6 s0 q7 L8 l5 V
S; t+ o) t$ p t
注意Forcal的矢量化代码第一次运行有时效率较低。/ j$ u- P8 a( h# b
! b5 f& G. _. L( C) q例子1中Forcal和matlab都是矢量化代码,但matlab跑不过Forcal。该例子的特点是函数调用频繁,临时变量生成多,但矩阵很小,矩阵的各种函数运行时耗时较少。故说明Forcal函数调用+变量管理效率优于matlab。7 R+ ?& ?! h. V) m0 `
! {. M" U5 ?9 O5 @5 {& g/ P, k
例子2中Forcal的矢量化代码是最快的,但与matlab的矢量化代码相比仍有差距。该例子的特点是函数调用少,临时变量也少,但矩阵大。故说明Forcal的各种矩阵函数Sin、Cos及矩阵的加减运算等函数的内部设计不及matlab。
- r$ ~# u' `; Y8 Y ` n0 d6 [! T. E5 X( S8 x5 D/ I+ q
如能在函数内部设计上下点功夫,例子2超越matlab也是可能的。在这方面,期待高手们的指点。' v& d' Z1 I% I
/ F8 D9 I' h$ Z6 o* T5 v4 \如果例子2速度也超越了matlab ,matlab矢量化的神秘面纱就揭开了。( M" p7 [! T/ {9 A) z8 `5 U( k; p2 k
# M Q h7 d8 d' Y" [, l+ ]顺便说一下,例子1如果用C++的运算符重载来实现,速度将比Forcal慢一些,也就是说,在涉及运算符重载时,脚本的效率有时比C++还要高些。, m' r2 Q: N3 d/ D& u; }8 ?3 y
|
|