- 在线时间
- 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 编辑
# v% ?. q, s( a( k/ L
( u; A! s/ U# I9 k; n7 x8 t我正在练手设计的FcMath库也打算以矩阵运算为基础,设计一些专门的函数对数组元素集中运算,运行效率确实有所提高(甚至有些涉及矩阵的算法比matlab还快),代码也简洁了,但不知这是不是矢量化?2 f; Z* ^% J& T
, B4 L! Q$ X8 F: F1 w+ T. {0 n
脚本运行效率应该取决于函数调度效率、对象管理效率和函数内部算法的实现。
' h. F" E0 ~2 t& n, R ?. N1 Y0 Z. J! Y
我感觉,matlab的函数调度效率较低,对象管理效率这个不好说,但一些函数内部的设计比较优秀。故有些Forcal代码比matlab快,而有些慢。
3 T( ? N u. [8 N { k' `# r1 S5 t) H) s+ B/ n
以下例子体现了Forcal和matlab的效率差别所在。) X( y0 m% J( F5 [# B+ Z9 s
4 ~- b6 W1 n4 R( A7 K. `! S4 Y
这个matlab程序段是网友lin2009 给出的,理论结果是每个元素均为275000。- clear all
! k! L: @' O) l: r - clc
! ^; m2 T0 ^9 E, Z\" ~7 h1 | - tic
# n7 J* e k8 b - k = zeros(5,5); % //生成5×5全0矩阵) ]& f, F; m( L: w/ E, a
- % 循环计算以下程序段1000 00次:
5 C& v v) t) A( t1 G. I7 }+ A - for m = 1:1000 00! A$ @$ K9 F# G v6 }9 t& Z: J
- a = rand(5,7);! J% [7 Z$ i. ~1 A [6 i2 T, c' M
- b = rand(7,5);%//生成5×7矩阵a,7×5矩阵b,用0~1之间的随机数初始化' R4 {: v5 k. X+ u5 \
- k = k + a * b + a(1:5, 2:6) * b(2:6, 1:5) - a(:, 7) * b(3, :);( [9 x/ a3 K: F; y; X, ~
- end- D% c2 u* l) U+ p. y( s\" r5 G3 {
- k/ k U d5 i9 O+ w( g/ F6 D
- toc
复制代码
" V9 m0 K3 ~9 SForcal代码1:运行稍快的代码,比matlab约快10%吧?
- O# p; V& e0 o6 { a2 N - !using["math","sys"];% }& Q) _ ]1 W- x
- mvar:
- 1 }' `8 ^& R# L( a ^
- t0=clock(),) f+ [6 {* R) |; Y* Q
- oo{k=zeros[5,5]},
- . W! c0 K' g6 N3 u
- i=0,((i++)<100000).while{
- : ~5 {$ s3 Q2 Y
- oo{
- \\" V3 H2 @5 b7 s( N) t: k- l
- a=rand[5,7], b=rand[7,5],
- 7 M8 t- s( 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)]
- / h5 t- @\\" l- C
- }
- ' X& ~0 p, Y6 v) W
- },2 P6 M\\" O\\" p, ]2 v( S
- k.outm(),
- 6 `$ ^ j) ^, {8 N5 k
- [clock()-t0]/1000;
在我的电脑上运行时间为3.344秒。
1 s( F1 e" I. j- V6 C- Z) s
8 N& j; [! d0 T: e" r4 U1 N. MForcal代码2:比较好看些的代码,似乎也比matlab稍快吧?
1 g: u& \( G' A, A - !using["math","sys"];3 {2 ^; r9 T+ ]! b! I
- (:t0,k,i,a,b)=
- ) q\\" c7 \4 a2 w) Q
- {
- ) }4 |; }8 f$ V. W4 ~
- t0=clock(),\\" \ Y1 [3 b. v3 S
- oo{k=zeros[5,5]},, b9 z4 s) X9 U4 q2 @
- i=0,((i++)<100000).while{
- \\" A3 j: Q. h3 j4 H( A- s
- oo{
- ; t' {( U1 q) G% O1 ^
- a=rand[5,7], b=rand[7,5],/ z! |/ }9 T# E
- k.=k+a*b+a(0,4:1,5)*b(1,5:0,4)-a(neg:6)*b(3:neg)/ m {; b' c# _9 l) J- W4 G\\" y
- }- y5 X% t' X% @) z1 J& V1 M/ T
- },3 L' I( G8 n# R: P; g% Z6 X' s
- k.outm(),
- 2 q( d% l4 M$ ]2 t! j
- [clock()-t0]/10000 ]\\" K' c% P( x6 i9 n
- };
在我的电脑上运行时间为3.579秒。
x, K7 ^7 k, `) o, V5 O; j
: T* K" P9 V# p* H例子2:
: e( K+ E% r' e) `" p- c. l: s# F7 H一段程序的Forcal实现:4 J2 Q x; e! d- p
- //用C++代码描述为:* B1 L' X) k$ G/ V5 s; E
- s=0.0;
! r+ l. P; W. `! ^; D - for(x=0.0;x<=1.0;x=x+0.0011) 4 Q+ i9 d( v1 P' V
- {
$ \* m( C$ a2 m$ M# ~\" ?3 e& k - for(y=1.0;y<=2.0;y=y+0.0009). v6 h8 n4 {% a. Y) L5 r
- {! a2 y\" M6 ?/ m* L& W9 c
- s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));
9 h' @+ J0 \: H, F1 m: i - }
, o1 \+ F\" S7 G( w; | - }
复制代码 结果:
4 J$ u8 N N% p$ U1008606.649474410 j- ]8 W* O2 l& ]: f' f
0.609 //时间
; g4 L/ j; Y. F" c0 c1 j! F0 I
0 T D9 K) {0 C) b: k! ^这个matlab程序段是网友yycs001给出的。
2 H9 I+ x: A: v: }7 V/ ~3 J- %file speedtest.m
, [) _. R6 e- z c9 s - function speedtest* i9 ~ B/ x u: i+ D1 J
- format long' Q' [* t+ R+ b; s7 }9 A
- tic# |+ p% E5 S7 d\" Q$ a
- [x,y]=meshgrid(0:0.0011:1,1:0.0009:2);2 q. _. y& R# C, p+ C, Z( D) a$ L
- s=sum(sum(cos(1-sin(1.2*x.^(y/2)+cos(1-sin(1.2*y.^(x/2)))))))
2 D4 c, S/ q% C0 w9 P8 {2 l+ O; S - toc
复制代码 2 t# Z1 _; [/ K, F5 y
Forcal代码1:**数组求和函数Sum,完全矢量化的代码
6 V; |( K* `* l - !using["math","sys"];) y5 ?/ {5 m1 ?1 _: s0 P
- mvar:' k# `8 n- x- V A0 l K\\" T
- t=clock(),
- 5 D2 P& h% O$ H, c
- oo{& Q _: J& J: w7 i4 ]
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],5 m\\" O8 R) u1 x7 [3 J
- Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2)))))),0]: X% N/ ~& G, I. j) x
- };0 j5 F! Y7 d8 @6 O2 j1 n
- [clock()-t]/1000;
结果:. o' D J3 l0 F# {8 N
1008606.64947441
; `; G! @3 k: }2 ^0.625 //时间! ]( A, L& ]$ \% [
6 F" G7 M; e& L或者这个,与上面效率差别不大:
* P( |) l+ B- t2 V1 m2 b% p$ m - !using["math","sys"];
- % w* w, O$ J3 ^\\" s- C9 B
- mvar:
- % N' E2 l: d+ b r* N9 B
- t=clock(),
- 9 F' y. U J0 m/ D! F
- oo{
- / `+ o& y6 `! o- H! x/ S- b1 l9 ]
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],
- : a1 q1 t1 j+ i ?/ O* y; ?* N+ W
- Sum[Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2))))))]]
- c: U0 c) P4 l
- };# U6 A0 v; y- L$ |! ?5 r$ f+ ?
- [clock()-t]/1000;
% |! G/ W8 g( C! z& {" u ~
Forcal代码2:求和函数sum,非矢量化代码5 s6 c) r, Q* i/ U& x8 N
- f(x,y)=cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))); $ K$ H9 c5 N# V
- sum["f",0,1,0.0011,1,2,0.0009];
复制代码 结果: R% S. s; d( D- H" ]8 z
1008606.649474412 t+ ]0 o6 C9 q; |' m$ b2 ], i
0.719 //时间/ H: ]+ s7 V% |) S6 v
( D/ |& w% b+ \
Forcal代码3:while循环
1 d0 g& m" n6 k/ |- mvar:1 h) @& o\" Q5 r; H
- t=sys::clock();
$ `* r* b. B- k\" K5 s' E3 J7 r) I - s=0,x=0, $ ]5 S# P8 H2 \4 `1 A' \7 D
- while{x<=1, //while循环算法; . ]1 X* P9 Q* q9 x) H2 |
- y=1,
8 j6 B o6 n; c/ J - while{y<=2, ' S3 G* e( [\" s) B- R
- s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))), / _9 ?* l6 X2 ^+ `
- y=y+0.0009 # }7 C. f\" |5 c# @& q
- }, \" g% C0 Z- o$ i; b ~6 R( t& q\" z
- x=x+0.0011 q+ f. s1 }7 N/ f
- },
* |+ }1 P! K9 l0 x& Q6 y# N$ E - s;+ w5 T6 H L% p
- [sys::clock()-t]/1000;
复制代码 结果:% C4 p9 u; i' |+ @6 i
1008606.64947441
, o0 o3 f. P3 L3 K0.734 //时间
- ^ j, s8 o; P# p. j+ y0 z) V% C1 v3 s9 A" V5 C* s# C. `: d
大家可下载OpenFC进行测试:http://www.forcal.net/xiazai/forcal9/openfc32w.rar
. P/ b8 v8 q% W9 y
* ?+ {2 `0 G" t/ w4 V0 m0 U* H注意Forcal的矢量化代码第一次运行有时效率较低。
l; A, R+ ^0 s/ E# M1 N; J0 v5 B% K2 `4 e& X; _ M$ t
例子1中Forcal和matlab都是矢量化代码,但matlab跑不过Forcal。该例子的特点是函数调用频繁,临时变量生成多,但矩阵很小,矩阵的各种函数运行时耗时较少。故说明Forcal函数调用+变量管理效率优于matlab。- C/ \1 O( B/ }& d0 J
7 V8 B% _: M3 j [2 v, [' E: Y% h
例子2中Forcal的矢量化代码是最快的,但与matlab的矢量化代码相比仍有差距。该例子的特点是函数调用少,临时变量也少,但矩阵大。故说明Forcal的各种矩阵函数Sin、Cos及矩阵的加减运算等函数的内部设计不及matlab。' A7 G, L' h1 u# e6 ^4 J( Z( c
' o" h5 k' i3 G f; {! X; R如能在函数内部设计上下点功夫,例子2超越matlab也是可能的。在这方面,期待高手们的指点。
* q3 _# N, W6 h) j0 B7 X5 d' x
h& L) y4 w: P* C2 Z如果例子2速度也超越了matlab ,matlab矢量化的神秘面纱就揭开了。0 ~6 B, l h# J' C% {
! m6 @& {" C' ]3 y. A1 H( y! Q* |! `
顺便说一下,例子1如果用C++的运算符重载来实现,速度将比Forcal慢一些,也就是说,在涉及运算符重载时,脚本的效率有时比C++还要高些。7 D* z: @9 h6 g, K- U; X* Z
|
|