- 在线时间
- 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 编辑 + `- ^8 s' r! q- i2 z4 X' n( `
* b6 |% D9 `3 @9 A4 c
我正在练手设计的FcMath库也打算以矩阵运算为基础,设计一些专门的函数对数组元素集中运算,运行效率确实有所提高(甚至有些涉及矩阵的算法比matlab还快),代码也简洁了,但不知这是不是矢量化?
* a& H# m- k( m4 ?! E9 g, L3 _' x. Z4 R* Q* J
脚本运行效率应该取决于函数调度效率、对象管理效率和函数内部算法的实现。
( b4 I8 } P% |( m% B7 \
& {: i0 H1 k( L3 E5 C; r我感觉,matlab的函数调度效率较低,对象管理效率这个不好说,但一些函数内部的设计比较优秀。故有些Forcal代码比matlab快,而有些慢。
7 Y- T3 S! g* j/ t
" W5 y5 ]6 G% s以下例子体现了Forcal和matlab的效率差别所在。
H* n( A* Q/ Y2 `3 k
% I. y8 p( P) }- B! c这个matlab程序段是网友lin2009 给出的,理论结果是每个元素均为275000。- clear all
$ T5 M5 D/ o0 d0 P8 I - clc; K2 W& L( L, v4 W; K
- tic
# U, Q j\" O1 t5 o$ |& |; Z - k = zeros(5,5); % //生成5×5全0矩阵2 d+ ]( b% s3 |( s# ?5 _/ ]
- % 循环计算以下程序段1000 00次:
, s0 v( J1 l- G m4 z$ E3 @5 _& P - for m = 1:1000 00
& ^2 ]3 Q; G' ~* G# Z4 Z - a = rand(5,7);$ y2 V) p) v! Y) F9 t
- b = rand(7,5);%//生成5×7矩阵a,7×5矩阵b,用0~1之间的随机数初始化+ U& D$ W- z+ ]2 D
- k = k + a * b + a(1:5, 2:6) * b(2:6, 1:5) - a(:, 7) * b(3, :);
! I3 D- f) y/ \' H - end# v# V\" ]/ J! ?% }* x: A6 s# R6 ^) ?
- k
9 R2 V6 Q, y2 X7 t - toc
复制代码 / H: |# S1 y2 u d) L/ E
Forcal代码1:运行稍快的代码,比matlab约快10%吧?$ ^; Q: q$ {1 x4 y: C$ k, o. U3 N9 w
 - !using["math","sys"];' ]% c% v- e: K3 M
- mvar:
- - J* I5 `/ V: h% B8 P
- t0=clock(),! }2 ^7 b4 F% t+ P/ x9 P6 {
- oo{k=zeros[5,5]},
- ) T: v7 q [ ?& q% M\\" p0 a
- i=0,((i++)<100000).while{2 q0 A- y# f/ V: N0 u2 K
- oo{
- \\" y! R. ~5 I8 @1 S1 X
- a=rand[5,7], b=rand[7,5],: l$ d' z1 ?- f9 \7 k3 P; 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)]; p3 k/ a& b. b7 b5 B- ?* e( v2 j
- }7 N( s- t) x+ o! Y/ o# P( O0 X' s
- },
- 5 T, W3 o* m# {+ _$ G6 s0 m) }
- k.outm(),
- : K8 B: C4 q3 R* o& I
- [clock()-t0]/1000;
在我的电脑上运行时间为3.344秒。. }# ~3 c3 _0 b+ j9 z4 I. S% T
" z/ @) Y5 k( s8 Z
Forcal代码2:比较好看些的代码,似乎也比matlab稍快吧?
6 D( G2 i# `4 c+ S/ g% T - !using["math","sys"];
- 9 P6 L% H; \( u% O8 J: W8 v
- (:t0,k,i,a,b)=, l, z& I6 D2 [$ \8 B4 }# U
- {
- ( H& ~4 d, Y( R' S
- t0=clock(),2 j5 L6 p6 [. s' b- X. E
- oo{k=zeros[5,5]},
- - x* j1 S% `' ^9 H/ j8 M. n
- i=0,((i++)<100000).while{
- 0 f4 F3 y) z9 W# m4 J
- oo{7 `* _* {2 e+ \; a0 I
- a=rand[5,7], b=rand[7,5],, y: |1 b, N! F$ y
- k.=k+a*b+a(0,4:1,5)*b(1,5:0,4)-a(neg:6)*b(3:neg)
- K. K5 c: @& B, M& X. V0 q3 s
- }! _ Z0 z' j; E+ D; g
- },; e9 h) S/ x0 O& {) x1 y) I
- k.outm(),0 h, M& o/ ~- \: r# O0 J
- [clock()-t0]/1000# R( T0 W3 v3 C$ Z
- };
在我的电脑上运行时间为3.579秒。6 x i+ e+ @0 U3 X. Y( w" m
4 J8 R4 I7 ]! X" C k例子2:% N2 K$ k3 p# J6 x8 r
一段程序的Forcal实现:
+ t) l: h# x7 ?" w) X- //用C++代码描述为:9 W/ e. w2 _; s1 e5 A0 B% ^, v
- s=0.0;
9 b7 z \# B3 d+ K - for(x=0.0;x<=1.0;x=x+0.0011)
6 q) H. p' E1 f% L\" t) L - {8 ?4 W. k5 {) @: J9 V6 Z$ @\" ?( b# i
- for(y=1.0;y<=2.0;y=y+0.0009). E2 v* h& @$ y L- G& A2 _. r
- {
5 i\" }' W8 o$ M9 w# l - s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));8 q, w( D& ^: _0 c9 {6 }
- }
% Q: V& `5 o( y6 e7 w1 h2 ^8 M) Y; K - }
复制代码 结果:
! k7 ~) }% C6 B+ X! X8 `5 c* _% \% B1008606.64947441
) N5 v. T! b0 e2 d3 b0.609 //时间
; v. d2 W0 g* n6 |% M4 E9 C$ t7 P9 p
这个matlab程序段是网友yycs001给出的。
J) l/ {" e7 C4 [, u( N- h( {( q- %file speedtest.m) I8 z' A\" Z\" k3 i4 y# c\" y3 p
- function speedtest
[9 j! @+ @( A - format long
3 `8 u* v4 S: x' ]) M5 L, r - tic
$ J+ L6 M6 n0 d. X2 C - [x,y]=meshgrid(0:0.0011:1,1:0.0009:2);1 G& s( R( j2 }3 [) [$ w
- s=sum(sum(cos(1-sin(1.2*x.^(y/2)+cos(1-sin(1.2*y.^(x/2)))))))& c. D6 T( k0 `
- toc
复制代码
6 Q) v9 x9 b* U7 E- ^Forcal代码1:**数组求和函数Sum,完全矢量化的代码
. s- D; X& i" N+ _- X" S; l - !using["math","sys"];5 C1 K3 W; ^+ g; o9 i) W
- mvar:: |1 l3 `$ V' u7 a0 w
- t=clock(),
- ! L8 [& e V\\" ]# g* a* \. e. ~
- oo{
- % q) r+ j7 s3 d# y
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],
- ( u0 o6 Q# v) |2 d6 K
- Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2)))))),0]
- / A1 G+ ^& y) v4 ?1 e
- };1 n# q+ T4 l% a, M2 E0 @
- [clock()-t]/1000;
结果:
6 h$ j7 Y% ]$ l" P, m1008606.64947441$ o5 {% M/ c8 }5 g4 i/ z
0.625 //时间# O. {& X; o4 O1 u
$ k4 e: y( v. j {
或者这个,与上面效率差别不大:
- {/ `6 ]& ]8 H+ \6 z% f$ o/ s- ] - !using["math","sys"];
- 0 a: b9 X0 ?0 [3 V, T\\" @$ {- C
- mvar:
- K/ ]8 e: a% K1 [1 {
- t=clock(),* i4 D% _3 w: y/ a
- oo{
- 8 b; i+ G g! {/ R7 z1 E; x8 D
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],) C4 k\\" @3 _/ x( N
- Sum[Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2))))))]]& N6 V5 q, M- t$ f1 d. o
- };
- 5 u- [$ X' q4 c4 J* l, F7 w. K
- [clock()-t]/1000;
- G5 v& |( ~0 @Forcal代码2:求和函数sum,非矢量化代码) O! X0 {, a' N4 R
- f(x,y)=cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))); , G; F& B/ A7 W
- sum["f",0,1,0.0011,1,2,0.0009];
复制代码 结果:) ?$ O$ e# O! e1 T9 p4 C$ H
1008606.64947441
. G" }1 G8 B; k: ?0.719 //时间
* x5 y; u: O; B
6 w2 M0 c! n o; X' C bForcal代码3:while循环" L& l2 x; W9 d* U5 @0 K7 W
- mvar:' x# _5 V; _\" ]5 h2 |% k
- t=sys::clock();+ ]% o Q: M6 q/ j7 A5 v
- s=0,x=0,
$ s0 ?5 \# I\" [5 K- Q9 h* c8 z: ` - while{x<=1, //while循环算法; p9 D+ M# o8 g1 Q
- y=1,
' ]! p* y9 C, F) L- Z( A! t - while{y<=2, 5 S. J! [7 v3 c
- s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))), : O) J5 C0 t1 U6 e
- y=y+0.0009
* X\" k% p8 k8 m% g5 z$ M - }, ) ?8 O$ Q% q- E
- x=x+0.0011 6 n/ _/ E7 c) L& h* U3 P$ g/ K
- },
* o\" T8 g7 ~, L- Z* n' B& y4 ? - s;2 ^/ u+ I ~% e+ Y$ C
- [sys::clock()-t]/1000;
复制代码 结果:* d' l& k8 L. \
1008606.649474418 K. S7 X0 s& ?* B; s4 v9 _
0.734 //时间4 _/ E L1 u0 F8 D) ^: M- \
- u, i0 G! l. d: f
大家可下载OpenFC进行测试:http://www.forcal.net/xiazai/forcal9/openfc32w.rar
' ]4 ?7 g5 I9 \+ G
! I; H* u0 L& V注意Forcal的矢量化代码第一次运行有时效率较低。# n$ S, C2 I( E' a b% y" m
* {6 [8 r# L; B0 C* G) B例子1中Forcal和matlab都是矢量化代码,但matlab跑不过Forcal。该例子的特点是函数调用频繁,临时变量生成多,但矩阵很小,矩阵的各种函数运行时耗时较少。故说明Forcal函数调用+变量管理效率优于matlab。
) Z7 H* c$ ^1 {8 W' P4 n, d0 B l- }- x
例子2中Forcal的矢量化代码是最快的,但与matlab的矢量化代码相比仍有差距。该例子的特点是函数调用少,临时变量也少,但矩阵大。故说明Forcal的各种矩阵函数Sin、Cos及矩阵的加减运算等函数的内部设计不及matlab。
% D/ W+ C" P& j, ?+ z
/ g) d( e2 }! `5 P% ]; i- I. m如能在函数内部设计上下点功夫,例子2超越matlab也是可能的。在这方面,期待高手们的指点。
3 A7 }# P. e7 g" I" } E
9 X4 G; ]! s) z1 s9 S如果例子2速度也超越了matlab ,matlab矢量化的神秘面纱就揭开了。
$ B5 U. F! o2 q! J; a7 i' W# g' i6 c- S2 V v$ V4 ^
顺便说一下,例子1如果用C++的运算符重载来实现,速度将比Forcal慢一些,也就是说,在涉及运算符重载时,脚本的效率有时比C++还要高些。
% O" D, }2 b V& p* {0 ?+ o' C |
|