- 在线时间
- 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 X6 `/ ]' ~, r: S, R
) g- F% B- g) O* |
我正在练手设计的FcMath库也打算以矩阵运算为基础,设计一些专门的函数对数组元素集中运算,运行效率确实有所提高(甚至有些涉及矩阵的算法比matlab还快),代码也简洁了,但不知这是不是矢量化?; q0 m5 Q$ H, I( W3 @0 G
$ f$ _* {9 z( R+ R1 I2 m脚本运行效率应该取决于函数调度效率、对象管理效率和函数内部算法的实现。/ q3 \4 ?4 [ \* ?( S; h$ L+ _
0 ]# c( ~3 {( |我感觉,matlab的函数调度效率较低,对象管理效率这个不好说,但一些函数内部的设计比较优秀。故有些Forcal代码比matlab快,而有些慢。& d7 q; B# W0 Y0 S
# M, Y) U7 M. i6 @( M
以下例子体现了Forcal和matlab的效率差别所在。3 D; p$ y2 U! ~9 Z. X- v# M
6 o) D3 K% M% {* Z( c" Q
这个matlab程序段是网友lin2009 给出的,理论结果是每个元素均为275000。- clear all
; W7 L) a8 `. U/ V% B8 t* W - clc, j1 @, i5 ?9 W) O
- tic
3 B j! n) ^\" d# F& g - k = zeros(5,5); % //生成5×5全0矩阵
& {& ~/ q/ B( L0 u2 Z - % 循环计算以下程序段1000 00次:
9 d2 e* ] Z: n4 M - for m = 1:1000 00& P, o7 X: \3 ^( O) A% X
- a = rand(5,7);9 X5 j: c( e) ~' o6 U
- b = rand(7,5);%//生成5×7矩阵a,7×5矩阵b,用0~1之间的随机数初始化9 t2 J2 `5 U# W/ Z\" F) R
- k = k + a * b + a(1:5, 2:6) * b(2:6, 1:5) - a(:, 7) * b(3, :);7 I8 F* b4 G5 n0 P
- end
7 }3 r3 A) `2 L - k3 Z6 t' V3 G S* [6 ~4 O/ U
- toc
复制代码
8 |: b2 x @0 M. sForcal代码1:运行稍快的代码,比matlab约快10%吧?
& r- F2 E' G; d( |7 j - !using["math","sys"];
- & y, u7 P7 ]- o, j+ h: s. O
- mvar:
- + a8 z2 P/ v! Q! ~7 }4 d! D
- t0=clock(),2 ?\\" N1 v8 G7 G) M
- oo{k=zeros[5,5]},\\" j5 P2 s+ U' s. m; Z; f\\" x
- i=0,((i++)<100000).while{0 D4 ]9 |0 ^; _$ m- ?
- oo{
- . R5 Z' ^7 c\\" M
- a=rand[5,7], b=rand[7,5],
- 7 V: O) V/ o& j5 w9 C$ K
- 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)]
- 0 c9 s4 ?\\" C) c
- }1 h9 ]) b# M7 U\\" `
- },$ V; V7 w' w- X6 ^' F2 d
- k.outm(),
- 3 @+ f0 M4 C9 O\\" C |
- [clock()-t0]/1000;
在我的电脑上运行时间为3.344秒。4 z# o _/ y" n6 M
# B+ w7 H9 }; }2 _Forcal代码2:比较好看些的代码,似乎也比matlab稍快吧?
" S0 @/ Y4 B P7 }4 i" C - !using["math","sys"];# C' ~# |/ c& \# u2 R3 Q5 d% I
- (:t0,k,i,a,b)=: ~) A' m4 d& B* D- V
- {
- ! _8 Z4 w9 S' \) o3 T k
- t0=clock(),
- 6 ~! z\\" f% V# U% ]
- oo{k=zeros[5,5]},
- + U+ L5 Y3 y1 a
- i=0,((i++)<100000).while{3 D9 K, x7 y8 B# @
- oo{
- ' p' r9 n0 A\\" h# A: h l! `
- a=rand[5,7], b=rand[7,5],. E' f/ Y% m' h$ {
- k.=k+a*b+a(0,4:1,5)*b(1,5:0,4)-a(neg:6)*b(3:neg)\\" R; o2 N8 Y3 ?1 {( h2 g
- }
- 7 S, a! U: s5 \! ^+ V) S6 m
- },
- - O7 C: b: |5 Q1 m7 G6 [+ _7 A
- k.outm(),
- 3 k/ s, p- Q* G8 E+ Q! Y. y
- [clock()-t0]/1000
- 4 r; }2 p; ~( g
- };
在我的电脑上运行时间为3.579秒。
a% N9 [ Q' ~4 q P7 M! ~' z4 m1 D/ `) T# \0 T c0 T! [. g
例子2:; E+ M$ w: P+ V* X* t# c5 N
一段程序的Forcal实现:( y8 A- e" p8 z& ]2 _2 F/ v% N
- //用C++代码描述为:( S4 t8 a+ y- ~) P
- s=0.0;
$ ^; c9 q% i0 y2 m b% F - for(x=0.0;x<=1.0;x=x+0.0011)
# ]+ w( K% h! m: v - {
4 I8 @6 T' h: O - for(y=1.0;y<=2.0;y=y+0.0009)! O% b( K0 K$ P8 [- X+ {& D8 C
- {/ a1 h1 j g0 t0 f( g4 F
- s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));# h) r4 i2 t9 E1 V
- }
% N\" z. L0 b$ ^3 H& m - }
复制代码 结果:
4 Z/ D8 O: B6 K! m8 u c5 n1008606.64947441
0 O* i) I `8 s+ }, l0.609 //时间) u4 C: v9 U8 ]
# h* W _% W* x. |
这个matlab程序段是网友yycs001给出的。
( k ^3 Z# z. b' i- %file speedtest.m
# x/ s$ [9 h6 o1 o - function speedtest
+ S: Q2 e\" R4 Q\" r. p - format long
6 R% U, O6 _4 z3 ] - tic
9 ~6 ?# i6 [+ ^$ M( x3 q: C8 m - [x,y]=meshgrid(0:0.0011:1,1:0.0009:2);
1 f O9 l d( I! a - s=sum(sum(cos(1-sin(1.2*x.^(y/2)+cos(1-sin(1.2*y.^(x/2)))))))
, d2 c9 Q: t( e8 k2 Y L2 T3 w - toc
复制代码
2 z. Q y1 J: b- W7 R- L: YForcal代码1:**数组求和函数Sum,完全矢量化的代码
& w$ J% Y, t+ O3 l# ?; t. i: A - !using["math","sys"];
- \\" e7 z! x\\" j) C2 {) o8 V) h
- mvar:# p7 a& }2 t3 N& {9 X4 w
- t=clock(),1 g r l6 X a! |8 [3 ~
- oo{
- ' D+ k! r4 g/ S8 `( Z8 z u' D
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],7 B6 o: _ ^$ {+ c4 u* p4 {
- Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2)))))),0]
- - H. p5 @. r9 ^) x# B
- };
- $ i$ M4 g, R\\" W }# F; h
- [clock()-t]/1000;
结果:
4 J2 ^* Q' q7 M8 v7 v1008606.64947441
, ?, \6 [! V/ _0.625 //时间
/ }5 }( e q& T9 D6 e" J# E$ T' m- Q7 U6 ]
或者这个,与上面效率差别不大:! b8 v; v6 v1 g0 O' d
 - !using["math","sys"];
- 4 l6 z7 a: d0 q& b7 ~( O |
- mvar:
- 2 F; O- ^1 E/ n2 {$ ~' J
- t=clock(),
- 6 ^6 [8 f, C/ q( h& i9 l
- oo{
- 5 [3 e4 }# `* t! f\\" @( ~7 r! ^
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],. J- j* P# a. W3 T, b; U3 j0 S
- 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 ]& v( y2 I9 p% }* u) {. {3 Z
- };
- 6 D5 b' i0 g9 B- C) P O
- [clock()-t]/1000;
- Z; N. |/ ^6 \* [
Forcal代码2:求和函数sum,非矢量化代码
# f* I! L/ ^" i* ~: A& t- f(x,y)=cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));
7 e) W2 t# Q/ O, H - sum["f",0,1,0.0011,1,2,0.0009];
复制代码 结果:' k) Q+ u6 I O! V$ N* A* Z' x p
1008606.64947441
& U+ x: T1 Q9 h4 r0.719 //时间
$ K* h Y6 {9 C! k1 k3 ~9 o) u8 H' I* K4 G
Forcal代码3:while循环
3 [, Z- W! s l& ^3 e E: `1 d) p- mvar:3 p- S0 I+ L0 i* F& }* R! n& I
- t=sys::clock();. f! \% d6 P% n* q: g \; a
- s=0,x=0,
. M( G$ ^$ d% U* {6 e - while{x<=1, //while循环算法; 1 U! Y. M$ s\" n% \\" m6 F$ X7 B
- y=1, + X3 H% _: A' M2 P
- while{y<=2, P3 m* O7 X1 R( ]4 N
- s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))),
: Q3 u R* L$ T( j - y=y+0.0009
* h) w, y$ I: o7 D - },
4 Y' @7 n5 U0 f, M0 `- S - x=x+0.0011
\" C2 M/ U$ e' t4 S. K: T% E. g - }, ' `3 \8 v5 s( w
- s;/ V9 W2 x6 O* k1 L
- [sys::clock()-t]/1000;
复制代码 结果:/ M9 Y+ i! r" K4 l: j0 S
1008606.649474411 B4 `9 ^3 n* K, T/ p
0.734 //时间; {/ b# O. t9 w$ E5 d* E3 I" \( p/ x
U; e- Z9 V' i% T z
大家可下载OpenFC进行测试:http://www.forcal.net/xiazai/forcal9/openfc32w.rar
, d# _8 |9 u$ I/ {1 Y
& {0 M$ u% G: }$ U. g注意Forcal的矢量化代码第一次运行有时效率较低。
3 ]" y0 e! N# }: N" s: i0 `
4 ~* e0 N4 h8 p. e0 |例子1中Forcal和matlab都是矢量化代码,但matlab跑不过Forcal。该例子的特点是函数调用频繁,临时变量生成多,但矩阵很小,矩阵的各种函数运行时耗时较少。故说明Forcal函数调用+变量管理效率优于matlab。
' a6 {, G \) x+ U ^$ J- J) \7 j( c! E w( m, J$ I
例子2中Forcal的矢量化代码是最快的,但与matlab的矢量化代码相比仍有差距。该例子的特点是函数调用少,临时变量也少,但矩阵大。故说明Forcal的各种矩阵函数Sin、Cos及矩阵的加减运算等函数的内部设计不及matlab。* O; A& U+ l% m8 n& c
8 h' |+ V% k# Z M; ^+ |, t如能在函数内部设计上下点功夫,例子2超越matlab也是可能的。在这方面,期待高手们的指点。: N; e0 r7 i" X/ L8 U& @9 P8 N
4 P: m6 J6 w: r" A; ~
如果例子2速度也超越了matlab ,matlab矢量化的神秘面纱就揭开了。$ X1 P. E* D6 B/ n
. ?# |0 p3 z8 T3 u" s/ h
顺便说一下,例子1如果用C++的运算符重载来实现,速度将比Forcal慢一些,也就是说,在涉及运算符重载时,脚本的效率有时比C++还要高些。9 e' R$ ]2 ^1 W$ z$ D& f# Z
|
|