数学建模社区-数学中国
标题:
关于matlab代码矢量化的理解
[打印本页]
作者:
forcal
时间:
2010-10-5 09:32
标题:
关于matlab代码矢量化的理解
代码矢量化是matlab的精髓,其基本特点是运行速度快和代码简洁,它是如何实现的?
3 B1 G t3 J0 [, S- W5 W3 F* ^* m
6 m- E2 r9 c" |! {2 U$ B1 m
按我的理解,代码矢量化的本质就是设计专门的函数对数组元素集中运算,这样可提高运行速度,同时兼有代码简洁的特点。
7 m1 W! ?% N* {
/ g! C1 S& a- @+ {
对matlab的理解比较肤浅,但也确实看不出有更深意义的东西,望解惑。
: K* n5 |& @8 W, a$ a. i, @" s3 J
& R9 ]$ m7 F) v$ F% M4 a, K5 N% r3 B
大家有什么看法,愿畅所欲言。
8 Z- W! f+ |4 t0 ~
作者:
qbist
时间:
2010-10-5 09:52
我 正在 学 Matlab 软件!~~
作者:
zhwqqiangge
时间:
2010-10-5 10:17
??????????????????
作者:
wznzy0822
时间:
2010-10-5 10:52
顶。。。。。。。。。。。。。。。。。。。。。。
作者:
master_math
时间:
2010-10-5 18:32
,,,顶顶更健康!
作者:
forcal
时间:
2010-10-12 21:36
本帖最后由 forcal 于 2010-10-12 21:46 编辑
/ y7 s k7 t/ V5 ~
0 g3 ?, Q7 p; M5 `5 A1 x
我正在练手设计的FcMath库也打算以矩阵运算为基础,设计一些专门的函数对数组元素集中运算,运行效率确实有所提高(甚至有些涉及矩阵的算法比matlab还快),代码也简洁了,但不知这是不是矢量化?
2 [2 @$ C* l! x0 z; a4 {, f
. w& A* E8 f4 N# S2 i! w1 L
脚本运行效率应该取决于函数调度效率、对象管理效率和函数内部算法的实现。
8 Q9 W* k' M4 b! \; d
7 j8 }" T2 _" s M- I
我感觉,matlab的函数调度效率较低,对象管理效率这个不好说,但一些函数内部的设计比较优秀。故有些Forcal代码比matlab快,而有些慢。
# q/ p3 x$ V, b6 q# j( p
& k6 \" i$ D5 B( i1 X
以下例子体现了Forcal和matlab的效率差别所在。
( N0 |- ^4 P; m- T: @8 i
0 c$ K4 o2 E) V* g- X. o5 \& e
这个matlab程序段是网友lin2009 给出的,理论结果是每个元素均为275000。
clear all
5 o* H- l2 q( ]: G) }
clc
" B. ]9 i- O2 u5 A3 [/ T+ y
tic
. E, ~% L2 A7 i, `$ [
k = zeros(5,5); % //生成5×5全0矩阵
" P, b- l7 n% Y1 ^& x# X/ c4 Y
% 循环计算以下程序段1000 00次:
/ [2 X8 O5 ?& }
for m = 1:1000 00
8 H. a/ w" ~8 y4 k1 Y( i7 C/ W
a = rand(5,7);
L# }7 X, H* u7 j' H6 U& [( w4 L
b = rand(7,5);%//生成5×7矩阵a,7×5矩阵b,用0~1之间的随机数初始化
/ i4 N0 X& Y9 s# o3 F/ Q- P0 R
k = k + a * b + a(1:5, 2:6) * b(2:6, 1:5) - a(:, 7) * b(3, :);
+ V6 K( L- C5 B% \- b
end
' b% s% m5 U8 n2 A) e- J
k
H6 F: ~8 q- p C/ v) _
toc
复制代码
. d1 v' ?, ^% c3 {* T3 h
Forcal代码1:运行稍快的代码,比matlab约快10%吧?
8 O: X3 q6 s' H# i+ V+ W4 Y
!using["math","sys"];
" x* ^1 Z' \. ^ k4 d
mvar:
- f, q( _2 U2 Y
t0=clock(),
+ H7 N1 V7 Y: ?# f1 G$ v5 k) u% ?: Q
oo{k=zeros[5,5]},
3 ?" ^$ L* X6 ~8 Z) V) V; U
i=0,((i++)<100000).while{
2 m; S# g7 m$ V/ o. Y. Q2 Y
oo{
' E- C* ~1 g2 }" p
a=rand[5,7], b=rand[7,5],
; T t% ~! X# @: e
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)]
) W$ p' o. A& ]+ p2 ?
}
$ j' j7 x) {* A3 N2 X$ ^- u& ~% _
},
, {6 {! o g1 p- Y+ \$ }
k.outm(),
4 W% O) \! h2 j+ l' M1 k: u
[clock()-t0]/1000;
复制代码
在我的电脑上运行时间为3.344秒。
; O' j5 K' r7 d. y$ e3 {( ?6 F
! F9 {" j& O, {3 t* F- U! f
Forcal代码2:比较好看些的代码,似乎也比matlab稍快吧?
. o% E$ r' P: `8 ]8 n' D2 |% N1 H
!using["math","sys"];
! }' a4 ?8 @' }: b
(:t0,k,i,a,b)=
# m2 ?3 N$ Q8 W; j9 C/ C" x
{
/ i0 K0 P! D M: A% m. K0 X
t0=clock(),
8 n/ d' u* q$ R7 e; m' @" T$ n2 L
oo{k=zeros[5,5]},
9 @* F& t [* i+ }5 P! o h( X3 K( t
i=0,((i++)<100000).while{
* A, m$ A7 x9 h2 n" N, G
oo{
5 |# K& ^6 A; z# c6 E# f( O' Y! e
a=rand[5,7], b=rand[7,5],
$ \/ X1 y0 f0 i: j0 S S
k.=k+a*b+a(0,4:1,5)*b(1,5:0,4)-a(neg:6)*b(3:neg)
2 w i4 C( C6 O2 v. j
}
8 u1 x% a6 U3 `8 O/ s% Q, Y' t1 c
},
B& L1 P8 a& \' A7 V: e1 {
k.outm(),
. H% p" w2 M- q! a& {+ i K! c* v
[clock()-t0]/1000
6 r4 B. z8 V7 |9 t2 W! o0 v! _. S
};
复制代码
在我的电脑上运行时间为3.579秒。
6 ^/ `- H& _4 i) i9 u: I3 D$ D7 p: f* Q9 K
- M p) i. }8 h6 p
例子2:
1 `3 w! H$ J9 @: l
一段程序的Forcal实现:
! }- z n$ G6 i
//用C++代码描述为:
2 X% x3 G0 ]3 C7 a- Y, b' }8 I/ H- X
s=0.0;
. d* D9 ]2 i! a7 @' |& t
for(x=0.0;x<=1.0;x=x+0.0011)
: `" S a5 T$ `2 r
{
H; q5 g, Z0 F7 P. s5 \
for(y=1.0;y<=2.0;y=y+0.0009)
$ \( B- N! p1 }$ h' O( J
{
! _0 G! |, N9 |1 c3 x4 _( v+ v
s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));
- o% f( S; L9 x2 t1 V. g1 M% }) v
}
! X R# }5 Y2 Z/ @
}
复制代码
结果:
# j# T+ {0 G% B5 H! y
1008606.64947441
$ U9 N$ _" g1 ^
0.609 //时间
3 E$ ?- f3 e1 t2 S$ o* w
. P: e+ }$ |: \1 Q6 h% s3 ~
这个matlab程序段是网友yycs001给出的。
' l& L+ F8 v" F0 A/ h! a
%file speedtest.m
) C* e' \+ Q t1 l; k
function speedtest
4 w; d% b$ ~" N! m$ _6 [
format long
8 a+ b' B/ H( ~3 ^
tic
; N$ k) f/ W" }/ K7 N
[x,y]=meshgrid(0:0.0011:1,1:0.0009:2);
\5 F, o9 Y- Y+ x9 \( w
s=sum(sum(cos(1-sin(1.2*x.^(y/2)+cos(1-sin(1.2*y.^(x/2)))))))
7 T* d9 [, p8 _$ z
toc
复制代码
; O+ K9 v- }+ @$ W) t
Forcal代码1:**数组求和函数Sum,完全矢量化的代码
, X1 b: J3 Y8 p9 r) o4 H
!using["math","sys"];
% u+ p4 h O, ?4 L" j
mvar:
# b. H6 T3 \- r2 g& d6 h
t=clock(),
0 |: B% H) @ g
oo{
8 m$ ~8 u; V8 G, _# w
ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],
4 b; j, L! V( O8 C& s: z% 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]
/ ~* m6 _- u7 D6 }
};
& n$ [0 T, ~3 y! ` R, A+ Z
[clock()-t]/1000;
复制代码
结果:
' r2 h3 T8 ^8 I( h( {% ?0 R! h
1008606.64947441
4 Y0 Y/ ?0 b2 q
0.625 //时间
6 ^# f5 R2 `: k
& _+ u4 i- M& |7 Y' ]
或者这个,与上面效率差别不大:
% @6 M; I; s3 s
!using["math","sys"];
* T& p$ b% j/ V1 v
mvar:
C4 K) c; i7 \. M7 x* b0 b
t=clock(),
; F. {7 {) u# G: [" |! G+ I
oo{
+ x: J* ]) V, L6 Y2 c
ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],
5 ~! R" U' \4 j0 q
Sum[Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2))))))]]
3 e7 ^- j: F' O, z+ B( i3 c
};
! b7 V3 c& I# N S
[clock()-t]/1000;
复制代码
* V4 `4 a( ]4 ]/ u7 z9 w
Forcal代码2:求和函数sum,非矢量化代码
( t/ p$ F: j. H
f(x,y)=cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));
* R2 C/ P4 {1 ?! [
sum["f",0,1,0.0011,1,2,0.0009];
复制代码
结果:
% M' p2 Y2 ~. {8 n/ o6 ?% x0 ^# q
1008606.64947441
" _; B* I9 p0 a- d8 |8 e5 C: v
0.719 //时间
% f ~, M. A N% U# G
+ d; I: K# a" W; {) X/ L% Y+ {4 u
Forcal代码3:while循环
0 g0 M8 \5 A6 ]1 [
mvar:
& m' B; J) o4 _& x( m
t=sys::clock();
1 p) o+ _; h1 c+ Q2 n. r
s=0,x=0,
; d& Z' p& T! u( U
while{x<=1, //while循环算法;
" e% B- }% ]0 z2 I2 I
y=1,
- [# y+ ~ c3 c9 L# N
while{y<=2,
, E8 T/ U% i4 \; ]5 U3 {+ b
s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))),
3 h5 A |* {% b8 ]3 M5 k
y=y+0.0009
- s, ?" r6 r' v/ ^' \
},
& e" {! e0 \$ z8 e
x=x+0.0011
+ O/ _3 E" p5 i" C7 ?
},
& K* O& ^2 W3 D& x K( h$ _+ O; {
s;
% y% V( L; v- J6 M6 D
[sys::clock()-t]/1000;
复制代码
结果:
2 L$ n: v- I! V3 S
1008606.64947441
" w! E! z2 t a8 J# i
0.734 //时间
7 v$ o* u3 d+ w% v6 i9 R: V1 b; j
: c- ?6 ~6 A }" g7 ?+ Y
大家可下载OpenFC进行测试:
http://www.forcal.net/xiazai/forcal9/openfc32w.rar
- W* y/ |7 k+ |
0 x4 [( W" C$ k2 z& R
注意Forcal的矢量化代码第一次运行有时效率较低。
) z3 j5 E' W, ?" W0 q2 ]* h
3 N4 r E! \+ u$ {/ ^+ r
例子1中Forcal和matlab都是矢量化代码,但matlab跑不过Forcal。该例子的特点是函数调用频繁,临时变量生成多,但矩阵很小,矩阵的各种函数运行时耗时较少。故说明Forcal函数调用+变量管理效率优于matlab。
9 C$ K5 I" `4 I0 y* ^8 p
/ [3 W3 E4 X% h+ a
例子2中Forcal的矢量化代码是最快的,但与matlab的矢量化代码相比仍有差距。该例子的特点是函数调用少,临时变量也少,但矩阵大。故说明Forcal的各种矩阵函数Sin、Cos及矩阵的加减运算等函数的内部设计不及matlab。
' `( S' j, P0 V
' `6 W; o2 S% ~$ G4 u o
如能在函数内部设计上下点功夫,例子2超越matlab也是可能的。在这方面,期待高手们的指点。
4 i1 [( t$ ^2 b
5 m: h% q" u5 b9 Y. V) V3 w
如果例子2速度也超越了matlab ,matlab矢量化的神秘面纱就揭开了。
3 G/ {9 q! q: K' Y- \& F
) K! b z- B4 v1 }9 A: S
顺便说一下,例子1如果用C++的运算符重载来实现,速度将比Forcal慢一些,也就是说,在涉及运算符重载时,脚本的效率有时比C++还要高些。
/ t6 c1 S& h" E" d/ o7 d( ^- Q7 n, f
作者:
forcal
时间:
2010-10-16 16:59
讨论有益!以下是在其他论坛的讨论帖子:
+ {6 t/ S. E, r" h. s: Y) z
simwe:
http://forum.simwe.com/thread-952532-1-3.html
7 E" n; v. M5 x) i" R
csdn:
http://topic.csdn.net/u/20101006/21/2ed9e5c1-cc9f-4623-b1c0-ebd5d1b5a98a.html
3 K7 D5 X: |* A0 R
cadn:
http://topic.csdn.net/u/20101010/15/3bcf2fe0-0abd-4c29-b854-b1d007b16863.html
4 U1 K$ l. `* H
作者:
forcal
时间:
2010-10-24 16:59
参考:
http://bbs.emath.ac.cn/thread-2709-1-1.html
0 U' [: E% D5 l! W4 ]& c
1 ^* h8 E1 g8 W$ R" Z# A
我在多个帖子中有不同说明,但将这些说明再集中到一个帖子中比较麻烦,大家相互参考一下,看能否把这个问题解决了。
作者:
forcal
时间:
2010-11-2 18:06
参考:
http://bbs.emath.ac.cn/thread-2727-1-1.html
; i2 J6 Y5 a" o2 w
2 d* }1 K5 t$ j7 j [. l
关于最快速的矩阵乘实现的讨论。
8 t7 O9 C# w/ Y) W+ v
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5