- 在线时间
- 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 编辑
* o. W r$ _# i& |0 {: M5 o, D4 h: H$ Z
我正在练手设计的FcMath库也打算以矩阵运算为基础,设计一些专门的函数对数组元素集中运算,运行效率确实有所提高(甚至有些涉及矩阵的算法比matlab还快),代码也简洁了,但不知这是不是矢量化?
# ~/ s- ~6 c9 i( j& W) H A' y( M; |' U2 n" O6 x6 W
脚本运行效率应该取决于函数调度效率、对象管理效率和函数内部算法的实现。% G& _; ? r) U
4 I, ]5 R" V, P; B我感觉,matlab的函数调度效率较低,对象管理效率这个不好说,但一些函数内部的设计比较优秀。故有些Forcal代码比matlab快,而有些慢。2 t( j# r4 c# n( T* U
6 V( ^* O5 a# R0 z2 |9 d9 N8 r
以下例子体现了Forcal和matlab的效率差别所在。& e, \7 s0 P: N. F1 z; d! a+ i
, U: F3 g0 e- b% V
这个matlab程序段是网友lin2009 给出的,理论结果是每个元素均为275000。- clear all
$ _, X r! f# ?0 z. v4 F - clc) `7 ^& i3 V; A* t& z$ e4 @& n
- tic
: M9 `. A7 @8 R# X! [( H+ O/ a - k = zeros(5,5); % //生成5×5全0矩阵
$ c, X; p) |1 {6 j5 _- J) v - % 循环计算以下程序段1000 00次:
\" p( y- A& O( ~\" d, v\" ~- ?- t% z5 g' _ - for m = 1:1000 00. u# K! w8 p9 ]/ C, E& S7 H
- a = rand(5,7);
. k- K8 X' ?! v. D. E\" u - b = rand(7,5);%//生成5×7矩阵a,7×5矩阵b,用0~1之间的随机数初始化
3 @' | K4 d6 c! A6 O! k - k = k + a * b + a(1:5, 2:6) * b(2:6, 1:5) - a(:, 7) * b(3, :);
! x8 `5 q$ `: v/ V1 X! L5 B$ H/ U - end
* d+ G, g/ K) \: }5 h' | - k( h8 M) g Y, F/ g$ X M. Q
- toc
复制代码
- ], V! s5 T: Y: u! EForcal代码1:运行稍快的代码,比matlab约快10%吧?
# q" D- G0 i) |6 y O - !using["math","sys"];) O+ l, Z- S2 P$ ~
- mvar:5 A# U9 Q; v1 \) F1 V) {
- t0=clock(),- d& L, [1 H3 L+ p
- oo{k=zeros[5,5]},
- 7 [* L- Q% ~; U7 V\\" z# F/ C7 X
- i=0,((i++)<100000).while{\\" a' C8 ?- R6 Q& ^5 J7 Q$ d
- oo{
- ) R4 r+ u% S2 b% y& ^* l
- a=rand[5,7], b=rand[7,5],
- 7 |7 m, ^. Z! D* @: P+ 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)]4 m) E/ j# o! _8 Y5 Z- q% X3 O- j
- }8 |: w& x% ~. Y* n2 |: @0 h+ q
- },
- ' C/ O: ?6 E) K. S- t4 z1 I
- k.outm(),
- ( s% L3 e. r I6 T+ V5 X
- [clock()-t0]/1000;
在我的电脑上运行时间为3.344秒。! \" b. P. b" Z2 ]4 Z6 X& x4 t
# D3 W' g. W3 d5 ?+ k8 P
Forcal代码2:比较好看些的代码,似乎也比matlab稍快吧?
) b6 C# s1 {. v) ~4 y2 r - !using["math","sys"];+ L8 { G' f/ a6 w p
- (:t0,k,i,a,b)=
- 4 Q$ q& I* _, ~% Z! s* N( p; j
- {# ?6 E3 v\\" i' b5 l& D7 P% M( w
- t0=clock(),3 I9 B& o4 ~- _& J& x ~2 w, U
- oo{k=zeros[5,5]},
- . J* u5 N\\" @$ j7 m3 n
- i=0,((i++)<100000).while{
- 7 b. ^* R# _; V3 Y3 e r0 h, d
- oo{6 }* E0 J- I# t; Z
- a=rand[5,7], b=rand[7,5],
- 3 C+ p& \4 c6 _ [3 {
- k.=k+a*b+a(0,4:1,5)*b(1,5:0,4)-a(neg:6)*b(3:neg)' a' |; Z6 j7 k) t( ^! D& E% u
- }6 M* }6 ]# {+ P L/ p/ w
- },! _; F/ s* Q3 g% N$ T; w# [$ k
- k.outm(),
- 6 G+ X/ d% @8 }
- [clock()-t0]/1000; E; e$ |! ]2 n7 p/ Y( `8 H6 {( P Y
- };
在我的电脑上运行时间为3.579秒。8 B0 I/ K, z% M: \& R
" v8 q5 z/ r+ c; u+ h# a1 T- P例子2:% h3 [' D. `0 r# A
一段程序的Forcal实现:
* t% i1 t( }: v6 B, ~( c& z( B- //用C++代码描述为:
5 s% q& j. Z, i1 H\" ^/ O3 W- _5 s - s=0.0;
+ Z9 a( @% T* m7 s; u+ P/ m - for(x=0.0;x<=1.0;x=x+0.0011)
9 Y0 Z5 q2 t1 o, S+ d - {) S, j' S) n, p0 U6 @* t
- for(y=1.0;y<=2.0;y=y+0.0009)9 p5 A2 a3 f. ]7 R: J
- {% b( N# O( I2 R
- s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));( C1 t/ J3 p: S- b5 C- c
- }2 q( G9 X0 @/ [% d& z
- }
复制代码 结果:
9 N, q* l6 K# l/ ^1008606.64947441
# c# m9 c: o1 O7 }" X+ U$ M! R0.609 //时间
% Q S' X5 v' C4 t6 R) p1 ^! D# C* P4 x
这个matlab程序段是网友yycs001给出的。
) P" W' q% A5 ?, S- %file speedtest.m8 O! r% A& ]6 |6 W3 |9 k ]
- function speedtest/ D7 O1 W% m2 L3 ~\" j' e e3 ]
- format long
; D7 a7 D3 u, T( A7 ~: V- W) Q1 h# V4 \ - tic
0 o, R6 N5 J/ F - [x,y]=meshgrid(0:0.0011:1,1:0.0009:2);0 S+ I1 Y6 z+ R\" c8 v
- s=sum(sum(cos(1-sin(1.2*x.^(y/2)+cos(1-sin(1.2*y.^(x/2)))))))
\" O0 f- { z0 x - toc
复制代码 ! S m- j4 Y& l" ^9 W
Forcal代码1:**数组求和函数Sum,完全矢量化的代码6 @7 l" L' i9 q) j3 n, }% o) `- j( X+ p
 - !using["math","sys"];
- ! J* b$ g! Z. U9 D& B5 N. H/ ]' I
- mvar:$ S, h. T& p- P* R\\" o' A4 ]3 f& d8 a
- t=clock(),
- \\" Q. }% U/ O# j: D
- oo{/ h- t9 N\\" T& C
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],. c% E+ U, g% ~2 Y# T. B
- Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2)))))),0]
- / Y\\" G; f2 N; _2 y/ v
- };
- Q& p8 C; u\\" {9 _0 ^; j$ t7 ^
- [clock()-t]/1000;
结果: e! k# b: q8 {# z- x" B
1008606.64947441" [: r% z; Z7 g( E4 r/ A
0.625 //时间
, E4 t5 P9 O g1 h: p# R' Z5 i
% h# p% b! k. h3 b或者这个,与上面效率差别不大:
4 i& A: s" F7 I" v$ K% {& U - !using["math","sys"];4 w1 Y9 X, n/ _/ _/ j$ F m+ @& y! ^
- mvar:/ A. y/ u5 d; C- Q( I
- t=clock(),
- 2 r+ a4 m0 f0 h! W* I: T
- oo{
- 4 F2 J- \: g; V. u' g7 f
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],4 Z! }- j8 f$ K0 W; D% 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))))))]]
- # e, _$ z4 j% `8 v$ X2 H/ ^
- };( E( B# l3 Q- ~9 _
- [clock()-t]/1000;
' B0 \7 s# u. ?4 RForcal代码2:求和函数sum,非矢量化代码
! l8 [3 P- o, H0 d' A/ p" q- f(x,y)=cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))); ( T: h( W9 F4 ~3 a& A
- sum["f",0,1,0.0011,1,2,0.0009];
复制代码 结果:
' j! ?, n2 ^! P6 \( a1008606.649474419 N! T- a/ v% z7 M0 g8 E
0.719 //时间
8 h0 D1 R& H/ E) @. L' s
+ T' t5 q- ]- QForcal代码3:while循环
* X- d' N1 D/ n3 s d- mvar:
& w/ P [: b$ ]$ m5 q5 ~7 k% q% J - t=sys::clock();
: ?$ \0 x' D6 k$ d* ?# y - s=0,x=0,
\" j' D, J2 j, Y- n6 U0 h- z - while{x<=1, //while循环算法; / _\" ^3 A0 v7 y/ k8 P# W
- y=1, I: Y) H3 R4 F; P$ L* M4 C
- while{y<=2,
4 [6 I' o0 s\" S\" J* u - s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))),
3 L- f) \6 k) F, _# m - y=y+0.0009 5 C* G0 P6 ?( T+ b
- },
' H J8 V: V4 _1 t. F- | ] - x=x+0.0011
9 I& v i6 V+ M3 \$ C - }, 5 t6 u! B, d# Z- [3 `% I3 H
- s;: F! y. g+ Z4 B! |; |0 a
- [sys::clock()-t]/1000;
复制代码 结果:
! K/ v! S8 u, p( R) y" A1008606.64947441
3 u8 J8 @. N/ h8 @# p0.734 //时间9 T+ j2 _9 K- s
$ c z& K1 C4 @/ @$ j大家可下载OpenFC进行测试:http://www.forcal.net/xiazai/forcal9/openfc32w.rar
: Q2 {& d- _/ n9 M# U7 `0 o, X; \" C0 c3 Z
注意Forcal的矢量化代码第一次运行有时效率较低。
: ]- s( u( l, D3 U$ C/ D
. @* I- V9 S% A: C, E例子1中Forcal和matlab都是矢量化代码,但matlab跑不过Forcal。该例子的特点是函数调用频繁,临时变量生成多,但矩阵很小,矩阵的各种函数运行时耗时较少。故说明Forcal函数调用+变量管理效率优于matlab。 p \0 A B, o1 w
- {9 @( [* O2 p4 D3 L; l) Q例子2中Forcal的矢量化代码是最快的,但与matlab的矢量化代码相比仍有差距。该例子的特点是函数调用少,临时变量也少,但矩阵大。故说明Forcal的各种矩阵函数Sin、Cos及矩阵的加减运算等函数的内部设计不及matlab。
( e" }7 x: J% U* X2 b' k# N8 U9 a1 s- q7 k% z- u- r) |- k' p/ M
如能在函数内部设计上下点功夫,例子2超越matlab也是可能的。在这方面,期待高手们的指点。. ? \4 Q3 ^( S2 }: s6 v( M
0 X' S& G$ q- G如果例子2速度也超越了matlab ,matlab矢量化的神秘面纱就揭开了。
% G* V0 X$ }* F" c8 u0 \
, R* n/ ~. i" K& C顺便说一下,例子1如果用C++的运算符重载来实现,速度将比Forcal慢一些,也就是说,在涉及运算符重载时,脚本的效率有时比C++还要高些。5 ]8 D9 Z( a6 G3 g# ]
|
|