- 在线时间
- 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 编辑
3 V& b0 M6 F& w
# V: m5 ]* ?+ w我正在练手设计的FcMath库也打算以矩阵运算为基础,设计一些专门的函数对数组元素集中运算,运行效率确实有所提高(甚至有些涉及矩阵的算法比matlab还快),代码也简洁了,但不知这是不是矢量化?" j: U* E" M' R y
G# P: y$ T8 R$ @2 z3 ?4 _5 p脚本运行效率应该取决于函数调度效率、对象管理效率和函数内部算法的实现。) \: D8 E. m- ]5 [; D
8 k/ j, V1 s/ `我感觉,matlab的函数调度效率较低,对象管理效率这个不好说,但一些函数内部的设计比较优秀。故有些Forcal代码比matlab快,而有些慢。
( J% Z4 D- S( d T3 i& h% Z$ t. Z7 A* g- r
以下例子体现了Forcal和matlab的效率差别所在。
" Y1 v6 m8 G& ~+ D: H! K
) a% V U- L4 @4 g4 X& e这个matlab程序段是网友lin2009 给出的,理论结果是每个元素均为275000。- clear all
7 T3 ~\" u( {; y, m - clc! G$ l2 D5 Q( c- a: ]$ }
- tic' e% H- s/ e: \0 U3 G& I' s8 L
- k = zeros(5,5); % //生成5×5全0矩阵
/ N. D F, j) j5 v. G - % 循环计算以下程序段1000 00次:: u8 j6 L/ a- D9 P: W1 g
- for m = 1:1000 004 y# g) T% B8 q: D
- a = rand(5,7);8 g0 ?# D+ h' Q1 H, p& Z8 ]: W# W
- b = rand(7,5);%//生成5×7矩阵a,7×5矩阵b,用0~1之间的随机数初始化
6 K' P: }& M' l. B* ]) N* a9 Q1 [ - k = k + a * b + a(1:5, 2:6) * b(2:6, 1:5) - a(:, 7) * b(3, :);6 P1 ~9 `' Y! Y8 Q* k
- end( u$ {: T; b* X' j7 T. P6 [
- k4 e/ }2 j: {# z! Y/ @* K9 I0 {9 W
- toc
复制代码 " f8 @3 o# t$ k d! X
Forcal代码1:运行稍快的代码,比matlab约快10%吧?
, `4 Z! u- H! q7 C - !using["math","sys"];
- # y( w, K- ~) ~+ O# O0 z% n
- mvar:
- * k$ m1 d* \# ?' @. X# K8 g
- t0=clock(),% f) L4 o\\" ^5 v( K s9 y3 s$ c
- oo{k=zeros[5,5]},
- ' F& H4 F: Y( D f- n
- i=0,((i++)<100000).while{
- - B! b& u) K9 P. l# O' T
- oo{
- * `- u6 k1 U\\" g5 ^0 m
- a=rand[5,7], b=rand[7,5],
- % P+ @0 ~) I) P! p: y% L' 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)]
- 1 r9 E5 B0 g- _1 ~+ \. f
- }
- ; ?. ^9 }, c; B& h
- },4 F d3 i& M9 \ {
- k.outm(),
- % l9 x\\" n' ?% @* `% B( w
- [clock()-t0]/1000;
在我的电脑上运行时间为3.344秒。
3 f- Q% z3 i$ g2 k" g) g: J3 M- f* ~7 ~' h: }" p
Forcal代码2:比较好看些的代码,似乎也比matlab稍快吧?5 p8 r% I: p- M, q( x* V
 - !using["math","sys"];6 c. p% ?4 c$ i. j O
- (:t0,k,i,a,b)=
- 6 q3 V0 e# e$ K$ T* _# x
- {9 r/ d. }& i% O+ k$ V: O, y! o
- t0=clock(),3 f8 H5 |\\" J1 Y# @
- oo{k=zeros[5,5]},. U! t1 z. b$ D
- i=0,((i++)<100000).while{
- \\" t\\" P' q4 z7 \3 A
- oo{\\" e* X6 i7 g! S; [5 a
- a=rand[5,7], b=rand[7,5],! `1 j+ j7 u* ^* x* N
- k.=k+a*b+a(0,4:1,5)*b(1,5:0,4)-a(neg:6)*b(3:neg)
- $ l, f\\" c5 [& j- n. N1 e
- }
- ) X. X\\" N4 `- g# T, U
- },
- + A |5 ] C* T
- k.outm(), T2 @, G5 @% F2 H. Z' P, i
- [clock()-t0]/10001 o5 c& q9 r8 Y* ]2 }6 G) c
- };
在我的电脑上运行时间为3.579秒。
/ j& r3 I1 B6 C+ A6 x7 N* E+ p
; c% b3 j" ^% c* |例子2:5 [+ l/ g: p9 f
一段程序的Forcal实现:
* ?( G2 f' q5 ?- //用C++代码描述为:
) L9 p1 z2 z; k: i# A, q& D - s=0.0; & C$ o0 t7 E) o0 C: h# x: Z
- for(x=0.0;x<=1.0;x=x+0.0011)
/ H2 s0 s9 H/ F4 T - {) u5 p/ O! u$ d/ b# M! S3 t5 O; ?
- for(y=1.0;y<=2.0;y=y+0.0009)
H; d+ l5 {9 P# M - {. |! ^* @8 d* M. K! G* q& o: f
- s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));& J; J a' C- j, K# p
- }+ A; k0 N1 X& k: L, ]
- }
复制代码 结果:" k, r. ^" U _$ q# R# f: y: y, w7 S
1008606.64947441
4 n$ c3 T% u1 o2 W0.609 //时间
6 j8 u; H/ S* [ ~7 b% n. i! d* z+ a
这个matlab程序段是网友yycs001给出的。1 P3 D/ N, x1 Q" B# W, H# h
- %file speedtest.m% I5 I& ], w+ y }, ^
- function speedtest% r# l\" k+ J6 ~/ y2 t
- format long
% b5 n! @6 a4 y) ~* i2 A - tic
, C3 E6 E6 B: `& N - [x,y]=meshgrid(0:0.0011:1,1:0.0009:2);
/ | r: s! k- l y - s=sum(sum(cos(1-sin(1.2*x.^(y/2)+cos(1-sin(1.2*y.^(x/2)))))))
' u3 F: G% R\" N) U* g1 w\" g, q - toc
复制代码 2 Q3 P- }0 g: \% h
Forcal代码1:**数组求和函数Sum,完全矢量化的代码
9 X2 m4 G) p4 g$ W4 F7 V - !using["math","sys"];, a: J1 U# P5 ]\\" W) ?* z
- mvar:& @\\" j( G- E0 m) s9 g
- t=clock(),
- , y% I2 Z+ T1 S m; L
- oo{8 r0 U# N. }! B$ B. R
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],* n1 p\\" O3 A$ R, W+ V0 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]
- ' a* B: t/ w6 x T+ N3 u! |% C! t
- };
- : F- ~9 \- O* V, P* J; D
- [clock()-t]/1000;
结果:
% A& w; I5 C* l- g# {$ U3 X/ u1008606.64947441
9 i9 y. ^ d: l2 x2 o" F0.625 //时间& _2 I7 ^! c. |1 k# u# t
- B9 n: d! I- w+ N
或者这个,与上面效率差别不大:3 r0 p/ l/ M0 V! e$ r1 `5 a
 - !using["math","sys"];' ]. Q) W& k' w/ w
