- 在线时间
- 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 编辑
/ U2 i1 ^" Z# i/ j" [
% x8 {# k3 D" e+ ~! K我正在练手设计的FcMath库也打算以矩阵运算为基础,设计一些专门的函数对数组元素集中运算,运行效率确实有所提高(甚至有些涉及矩阵的算法比matlab还快),代码也简洁了,但不知这是不是矢量化?" y+ F' | ~& k/ E+ {! N
& x, k/ O# s" M5 a& T; Q
脚本运行效率应该取决于函数调度效率、对象管理效率和函数内部算法的实现。 `$ P& _, C- B" [2 q# ?
5 W& R9 N( |1 G( A0 w我感觉,matlab的函数调度效率较低,对象管理效率这个不好说,但一些函数内部的设计比较优秀。故有些Forcal代码比matlab快,而有些慢。
/ u6 i3 d. c+ r6 Y+ u3 } E" `) C: Z
以下例子体现了Forcal和matlab的效率差别所在。$ S9 k) ?3 b$ g: K; M
) i# }) j3 d% `' `7 f
这个matlab程序段是网友lin2009 给出的,理论结果是每个元素均为275000。- clear all1 v! F- P `) n+ r( }' Z
- clc
y/ O9 t: K$ [5 d! q3 v1 w* d - tic/ N) [5 E8 H7 B* q, C
- k = zeros(5,5); % //生成5×5全0矩阵* C: O* A9 x\" u8 |* d
- % 循环计算以下程序段1000 00次:
8 T9 P7 V( Z6 D7 v - for m = 1:1000 002 H5 ^) f: Q# J9 r3 r( }; w
- a = rand(5,7);
+ ]/ y; {1 J! M' v; @ - b = rand(7,5);%//生成5×7矩阵a,7×5矩阵b,用0~1之间的随机数初始化
. t$ p' w0 H5 Z0 k - k = k + a * b + a(1:5, 2:6) * b(2:6, 1:5) - a(:, 7) * b(3, :);8 _$ ^) o6 l- g\" p
- end
7 Y$ I( e2 _* r; E, ]# N - k
q' i2 f% p! O3 c. g' [ - toc
复制代码 ! i7 S! U. b+ R7 z5 q/ {1 L8 n3 s
Forcal代码1:运行稍快的代码,比matlab约快10%吧?- m4 d* `; ^1 ^& _ f# v8 e
 - !using["math","sys"];/ A0 _ W i1 @2 l9 A0 t# T
