- 在线时间
- 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 编辑
7 }! O. U S; J5 l- o$ I
6 ]' f# y2 J; Q4 {我正在练手设计的FcMath库也打算以矩阵运算为基础,设计一些专门的函数对数组元素集中运算,运行效率确实有所提高(甚至有些涉及矩阵的算法比matlab还快),代码也简洁了,但不知这是不是矢量化?& n; v/ I8 ^: x0 A
" d$ [4 w8 K. ^, E( _脚本运行效率应该取决于函数调度效率、对象管理效率和函数内部算法的实现。
+ ~. q' ?2 ?: P; R T* h1 d! B& H. h1 n2 s0 u8 L" U7 l
我感觉,matlab的函数调度效率较低,对象管理效率这个不好说,但一些函数内部的设计比较优秀。故有些Forcal代码比matlab快,而有些慢。4 H; G& K- z) F& [$ ?1 r
: G. q# c2 n* f. M6 K( p4 h5 n8 T以下例子体现了Forcal和matlab的效率差别所在。
% Q* {& T, l, {5 [$ V" k
' z) r; |6 R- f# Z这个matlab程序段是网友lin2009 给出的,理论结果是每个元素均为275000。- clear all
0 {8 |, @) m8 f0 m* r\" Q: F - clc# l5 U- V6 a* w w0 R: a
- tic
0 A d! I, m( J9 }8 _2 ` - k = zeros(5,5); % //生成5×5全0矩阵
7 o$ {! V% Q/ n. c - % 循环计算以下程序段1000 00次:
+ m& d- X G0 A4 a1 l\" _5 k - for m = 1:1000 00
; B1 I0 D# \$ G$ N7 I - a = rand(5,7);% f' ^$ o, O/ X+ u
- b = rand(7,5);%//生成5×7矩阵a,7×5矩阵b,用0~1之间的随机数初始化
% O' X7 n4 [& [4 C - k = k + a * b + a(1:5, 2:6) * b(2:6, 1:5) - a(:, 7) * b(3, :);
& q% B5 P1 ]! r$ ?8 t0 V - end+ ]* t0 o$ B3 V2 K# c
- k* j4 F0 r8 U2 X+ R
- toc
复制代码
6 r6 E2 B* p1 p* u |Forcal代码1:运行稍快的代码,比matlab约快10%吧? q! T7 [7 G) }- U8 D0 M2 h+ v
 - !using["math","sys"];8 ?) y z! L$ B# W
- mvar:
- * Y& C; _; D& L
- t0=clock(),
- 5 i6 A, d9 U7 X; \. v/ J
- oo{k=zeros[5,5]},
- 1 r: O, ^) A5 i9 C1 S( C\\" s
- i=0,((i++)<100000).while{
- 4 ]* W, G( B' p. k7 e2 |7 K
- oo{: w4 e3 l% _( H6 C8 D7 G
- a=rand[5,7], b=rand[7,5],
- \\" M- V* _9 W# A
- 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)]- }\\" g' M' G\\" X; x+ d0 t9 ~' J
- }
- 3 d; T/ m( w2 K4 L+ Q- l3 L8 L
- },\\" B, Q9 g- Y4 ?, `\\" m' T\\" l: j
- k.outm(),
- ) r5 ?2 l' @8 G
- [clock()-t0]/1000;
在我的电脑上运行时间为3.344秒。
( S, f% C9 o2 O3 b! m1 `* ^; c5 e% F
2 t$ `: g ^6 ?: I( c( P4 DForcal代码2:比较好看些的代码,似乎也比matlab稍快吧?
5 e" N0 V: y4 ^5 Z - !using["math","sys"];* \% S, L: ~, F1 |8 y9 N! P
- (:t0,k,i,a,b)=5 w0 R9 h% P* J8 T5 Z- q
- {
- 4 D* I! N; C2 N+ m; m
- t0=clock(),: B5 B% D# K! y# `+ F
- oo{k=zeros[5,5]},
- & [, G$ c3 J2 Y; g2 s\\" b$ [
- i=0,((i++)<100000).while{1 g2 Q7 z/ M! [, H( C2 i3 X
- oo{
- @/ E( z$ A. L H- I. M; g4 ^
- a=rand[5,7], b=rand[7,5],3 @0 ]4 S- w& s\\" G; |7 |8 e
- k.=k+a*b+a(0,4:1,5)*b(1,5:0,4)-a(neg:6)*b(3:neg)% c5 a& |- m- R
- }
- + Z9 y k8 G8 h3 A/ Y: p& X
- },1 _$ q$ r/ F& }& x0 `! P
- k.outm(),
- 1 e\\" h2 g- `2 I6 a0 ^
- [clock()-t0]/10006 K7 b9 F, T, h$ y
- };
在我的电脑上运行时间为3.579秒。
0 r3 k3 W! p+ v; V% r. e9 {
1 V: l7 ]6 D7 F4 g- n2 ]- y$ m7 X例子2:) |' L/ p' J; j8 I; ]1 o4 R
一段程序的Forcal实现:7 R1 n& ^; S) |( b& X5 f
- //用C++代码描述为:
\" |; N. _& ^& i1 v6 ]9 ]& x\" B - s=0.0; & {& c* F& P' b
- for(x=0.0;x<=1.0;x=x+0.0011) * j! z! S/ {* E' Y: c$ W
- {
9 ?6 H0 K# b; p, l - for(y=1.0;y<=2.0;y=y+0.0009)
2 N9 v5 W2 t2 a: V. Y1 J - {
' g2 b! }7 L3 s7 \8 s2 S - s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));5 W7 l) t, U\" V) h, I
- }, @+ ]: ~ U2 j3 O0 [, a0 w
- }
复制代码 结果:
* M2 V, o# K& V. B1008606.649474414 D. Y8 a2 a- X/ D6 s0 T" E
0.609 //时间
% ~6 Q1 X4 H+ `, I" X4 T3 Y7 x' A7 V' `% c
这个matlab程序段是网友yycs001给出的。. I0 c/ \# C+ d+ V* M4 X
- %file speedtest.m
8 f4 ]* H7 w6 c) d& r7 Y - function speedtest9 n4 f2 r; X- _$ h4 ?0 h) f, u& [5 M' u
- format long
; k( D! B) ]# c) {9 ~' `+ o7 q2 S - tic
* z% T/ c+ | s- i$ C7 I( V% a - [x,y]=meshgrid(0:0.0011:1,1:0.0009:2);3 ^5 y5 k, d3 }' T
- s=sum(sum(cos(1-sin(1.2*x.^(y/2)+cos(1-sin(1.2*y.^(x/2)))))))* F0 R- H5 L9 e [2 j
- toc
复制代码 % S$ I2 X, K( ^& U+ z. ]
Forcal代码1:**数组求和函数Sum,完全矢量化的代码) i, h# S$ A' w t. R. W
 - !using["math","sys"];& O9 j, Z! x6 h( Z' @8 s# V3 H% `6 P
- mvar:
- 2 x: ^! F% B- H+ b% l
- t=clock(),\\" q5 @3 D e7 D k! r& f
- oo{
- 6 z8 R. O6 h0 i$ x\\" e
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],
- 2 ? {2 L: A+ e$ r9 o. U2 E% b8 Z
- Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2)))))),0]
- : O0 z/ h1 ~+ E& T$ K
- };% t8 l% D: j' {( {5 r9 u\\" E7 ]/ b
- [clock()-t]/1000;
结果:
: t5 D4 U7 a4 x- m* A+ G z1008606.64947441
' c, C1 R/ r0 X2 d0.625 //时间
6 p4 M1 y3 e9 u. {$ x; s% G1 T4 y' @* E! W
+ o( G/ i# ?5 \" B6 z或者这个,与上面效率差别不大:7 O- |2 v* O! e4 D
 - !using["math","sys"];& C/ m- j! h. ]) h
