- 在线时间
- 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 编辑 + S' L5 w: B+ X# \
! t. P' q; [) p5 L, J我正在练手设计的FcMath库也打算以矩阵运算为基础,设计一些专门的函数对数组元素集中运算,运行效率确实有所提高(甚至有些涉及矩阵的算法比matlab还快),代码也简洁了,但不知这是不是矢量化?
: O; q9 c* W4 q- u- A3 l0 Q* d' m1 G' \
脚本运行效率应该取决于函数调度效率、对象管理效率和函数内部算法的实现。8 ^ {6 X' D' w& j2 d- E3 T
1 N) B. M) H c我感觉,matlab的函数调度效率较低,对象管理效率这个不好说,但一些函数内部的设计比较优秀。故有些Forcal代码比matlab快,而有些慢。
: X4 n2 M9 H9 T2 A3 x9 K6 a+ Q
5 z3 t/ Y& x# K1 k' `9 [3 f以下例子体现了Forcal和matlab的效率差别所在。
/ i. [- M1 n8 [! d, H! V7 ^5 J+ K% ] c
这个matlab程序段是网友lin2009 给出的,理论结果是每个元素均为275000。- clear all
0 d3 }; v, g+ n' u: @6 e1 e8 p! U - clc7 k: ^, c9 ^\" b8 ^# k* k7 N
- tic
' Q7 R6 Z5 c4 z1 d! ] - k = zeros(5,5); % //生成5×5全0矩阵; r6 t! O; \; P* ~* o/ v9 E
- % 循环计算以下程序段1000 00次:
v5 Y- r3 [& t4 J8 g! B- d - for m = 1:1000 00
# K4 ?1 ]3 g. S1 k F\" V& \ - a = rand(5,7);
1 _/ ?0 ~9 N7 r\" t - b = rand(7,5);%//生成5×7矩阵a,7×5矩阵b,用0~1之间的随机数初始化
; W+ ^0 K( |) w\" x6 T* T( y) r - k = k + a * b + a(1:5, 2:6) * b(2:6, 1:5) - a(:, 7) * b(3, :);: o7 f* H0 w+ ~$ O1 n
- end
- ^5 @) h! Q6 c0 m - k. K2 g( O4 ?6 @: I& W
- toc
复制代码 / j% l% P. v$ u" [! G8 O. X. Q
Forcal代码1:运行稍快的代码,比matlab约快10%吧?
9 R" M' N; E: b# t! ~& |+ Y - !using["math","sys"];
- 7 W3 P% |+ P0 K p3 O+ M
- mvar:0 {- o; g8 m4 z: t& E$ A, P5 T! A
- t0=clock(),
- % i- f! t+ k. K7 {3 D# j
- oo{k=zeros[5,5]},! s: ` V' J* ~9 |% t
- i=0,((i++)<100000).while{6 K& N. r. ?# P0 n
- oo{9 L$ F) u' G! |2 [2 g2 {; [, N
- a=rand[5,7], b=rand[7,5],
- ; ~5 D) z' d/ K8 r* B3 v5 {
- 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)]
- 9 C- B( G0 ]+ i+ P+ P- g2 r
- }2 ]3 g6 X\\" R3 k4 y. b
- },
- 8 B2 W7 Q6 Q\\" f6 ?; z
- k.outm(),9 Q0 i! P9 j, w* x3 Q/ x2 {! `
- [clock()-t0]/1000;
在我的电脑上运行时间为3.344秒。4 n% X( E8 J) Z1 j) E0 Z: P
8 E1 M. s. d! M/ T( o) w# r- EForcal代码2:比较好看些的代码,似乎也比matlab稍快吧?
3 f/ s9 ~, ?4 q3 \ - !using["math","sys"];
- ( |5 a, h3 U% M: ?3 K) N; @- L
- (:t0,k,i,a,b)=! ~6 A' z; Z* M5 E {
- {
- 3 E# _8 @2 q: @ i. C
- t0=clock(),$ W6 u5 c9 c/ B- p
- oo{k=zeros[5,5]},
- 8 W4 x5 ]0 |0 C\\" Q* P1 X
- i=0,((i++)<100000).while{
- ; q! @6 X8 D0 l3 p3 K\\" o
- oo{) K8 u- c8 p( f
- a=rand[5,7], b=rand[7,5],+ Y6 }( g# z$ J7 F; m
- k.=k+a*b+a(0,4:1,5)*b(1,5:0,4)-a(neg:6)*b(3:neg)( M# B0 {' i4 j
- }% a\\" X6 N; F$ J) u3 y
- },. y) k' R, q1 S# |; ^
- k.outm(),
- , ^/ g# ]2 H5 H
- [clock()-t0]/10006 L' D- d/ _* S( E9 v
- };
在我的电脑上运行时间为3.579秒。 H8 t) c9 ^9 ^ J0 |: O" u
5 l: i' N' u9 J例子2:
6 h. {8 O. I k' z% _" H* E; |2 G一段程序的Forcal实现:
) Q, l" L1 I4 `% I, y2 f, S- //用C++代码描述为:
( @2 \4 v* n! r - s=0.0;
3 R! o' J: T o2 M5 M4 @ - for(x=0.0;x<=1.0;x=x+0.0011)
8 B4 |$ x- t K( c9 R& B - {
2 K& P) B5 E% {# J+ n) y - for(y=1.0;y<=2.0;y=y+0.0009)
) V9 t: k' |/ N% l; V\" B - {9 L, R/ g5 [& K: o, y2 T: I0 f
- s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));
7 Y9 h0 x* k* R6 ]% D' A( B I7 e3 z - }; x# \+ U, B' x: X2 B) q: m
- }
复制代码 结果:
G; Y' C) f2 X1008606.64947441
$ f4 f t \4 t9 G3 y: p( T0.609 //时间
4 f: C; T5 U! X. f# T& q! H" j4 l
这个matlab程序段是网友yycs001给出的。- e1 c' T c- ?( A* x D
- %file speedtest.m
& ~3 k\" s% k7 P/ a' B - function speedtest
4 R, s0 _( N% E9 [% N( y - format long
; V2 _. K3 }) @ - tic
+ {\" E* }7 i5 Z1 V. T - [x,y]=meshgrid(0:0.0011:1,1:0.0009:2);8 P6 R# m, P6 ]4 \. u
- s=sum(sum(cos(1-sin(1.2*x.^(y/2)+cos(1-sin(1.2*y.^(x/2)))))))) r# @9 z: w8 b* f* h
- toc
复制代码
( ^1 J# t8 K+ l5 a7 ^* n+ kForcal代码1:**数组求和函数Sum,完全矢量化的代码' Z' ^0 M, \# X- o1 A" g+ F
 - !using["math","sys"];
- & s4 o+ u- ^8 N: S
- mvar:$ u2 K% q7 u8 @3 j' Y. l
- t=clock(),
- 0 j6 W7 I. ~! p& c7 S
- oo{
- - H- c7 f) B6 K) B1 T9 P. p$ ?
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],
- / k& K4 z/ X6 ?$ n3 M
- Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2)))))),0]
- 8 V/ T% A' D V* q+ ?/ J
- };
- % ]: V9 c2 @7 L
- [clock()-t]/1000;
结果:6 ~1 c5 B/ R' w$ g _
1008606.64947441% K4 H0 k# j6 B/ g8 r
0.625 //时间4 p: I- V; S* {
* k4 A: }. X5 v# Y1 j8 m! ]: O或者这个,与上面效率差别不大:
7 |: U, o5 {7 ?3 W; } - !using["math","sys"];( N) c6 F5 j8 d: ?. u' F
- mvar:
- ; @9 f! Q8 A' [7 p\\" W5 s
- t=clock(),
- 2 j4 W! _% }+ h7 G8 X
- oo{
- 2 m9 C7 y% d( ]% S\\" `
- ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],) b1 K: v 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))))))]]- s: E+ T! [1 @9 g Q7 U6 ~/ Q
- };
- 8 S2 J) |/ j2 T6 P# h
- [clock()-t]/1000;
; C, a/ }' x9 i& w2 ?# X; H/ L
Forcal代码2:求和函数sum,非矢量化代码
1 k. w, |: m# o5 _$ K- f(x,y)=cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));
\" }/ a* Q3 @9 K - sum["f",0,1,0.0011,1,2,0.0009];
复制代码 结果:
6 c; Q: \6 V( ]. Y3 c1008606.64947441
+ \* K. e S- f" O3 W* U0.719 //时间6 @2 Q5 O, g( h
5 l. d- O* V$ g+ Z5 n
Forcal代码3:while循环( V" D% P% G/ x9 I7 v
- mvar:
. D. O) Z4 i4 y( o4 W w4 g5 N0 p - t=sys::clock();
+ }( ^( X8 R# W. r\" X; K - s=0,x=0, & L1 A2 C& X: E1 g1 a
- while{x<=1, //while循环算法; ; z/ \; u& z0 A3 d. r
- y=1,
% z! W3 j5 |! t - while{y<=2,
0 ^$ G, |- y4 O5 O+ z$ {2 ^0 I\" _& _0 a2 ]1 w - s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))),
# h% S% w\" }. v3 K8 M - y=y+0.0009
2 o& Y& r1 O$ s( F. n: W - }, 5 f1 I( T\" a# J# G+ P
- x=x+0.0011
$ U\" Z0 ~% |5 u$ p: \! c - },
6 i. i) |9 T0 u% o& e - s;. p+ z# I& a7 K0 |# Q# g
- [sys::clock()-t]/1000;
复制代码 结果:* M* Z% F, c$ b: Y7 Y
1008606.64947441
9 F7 ^( \# `1 r0.734 //时间
! p& ]9 I! j- t! a/ l+ N- u' ]7 R$ I6 u5 Q, @0 I$ C) _# _' b+ i5 k' W
大家可下载OpenFC进行测试:http://www.forcal.net/xiazai/forcal9/openfc32w.rar
$ ^) {9 w; W9 }2 X& R9 o
, @9 H4 B1 D ~6 o8 d* f k' _注意Forcal的矢量化代码第一次运行有时效率较低。' h: o1 s# f0 j X- H" q. H
/ \/ \0 |+ T1 J) o% ?
例子1中Forcal和matlab都是矢量化代码,但matlab跑不过Forcal。该例子的特点是函数调用频繁,临时变量生成多,但矩阵很小,矩阵的各种函数运行时耗时较少。故说明Forcal函数调用+变量管理效率优于matlab。! L @! j8 J: l6 O; c
8 v. I7 o5 p P8 c9 W9 z% A
例子2中Forcal的矢量化代码是最快的,但与matlab的矢量化代码相比仍有差距。该例子的特点是函数调用少,临时变量也少,但矩阵大。故说明Forcal的各种矩阵函数Sin、Cos及矩阵的加减运算等函数的内部设计不及matlab。4 N. {3 k6 y& q g7 N* y" Z8 C
' d& _& Z5 _1 L& L+ f# i9 J% P3 f) O如能在函数内部设计上下点功夫,例子2超越matlab也是可能的。在这方面,期待高手们的指点。
4 X# Q+ e: U0 n: m. c+ C6 [6 x, ~/ m( P/ X- Z; ^4 `1 \
如果例子2速度也超越了matlab ,matlab矢量化的神秘面纱就揭开了。8 [1 |$ m8 M" o) S% ^8 k- @
+ e" f: ] S& s: `顺便说一下,例子1如果用C++的运算符重载来实现,速度将比Forcal慢一些,也就是说,在涉及运算符重载时,脚本的效率有时比C++还要高些。3 F2 ?% j2 s* y& Z& I. _& U
|
|