- mvar:\\" Z: ^9 D. }/ p\\" Y: {
- t0=clock(), A& x/ t. B3 {: E\\" u! A! A
- oo{k=zeros[5,5]},
- 0 S1 {7 B$ W% u
- i=0,((i++)<100000).while{
- 3 [3 _: d# f U/ t8 V5 d5 ]
- oo{
- 0 U9 V5 `5 g( s6 E! F, o4 x
- a=rand[5,7], b=rand[7,5],% N8 P\\" W( F* ?! D
- 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' e5 q1 x# k$ h: L, L
- }
- ; l/ @& H P8 }$ |' ~, O* T
- },
- 8 x% x4 F8 Y7 H- J9 B: O8 ^
- k.outm(),
- # Y& L& }+ B) H' M* ?! N4 X8 C
- [clock()-t0]/1000;
在我的电脑上运行时间为3.344秒。
6 l) |2 G( B$ d2 W L# P" p5 P# A- m
Forcal代码2:比较好看些的代码,似乎也比matlab稍快吧?. V' m2 W2 w( q8 Z5 ]$ r. \7 w
 - !using["math","sys"];
- - I- _\\" t( ]( n\\" v
- (:t0,k,i,a,b)=
- 6 ?9 J; j+ ]! Y+ z0 _, w
- {$ [2 z( B* k& R3 _
- t0=clock(),6 M\\" i! r& d7 O\\" k, M) {
- oo{k=zeros[5,5]},
- 2 E4 u7 T+ I x% @
- i=0,((i++)<100000).while{ p0 t/ h& N+ X$ G
- oo{
- ( ~! X8 P; y8 a2 ]8 J- }
- a=rand[5,7], b=rand[7,5],
- 8 O\\" _% C8 p. a* z- k
- k.=k+a*b+a(0,4:1,5)*b(1,5:0,4)-a(neg:6)*b(3:neg)
- 8 d% f; y\\" k& T9 A/ b% Q
- }; B3 N8 n5 j- e, q4 v6 D+ T
- },3 |+ Z& ^5 f8 B* v
- k.outm(),
- - @$ U% A; c: h& P
- [clock()-t0]/1000
- / C9 V: ?5 U/ G
- };
在我的电脑上运行时间为3.579秒。
$ h7 a* W. u f3 `
! ^ } Z/ e: m% p9 S$ S8 r例子2:
6 O2 ]& O9 e& ~一段程序的Forcal实现:
: g2 d+ ?/ V, ^: ^- //用C++代码描述为:6 v0 G9 }- m* G$ j
- s=0.0;
8 E$ T1 b2 o9 |: a0 u - for(x=0.0;x<=1.0;x=x+0.0011)
- k\" u. B: E* L - {9 o! m+ A( w: a
- for(y=1.0;y<=2.0;y=y+0.0009)
/ I+ n) U: z' _3 a: L: t F - {' n' T0 v, X$ s\" N& U
- s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));
, o9 l/ J# n2 J; @2 i$ T\" ^ - }& `, J9 U; U2 d0 K. D% N
- }
复制代码 结果:
& k9 b4 C; m+ e4 R8 q$ X1008606.64947441; h# C5 F/ C5 _0 Y2 |9 w6 [
0.609 //时间
. i0 z& c ]0 F% z2 Y6 ]8 Y, F- k/ f1 o
这个matlab程序段是网友yycs001给出的。
' v" j' F- |1 A' G- %file speedtest.m
8 F L$ r5 j9 L [; @% p) c - function speedtest, K0 @\" X) `1 g0 s4 _8 l# N\" \
- format long/ |3 M4 O% H' y# W8 w8 T+ H4 }
- tic2 u4 v' J! I6 Z: y ?4 w
- [x,y]=meshgrid(0:0.0011:1,1:0.0009:2);3 I! k9 ?/ {, | w+ q% m& l
- s=sum(sum(cos(1-sin(1.2*x.^(y/2)+cos(1-sin(1.2*y.^(x/2)))))))6 B) h8 I- E1 H$ p# o/ s
- toc
复制代码
3 Z8 s8 N4 A9 ^2 q9 wForcal代码1:**数组求和函数Sum,完全矢量化的代码
$ X1 }. b% q, `! g. G; _- _ - !using["math","sys"];
- 0 ~& n7 u$ ` h) V
- mvar:6 K7 w p N( n f& J$ f
- t=clock(),8 I; H1 Y: u, E4 l
- oo{
- ( x& k% p7 d# |+ d$ n3 _
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],
- 2 w0 I) J$ _. U+ R+ q
- Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2)))))),0]
- 7 [0 w0 |\\" {; @: z) H\\" w
- };
- L1 R5 N6 N* y I X2 C
- [clock()-t]/1000;
结果:
& J O+ h4 [) e1008606.64947441
+ t. H6 G5 f! e4 s0.625 //时间
/ y* V& d1 m4 ^
% Q9 h1 a4 |& _* i; @3 P7 w$ a% \# i或者这个,与上面效率差别不大:
8 a9 E5 _' X( p- A8 {$ { x - !using["math","sys"];& X) l* N8 ~% k0 e
- mvar:7 V/ o% ?7 n9 l# L E: R! X8 n6 |
- t=clock(),+ ]( n# [0 d5 t2 v# c5 [3 f+ S
- oo{\\" E: a' n# L5 a& F/ z. ~$ G
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],2 n! v- E2 |% s' @\\" C3 U; c
- Sum[Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2))))))]]. ?1 G* J$ W, `
- };# j. c7 z' d8 t' d: f1 i4 s9 B. Q7 H! ^
- [clock()-t]/1000;
8 q" x$ ?+ x8 ]/ ?5 W6 @
Forcal代码2:求和函数sum,非矢量化代码
% M; N2 D' E! g- f(x,y)=cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));
8 m. c, N9 ^- C; h' X8 V$ c - sum["f",0,1,0.0011,1,2,0.0009];
复制代码 结果:; m* E* {3 v1 y1 V6 }+ f. H3 p
1008606.64947441
' l; Z# m" D0 _4 E+ U; [0.719 //时间$ E7 \! c1 k/ m9 r: U
! z0 `+ H1 I& L* L& k7 b; BForcal代码3:while循环8 K- _ P) Q0 V1 O d* m8 @( `$ q
- mvar: z+ w* P- ~; u/ q. G3 Y* M
- t=sys::clock();
( n* w/ ` I/ p! b\" y - s=0,x=0, 4 L8 f) {8 ^. b\" D/ j- Z, o& q
- while{x<=1, //while循环算法;
4 {$ v9 e! P+ r( S: a - y=1,
* a2 H! g, R) ]& D - while{y<=2, 1 l; d; D- L0 h
- s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))),
: u: D9 I! h; D1 ]0 Z! S - y=y+0.0009
0 Q; I7 L; l0 ]% O+ b9 ^) Y4 H, U7 u - }, ! c) P6 H1 {, ]/ L2 Q1 M9 z7 @; e
- x=x+0.0011 # b. c4 i8 B5 t4 W* `6 }1 ~ R
- },
4 _3 F: e+ \. d+ J0 r- g - s;
. g0 i( T, R7 M8 G! e# o; O$ h - [sys::clock()-t]/1000;
复制代码 结果:+ E# z7 k6 G. u$ i3 Y; E5 n
1008606.64947441: F6 g* E$ [. F
0.734 //时间: j! F3 ~+ v- {1 U8 W6 j6 T
1 J( b: h( Q! Z) a* I2 F大家可下载OpenFC进行测试:http://www.forcal.net/xiazai/forcal9/openfc32w.rar4 G; r0 e f- W
+ R3 { x9 {3 t$ j& \& b+ G" M注意Forcal的矢量化代码第一次运行有时效率较低。$ e) J( Q- `1 d
. J6 e s) q; N
例子1中Forcal和matlab都是矢量化代码,但matlab跑不过Forcal。该例子的特点是函数调用频繁,临时变量生成多,但矩阵很小,矩阵的各种函数运行时耗时较少。故说明Forcal函数调用+变量管理效率优于matlab。6 p. i, I2 v( c% h+ i5 u
& k) M8 H4 k9 z) i6 t" p' O例子2中Forcal的矢量化代码是最快的,但与matlab的矢量化代码相比仍有差距。该例子的特点是函数调用少,临时变量也少,但矩阵大。故说明Forcal的各种矩阵函数Sin、Cos及矩阵的加减运算等函数的内部设计不及matlab。0 q- U3 X0 K" {) j8 `+ g! q
" H1 f$ f* D0 g+ e L
如能在函数内部设计上下点功夫,例子2超越matlab也是可能的。在这方面,期待高手们的指点。
2 I3 ]4 ?$ L z! W; l+ K
% \, M+ d5 S" @如果例子2速度也超越了matlab ,matlab矢量化的神秘面纱就揭开了。4 N) L7 _/ B# U$ F: C8 o
7 K7 D- E5 m5 M; N' k0 j
顺便说一下,例子1如果用C++的运算符重载来实现,速度将比Forcal慢一些,也就是说,在涉及运算符重载时,脚本的效率有时比C++还要高些。0 f; C9 v% b2 u- v' h( j
|
|