数学建模社区-数学中国
标题:
关于matlab代码矢量化的理解
[打印本页]
作者:
forcal
时间:
2010-10-5 09:32
标题:
关于matlab代码矢量化的理解
代码矢量化是matlab的精髓,其基本特点是运行速度快和代码简洁,它是如何实现的?
/ M2 f5 C; M4 P' T% i/ S) J S* m
4 K9 s# W% h' _# L, r- M
按我的理解,代码矢量化的本质就是设计专门的函数对数组元素集中运算,这样可提高运行速度,同时兼有代码简洁的特点。
- K+ w( a6 l W/ f& c; x; B( f; W( D3 U: }
& c! A! G" }5 c# D; W( E! w
对matlab的理解比较肤浅,但也确实看不出有更深意义的东西,望解惑。
( O/ }+ C- \) Q
P- g/ Z, s" B8 [& `! `8 T
大家有什么看法,愿畅所欲言。
2 D0 `$ E r, V( N% D4 t; q0 Q1 |
作者:
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 编辑
7 m' J3 t+ [8 M$ K1 s5 Z* R! ^+ {
, l* d/ [8 }" V& j
我正在练手设计的FcMath库也打算以矩阵运算为基础,设计一些专门的函数对数组元素集中运算,运行效率确实有所提高(甚至有些涉及矩阵的算法比matlab还快),代码也简洁了,但不知这是不是矢量化?
1 r2 g. E9 X( S' C
4 ?! Q; ]; U# }4 n( q
脚本运行效率应该取决于函数调度效率、对象管理效率和函数内部算法的实现。
6 J% }& y- @7 z. V$ E/ V) T
% `: J, H* J& k/ M/ ^
我感觉,matlab的函数调度效率较低,对象管理效率这个不好说,但一些函数内部的设计比较优秀。故有些Forcal代码比matlab快,而有些慢。
0 h. _/ K/ J- x' O$ _/ r
& c1 m5 I) D# K w: g5 k' d
以下例子体现了Forcal和matlab的效率差别所在。
$ M* j; k9 P* u" F
* F2 B2 c. ^5 T6 z9 H2 x: e! }
这个matlab程序段是网友lin2009 给出的,理论结果是每个元素均为275000。
clear all
6 V" c3 C& }3 h+ e) O) M. M
clc
1 W+ X, R# T4 u" u1 N: I j
tic
$ c2 {9 D. q# B0 J
k = zeros(5,5); % //生成5×5全0矩阵
* i, A& ~' E% o6 _+ u1 H
% 循环计算以下程序段1000 00次:
; P. E# R. x& _$ I4 \) [! W( [* A
for m = 1:1000 00
5 _( m! z0 {) ^# q: C( _$ P
a = rand(5,7);
* h* r+ w$ ` g3 r2 u
b = rand(7,5);%//生成5×7矩阵a,7×5矩阵b,用0~1之间的随机数初始化
/ C/ T6 M$ Z. n6 L: y) ]* g
k = k + a * b + a(1:5, 2:6) * b(2:6, 1:5) - a(:, 7) * b(3, :);
' } a) ]# a2 Q# }" c. ^
end
( }" T# G6 f. f' j# ?: G; }" T) [
k
% }2 @4 j; h7 Y5 i% C( @' f j
toc
复制代码
( C+ Q* b b( i: x0 w
Forcal代码1:运行稍快的代码,比matlab约快10%吧?
$ ?/ K; s9 J9 N4 S6 D5 H! ]. E3 a
!using["math","sys"];
4 q( m; d" Z, b. f+ {; l
mvar:
& b" \# M- e3 j1 z
t0=clock(),
; w* x% ]2 C1 U) B
oo{k=zeros[5,5]},
2 T% Z9 u. ], b3 W# k3 r
i=0,((i++)<100000).while{
- N% f: j |& L( G j) h( v
oo{
& E" F- i4 T; M% [
a=rand[5,7], b=rand[7,5],
# I5 C8 s+ I! c& _" G$ a) O7 n8 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)]
0 L6 \ ?. [# h/ G+ j
}
. F$ l, e1 E( R0 g, |6 _6 V
},
! g4 e- [2 O- C; E* F u8 Q- m
k.outm(),
/ Z3 K. t# u- w" {
[clock()-t0]/1000;
复制代码
在我的电脑上运行时间为3.344秒。
# r+ S' B8 l) d% V4 R
8 |' |( s4 Q* h. t
Forcal代码2:比较好看些的代码,似乎也比matlab稍快吧?
$ p2 U3 D; N* o7 P
!using["math","sys"];
, {1 k7 C( ~$ j: A; |( w( E
(:t0,k,i,a,b)=
1 S/ K) s! a+ F( Y
{
# d% i$ A1 n" P( a3 r
t0=clock(),
0 V, ~1 E, H3 Z" z
oo{k=zeros[5,5]},
5 p( B9 E4 R J
i=0,((i++)<100000).while{
# N; o& W0 j& ~) H: I9 E
oo{
7 {: b' R: y, q- L$ L
a=rand[5,7], b=rand[7,5],
2 D* K& Z: P8 u2 }- l# f( I+ A* f
k.=k+a*b+a(0,4:1,5)*b(1,5:0,4)-a(neg:6)*b(3:neg)
2 J4 T9 R& j6 Q
}
4 B- |+ D$ ?$ q& L, i2 ?
},
1 v5 Y0 ?* F5 d/ {/ ]
k.outm(),
) a( M2 X- j9 n; ^" e3 V2 d
[clock()-t0]/1000
7 P6 V( l7 X; }& x
};
复制代码
在我的电脑上运行时间为3.579秒。
5 z f9 S$ b) W4 U
8 } e4 o% ~# P8 J; w& Y* m
例子2:
. a6 `4 [' x t3 |
一段程序的Forcal实现:
( R% C) T' t" s h7 m
//用C++代码描述为:
3 e+ p" j! T/ i. }! ~0 Y
s=0.0;
2 [" U0 W- W8 m1 P& q% W
for(x=0.0;x<=1.0;x=x+0.0011)
) ], f( T* @ r
{
% D$ w$ h9 }0 ~: K7 ~( q' `
for(y=1.0;y<=2.0;y=y+0.0009)
8 f7 Q) r0 V, R6 d& ?( Z; D
{
" q% R$ f: \ D: Y, u+ |
s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));
3 b- B' L& n" p7 ]5 [4 n: O4 N
}
- b+ f0 g$ h9 l! B; Q
}
复制代码
结果:
8 i, u9 c3 l* q" _
1008606.64947441
, M' H6 `1 E- k+ Y l% f: d
0.609 //时间
( `2 u: ?% I/ Q' m3 Z
$ I6 [( `: {" `! h+ @
这个matlab程序段是网友yycs001给出的。
3 _0 h$ _ ]1 S. w0 ^4 g' x. O
%file speedtest.m
4 {/ J$ u9 N' N
function speedtest
, [7 r; n- p# l2 t- O+ G" C
format long
7 l- A+ x; o# a* a8 M* o7 _
tic
6 C1 y% }3 O1 E' Y
[x,y]=meshgrid(0:0.0011:1,1:0.0009:2);
! L/ f! `" M7 L8 G6 J& I
s=sum(sum(cos(1-sin(1.2*x.^(y/2)+cos(1-sin(1.2*y.^(x/2)))))))
7 K0 L" L5 `) k" b0 t0 D' ?; }
toc
复制代码
9 `; d- b3 K3 T
Forcal代码1:**数组求和函数Sum,完全矢量化的代码
1 J. o5 u$ o6 p" [5 [7 N! W
!using["math","sys"];
* Z6 \. S- k r8 Q& j! d# O+ h& p* f
mvar:
; R6 ?+ e( E5 A8 C
t=clock(),
8 o' O6 {% y- e/ L& ?
oo{
# h. @$ s( a3 G4 P, z
ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],
# q3 r9 x6 r y( Q# 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]
$ g y$ M- _4 y: a. A* w
};
% e+ O: q6 c$ Q+ e) R
[clock()-t]/1000;
复制代码
结果:
( p$ k) T- W& B/ a- Q) A) ]2 _3 R
1008606.64947441
( d9 k* o7 v( E4 k% v4 G+ ^; h
0.625 //时间
9 J6 D. q5 o. M0 j5 M$ Y
: Z" U8 K" n8 ^5 D" k, W# c
或者这个,与上面效率差别不大:
% t9 I3 l% r9 P, \" v/ G- F- K
!using["math","sys"];
! H$ Q& n" k+ G: T5 v
mvar:
2 D! A9 m7 J% Q2 o4 H# w1 {# @
t=clock(),
6 C8 l1 s2 k8 N: I% D: b% u
oo{
; Y) C2 ]% B5 \, c6 N
ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],
# T y" d1 T/ S0 P6 j
Sum[Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2))))))]]
2 v& J' }" F/ y* t
};
& a* w% M/ p, Q4 ~1 K
[clock()-t]/1000;
复制代码
. h; k! j+ M F7 C, G* }- x
Forcal代码2:求和函数sum,非矢量化代码
7 h0 c" [3 N4 `- C) F9 w
f(x,y)=cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));
' U- }4 ?" ^/ |) ~% G( g* h/ ^
sum["f",0,1,0.0011,1,2,0.0009];
复制代码
结果:
4 c- y- ~* @. ~; P+ o/ p6 k: e" ~
1008606.64947441
2 L+ C. Q# d' `2 t
0.719 //时间
4 Y, Y5 ]. e) k! u9 o0 u2 g& {
# e" y# f0 [. W0 O
Forcal代码3:while循环
1 ?$ q) v4 {4 N: c% i( R# \6 w- l
mvar:
$ T% h% Y" E) @2 W& X( [
t=sys::clock();
, y! M5 X( R" r' M
s=0,x=0,
4 j* u+ s+ k; z0 C& ], `& n
while{x<=1, //while循环算法;
5 B5 G( n9 J' r, [* ]
y=1,
! ?; z/ t3 Q9 _2 b5 n. J% R5 \+ B
while{y<=2,
. J0 y2 h; a! b' A; C3 Q5 ]; S4 L& n3 @
s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))),
7 B4 w9 |/ P0 G; q+ J) o6 u, K+ ]! M
y=y+0.0009
) [0 v/ N/ ?: f, m8 E
},
, _: T% {, Q; U8 }
x=x+0.0011
& Q& D" w8 M8 O# G' r
},
( _5 s+ b- |3 {4 O6 g
s;
' ?. K: b( x& M5 k8 t! F3 a
[sys::clock()-t]/1000;
复制代码
结果:
4 r, p4 t7 R! D$ F( F2 O$ g: I( L
1008606.64947441
' ^' _9 B" \' k
0.734 //时间
5 j, k9 r+ w4 Y9 _# f2 @+ G
4 \* Q4 p1 I5 w& ~: e
大家可下载OpenFC进行测试:
http://www.forcal.net/xiazai/forcal9/openfc32w.rar
3 r& v2 I% j: v+ V0 g$ n
) s& p/ n2 X6 V6 t
注意Forcal的矢量化代码第一次运行有时效率较低。
5 D2 i/ l+ l7 r, P( q% \
( H+ E0 n5 b7 n. w" V
例子1中Forcal和matlab都是矢量化代码,但matlab跑不过Forcal。该例子的特点是函数调用频繁,临时变量生成多,但矩阵很小,矩阵的各种函数运行时耗时较少。故说明Forcal函数调用+变量管理效率优于matlab。
9 ?6 t4 r4 d* {5 E8 u; w
5 A1 u" T& C# o8 l- b
例子2中Forcal的矢量化代码是最快的,但与matlab的矢量化代码相比仍有差距。该例子的特点是函数调用少,临时变量也少,但矩阵大。故说明Forcal的各种矩阵函数Sin、Cos及矩阵的加减运算等函数的内部设计不及matlab。
8 ^ Y: t5 `+ m; m) `
" X$ U2 t5 d: S( R
如能在函数内部设计上下点功夫,例子2超越matlab也是可能的。在这方面,期待高手们的指点。
' {5 h# V' y' G: V; v* v, L
+ g4 C$ \" e) z( m3 p6 w
如果例子2速度也超越了matlab ,matlab矢量化的神秘面纱就揭开了。
3 D6 n* a! C4 h2 g6 @
- }; K7 {" v5 V5 H) t' L' G
顺便说一下,例子1如果用C++的运算符重载来实现,速度将比Forcal慢一些,也就是说,在涉及运算符重载时,脚本的效率有时比C++还要高些。
& @6 w8 P9 W! c) \$ F6 e
作者:
forcal
时间:
2010-10-16 16:59
讨论有益!以下是在其他论坛的讨论帖子:
& {+ V2 v* l4 b$ R+ x2 n# W
simwe:
http://forum.simwe.com/thread-952532-1-3.html
8 ]# F7 D5 a! j5 Z9 T6 }5 R" t
csdn:
http://topic.csdn.net/u/20101006/21/2ed9e5c1-cc9f-4623-b1c0-ebd5d1b5a98a.html
; V2 L! n; n4 d; T
cadn:
http://topic.csdn.net/u/20101010/15/3bcf2fe0-0abd-4c29-b854-b1d007b16863.html
! H- M" p8 f6 v/ Y5 h. \
作者:
forcal
时间:
2010-10-24 16:59
参考:
http://bbs.emath.ac.cn/thread-2709-1-1.html
& y* ^ t$ y% d4 c
0 ]& k2 j0 F7 D$ C/ k
我在多个帖子中有不同说明,但将这些说明再集中到一个帖子中比较麻烦,大家相互参考一下,看能否把这个问题解决了。
作者:
forcal
时间:
2010-11-2 18:06
参考:
http://bbs.emath.ac.cn/thread-2727-1-1.html
* ~1 q: j( Y( E# D% a0 [$ B! a
I2 D2 x. W. ?( C0 F' |5 |
关于最快速的矩阵乘实现的讨论。
2 J q; Q3 o/ s) {
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5