- mvar:
- ' U5 z7 s: z: w5 y1 o& d
- t=clock(),
- ; H7 \# V7 }, C8 ?1 i
- oo{
- ! j; ^) {/ \( `/ z* }1 R; i
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],
- & V1 }, M+ k+ Z- w' H1 k5 b# k
- Sum[Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2))))))]]; Q# `; C7 |7 u5 S) D# m
- };
- ]2 S2 W) h8 h) l
- [clock()-t]/1000;
: v' C6 b: Y2 P* JForcal代码2:求和函数sum,非矢量化代码0 _7 z3 ]2 @. q
- f(x,y)=cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))); 1 s) }' [. x! G/ j0 {9 p
- sum["f",0,1,0.0011,1,2,0.0009];
复制代码 结果:; z: V2 D/ M" \4 Y* s) _
1008606.64947441
. W3 a7 H. n- s5 |- X$ @0.719 //时间& \, {. ~4 R) Q1 ?* W) r
1 I- |$ E; s1 |Forcal代码3:while循环
* }% ^" Q$ {2 Y' |* m$ z2 P8 V. l- mvar:
2 U* i8 o' T, \8 o - t=sys::clock();
# v6 z+ x+ H* w# i2 d! M - s=0,x=0, 0 E. z, F\" S7 u( E4 w1 X2 U; m8 l+ T$ n
- while{x<=1, //while循环算法; - z/ J% {0 T) {' V0 |
- y=1,
' ]# k+ o* s6 o - while{y<=2, \" U2 K* t7 R( ^' K$ ~: t4 C
- s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))), , c6 u' U. D# H5 v/ g* j' e
- y=y+0.0009 4 I, `9 ~, z2 \: f
- },
2 ?, q( S7 E% {2 g - x=x+0.0011 8 _8 f1 f8 S& m& U7 E* V+ G\" R. y
- },
) G; w5 Q7 u: B+ |: B2 G! g: j - s;
3 w6 a$ A4 C+ o4 D8 Y - [sys::clock()-t]/1000;
复制代码 结果:
" c& ~6 o# H2 c8 ~- l2 M. r' i- A1008606.64947441" K# |; a e+ p+ w
0.734 //时间
; N' q6 e) g" E7 _+ E' }. X- }! J0 h( Z+ J
大家可下载OpenFC进行测试:http://www.forcal.net/xiazai/forcal9/openfc32w.rar
% e% z5 ]1 F. W
1 H' } w/ c' E* ^ B2 z( H注意Forcal的矢量化代码第一次运行有时效率较低。
( U) i0 U! C1 c% `0 L' v& P& a# h3 z9 `
例子1中Forcal和matlab都是矢量化代码,但matlab跑不过Forcal。该例子的特点是函数调用频繁,临时变量生成多,但矩阵很小,矩阵的各种函数运行时耗时较少。故说明Forcal函数调用+变量管理效率优于matlab。7 G! F/ r5 U7 E/ C7 y* I$ B9 a5 D
, ?$ S0 j$ d, [$ h4 t5 Q
例子2中Forcal的矢量化代码是最快的,但与matlab的矢量化代码相比仍有差距。该例子的特点是函数调用少,临时变量也少,但矩阵大。故说明Forcal的各种矩阵函数Sin、Cos及矩阵的加减运算等函数的内部设计不及matlab。
0 ~8 N7 G: s( q% ^* |
8 l- C6 X+ B- q, ~1 ?( l6 Y如能在函数内部设计上下点功夫,例子2超越matlab也是可能的。在这方面,期待高手们的指点。
# b7 O; Q, S7 t2 J0 ?6 T3 ]
7 G' e& v6 I+ B# e7 J5 c如果例子2速度也超越了matlab ,matlab矢量化的神秘面纱就揭开了。
6 } ]5 j. I8 F' R
4 a+ g* @' j# k; j5 \顺便说一下,例子1如果用C++的运算符重载来实现,速度将比Forcal慢一些,也就是说,在涉及运算符重载时,脚本的效率有时比C++还要高些。
" a* N3 ]; L7 n |
|