- mvar:
- , i) J' ?/ P1 L
- t=clock(),
- # A6 x M% |2 U* c W
- oo{
- 4 ?4 ?0 f' @3 N! w+ ^7 D
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],! m+ L, W4 o, H, s+ v
- Sum[Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2))))))]]
- 4 O5 Q; S- }- }( [7 Y
- };) @% V4 o3 H) _& o
- [clock()-t]/1000;
* k* A$ B* b% y7 a7 [
Forcal代码2:求和函数sum,非矢量化代码
3 w P0 U6 ]5 s( Q$ f- f(x,y)=cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));
4 h9 T% p\" b) E5 ^% e+ Y - sum["f",0,1,0.0011,1,2,0.0009];
复制代码 结果:9 r5 u% J4 b8 V6 i* W$ ~% \
1008606.649474416 Z- U+ l8 v2 b; F V- M3 I/ r
0.719 //时间
# e4 M1 F- \+ c5 t/ Z
. @& \1 ~/ ]4 qForcal代码3:while循环
% q% h# p5 _' P( A- mvar:5 y/ t% u! Z\" n\" f- G7 H
- t=sys::clock();
! t. U7 T& c6 x- Y1 f: b\" X - s=0,x=0,
7 C7 g; z9 a' j6 ^; n5 I - while{x<=1, //while循环算法; % r- ?! z* n1 z
- y=1, : ?6 M$ m) _* E T7 V
- while{y<=2,
\1 i' Y: N w- \ - s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))),
+ ]: P& I N+ u+ y\" X - y=y+0.0009
; w7 l: L; Q5 E0 N* O3 T- Z( C - },
( R) x2 y. {8 i+ t7 B% s2 z - x=x+0.0011
4 Y1 F! ^. [\" X9 X( s - },
* t\" Z3 [0 S& x; P\" u* A3 W5 y9 { - s;7 S/ S% u7 }, Z
- [sys::clock()-t]/1000;
复制代码 结果:1 ]+ C- o. ]2 u) Q5 h8 x! C
1008606.649474416 \ @& d9 y; B$ s5 y
0.734 //时间" ]2 V: O7 s1 g" X L$ s
0 p9 J( @0 Q' Z" i大家可下载OpenFC进行测试:http://www.forcal.net/xiazai/forcal9/openfc32w.rar9 l- |* f$ p% S9 M' ]
- _+ |0 }9 f6 E# v注意Forcal的矢量化代码第一次运行有时效率较低。/ s- f* o8 }/ p
& a4 H% V* C6 |4 a3 j2 k1 D+ X
例子1中Forcal和matlab都是矢量化代码,但matlab跑不过Forcal。该例子的特点是函数调用频繁,临时变量生成多,但矩阵很小,矩阵的各种函数运行时耗时较少。故说明Forcal函数调用+变量管理效率优于matlab。
. i0 I, j2 q1 R4 b
8 n8 K5 J% [* U8 N; |6 ~" e例子2中Forcal的矢量化代码是最快的,但与matlab的矢量化代码相比仍有差距。该例子的特点是函数调用少,临时变量也少,但矩阵大。故说明Forcal的各种矩阵函数Sin、Cos及矩阵的加减运算等函数的内部设计不及matlab。
) z$ N& k6 x. W3 X
% X% w! `* }" B A6 @如能在函数内部设计上下点功夫,例子2超越matlab也是可能的。在这方面,期待高手们的指点。
. |5 ~ S' |! E/ ]( f3 F- T+ }5 S0 T, c6 S$ f% n6 a& ?) `: o, q% ?: t
如果例子2速度也超越了matlab ,matlab矢量化的神秘面纱就揭开了。- _0 j% b) L# n4 _
# N" n/ ]) T4 M* K9 p+ S
顺便说一下,例子1如果用C++的运算符重载来实现,速度将比Forcal慢一些,也就是说,在涉及运算符重载时,脚本的效率有时比C++还要高些。
% T; U. T, g3 [7 [. l1 f6 j1 i |
|