数学建模社区-数学中国
标题:
关于matlab代码矢量化的理解
[打印本页]
作者:
forcal
时间:
2010-10-5 09:32
标题:
关于matlab代码矢量化的理解
代码矢量化是matlab的精髓,其基本特点是运行速度快和代码简洁,它是如何实现的?
- T n+ k% }% b( Y- G: F4 j
1 ]: O. F/ O1 [" @6 O) g& ?. {3 U
按我的理解,代码矢量化的本质就是设计专门的函数对数组元素集中运算,这样可提高运行速度,同时兼有代码简洁的特点。
$ Z" @4 }- N! s" d
1 Q2 z/ d4 d r2 D: Z8 ~/ _
对matlab的理解比较肤浅,但也确实看不出有更深意义的东西,望解惑。
" }) _/ I) p0 a# }. n
1 z' [1 X& }+ i
大家有什么看法,愿畅所欲言。
5 u7 q+ a r: B& f
作者:
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 编辑
Z- ^* R8 T$ Q t& k
7 n+ J. s- F$ f" _' M# F* n. a
我正在练手设计的FcMath库也打算以矩阵运算为基础,设计一些专门的函数对数组元素集中运算,运行效率确实有所提高(甚至有些涉及矩阵的算法比matlab还快),代码也简洁了,但不知这是不是矢量化?
2 L) V- `$ y0 F F8 v, t0 N& R7 @
% l9 I! l8 K1 [& p0 @' L9 T- H
脚本运行效率应该取决于函数调度效率、对象管理效率和函数内部算法的实现。
* o" x3 [0 @& S+ ^
9 F/ {, g9 x3 y0 W
我感觉,matlab的函数调度效率较低,对象管理效率这个不好说,但一些函数内部的设计比较优秀。故有些Forcal代码比matlab快,而有些慢。
' g/ w; e/ n; S$ |
4 y( P+ Y8 W# w1 ^: t% e: z
以下例子体现了Forcal和matlab的效率差别所在。
, V5 a, Q3 k7 C) T9 W. T
1 a% K: Y9 k2 G
这个matlab程序段是网友lin2009 给出的,理论结果是每个元素均为275000。
clear all
; z( D! ^+ ]& r4 O D
clc
$ j: h2 X$ P- ~
tic
8 F+ L$ _! C" B, V
k = zeros(5,5); % //生成5×5全0矩阵
* @* t% S( c/ p+ f; G- l8 O3 Z
% 循环计算以下程序段1000 00次:
# R# ?% f- [7 o( Q
for m = 1:1000 00
9 w# B' e3 k* y
a = rand(5,7);
, {( D1 t3 N2 M
b = rand(7,5);%//生成5×7矩阵a,7×5矩阵b,用0~1之间的随机数初始化
, W! z2 e) u4 y( _. a- ~" |5 z4 ?
k = k + a * b + a(1:5, 2:6) * b(2:6, 1:5) - a(:, 7) * b(3, :);
8 F9 R: H! W" x y6 c! F$ ^
end
$ z5 F) Q7 s1 J9 N% a& j% ]
k
4 p6 i, N8 C/ ^5 i! q& |8 C( }
toc
复制代码
, y+ h* j3 S ^ x9 t
Forcal代码1:运行稍快的代码,比matlab约快10%吧?
* K" B& D0 `% ~8 Y
!using["math","sys"];
7 J% o9 o8 ]9 d( T, {
mvar:
- V W! G) z, G3 N- \4 `# _
t0=clock(),
) r- M7 q* p, M3 R# {- `
oo{k=zeros[5,5]},
6 ^! {* y# Y& T0 [1 B
i=0,((i++)<100000).while{
* H ~+ a& D. v1 `6 I Z8 d
oo{
0 a$ p9 z3 ~6 Z
a=rand[5,7], b=rand[7,5],
( x- i6 |" l& M, |3 N5 e8 C
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)]
1 n* k3 T& z$ u: F& B( ?. t
}
6 u' V" S) d# ?% K1 f7 o- o
},
4 ?& l! j' x8 ~7 j4 Y
k.outm(),
% U; r+ q$ g# Y" b% t4 _
[clock()-t0]/1000;
复制代码
在我的电脑上运行时间为3.344秒。
& ]# Y* D I/ t# g O
" ?$ f) f6 d8 G$ U+ ^
Forcal代码2:比较好看些的代码,似乎也比matlab稍快吧?
7 B" Q, _& D3 ?, }- ~
!using["math","sys"];
: T |; }$ y! u, D3 H7 j6 S
(:t0,k,i,a,b)=
: w$ q U3 b8 [9 k8 f6 O& G
{
5 H4 g$ o& ?9 r0 F; M1 S# Q
t0=clock(),
+ \+ r# j' b$ H8 w( H6 S3 y
oo{k=zeros[5,5]},
7 h( |% j5 Z) I- \" \8 Y* m
i=0,((i++)<100000).while{
- s/ K' P* j6 g( }" e
oo{
& g7 L5 }$ i$ w' b% @8 O! L. S. i
a=rand[5,7], b=rand[7,5],
: j9 a0 t' z o: m% h
k.=k+a*b+a(0,4:1,5)*b(1,5:0,4)-a(neg:6)*b(3:neg)
+ C6 u1 k" L2 ]3 x
}
" I% u8 q; J: S: t3 D: F& W6 h
},
, `- Z# M, r7 M: n8 q
k.outm(),
& _1 R8 e' [ H
[clock()-t0]/1000
: k! D1 C( ~/ z$ Y
};
复制代码
在我的电脑上运行时间为3.579秒。
p4 w+ u7 o" Y; T/ _
- h( J6 {; }4 ^* H" K0 q( y& s
例子2:
( q2 `, D$ Z% l4 N4 o" Z0 I
一段程序的Forcal实现:
0 ]0 T v6 C c0 J1 Z- e4 h0 [
//用C++代码描述为:
1 b2 l: W- H0 V' F9 a
s=0.0;
) N3 Z: b: r0 N, ^1 D* g5 z
for(x=0.0;x<=1.0;x=x+0.0011)
' `2 g" W3 K8 E' a" [. R7 u4 _% R
{
O# k# Z# n$ [' B& O$ W1 b
for(y=1.0;y<=2.0;y=y+0.0009)
( U0 Y I5 q* H7 I2 x1 l$ ?. T4 N
{
7 c+ o5 |" \$ J, P4 K
s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));
9 W, n! \3 m: A5 c) s# b0 u
}
8 [9 U W- \/ P" {
}
复制代码
结果:
% q; A4 \! ^7 R& K
1008606.64947441
) ~0 g, R% S+ Z' p! G
0.609 //时间
" h, a" c4 `0 h2 Z' g9 J9 `
/ c/ x2 F/ Q/ `, C' C
这个matlab程序段是网友yycs001给出的。
w3 U7 V. o, w( d2 w
%file speedtest.m
% T6 b$ d) n K- O4 k- s
function speedtest
# t3 h& X8 `+ Q0 B
format long
" Z* i* H7 i. x7 D5 J& Y1 C
tic
0 x I- J9 c' p6 o6 _+ t
[x,y]=meshgrid(0:0.0011:1,1:0.0009:2);
5 ?" _/ i$ W" b
s=sum(sum(cos(1-sin(1.2*x.^(y/2)+cos(1-sin(1.2*y.^(x/2)))))))
( P; G7 R% z. B p
toc
复制代码
. g$ Q" {$ p/ F1 t K4 ?, H. G
Forcal代码1:**数组求和函数Sum,完全矢量化的代码
1 o) e+ X$ Z+ P
!using["math","sys"];
' c& W" e" \: Z& d0 q% O
mvar:
$ N0 }9 C$ m& |; R2 m
t=clock(),
0 F) s! r1 ^; c+ V2 `
oo{
0 n/ Z! N$ |8 F; o! a( R9 E8 L b
ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],
, x+ `9 V0 Z+ @/ @# t
Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2)))))),0]
; [7 K7 v' ~1 {- I0 g
};
% M3 u) C2 ~( o g& d' Q8 l$ \! h: G
[clock()-t]/1000;
复制代码
结果:
1 n% n6 \7 ~; G1 q; L+ p& |
1008606.64947441
) e' c7 J% `" r4 T+ b0 [% I l8 e
0.625 //时间
# W9 Z+ J6 }* R6 ~% X7 m0 N
3 }' h# I0 v8 J' C7 b2 S
或者这个,与上面效率差别不大:
P* w' j) Y! x
!using["math","sys"];
`6 G6 l+ }3 H+ W
mvar:
9 Y, ?3 m% r- N4 ?
t=clock(),
# ?- j7 O/ J, M
oo{
3 p: j0 |7 d: Z5 g, m! d1 J# \
ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],
5 j8 D) S8 O& d3 R0 |' r! O. g
Sum[Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2))))))]]
: C3 \, o9 q r/ S/ m
};
& y- y+ J' }5 V" F4 \6 x
[clock()-t]/1000;
复制代码
* j) ~+ @$ G, Z8 }5 D
Forcal代码2:求和函数sum,非矢量化代码
! r. d z* H" _8 f
f(x,y)=cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));
8 N5 c9 l+ ?% k5 y. m; b& t
sum["f",0,1,0.0011,1,2,0.0009];
复制代码
结果:
- H6 r2 i* I9 v# A" C
1008606.64947441
+ ~( C2 M1 X) k G5 q
0.719 //时间
. q& T) r! }' L2 Z. E; Z
: Z- V K0 M; @& `/ [7 m3 [
Forcal代码3:while循环
% }6 I* S6 E3 B. y
mvar:
" _! d* N/ I! \3 {; I" j
t=sys::clock();
; r5 D u# R9 _% e$ N7 T5 Y
s=0,x=0,
/ D6 I7 ~4 G7 A
while{x<=1, //while循环算法;
" N8 w% B4 p+ n
y=1,
' F3 R- D: X$ ^
while{y<=2,
, p3 r6 E/ _( G1 Q
s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))),
! b8 _+ ~$ W7 U- w
y=y+0.0009
9 z# F ^' h& i7 l) K$ _' }5 h( i
},
7 }( y2 B; H; c" J3 ^/ n. e- w
x=x+0.0011
! i$ { t' _ U& ~- ~
},
& Y* `: ` U$ r* Q2 L
s;
0 g5 x* Z& g( u2 W. R) v2 p
[sys::clock()-t]/1000;
复制代码
结果:
6 I# [5 K4 ~+ T: L: [) ^& ?
1008606.64947441
7 B: z! r l# T! u8 |
0.734 //时间
5 v4 }5 ^* q0 t a' N/ r5 F
5 e* g$ m; i: t D% d- Q* D# W
大家可下载OpenFC进行测试:
http://www.forcal.net/xiazai/forcal9/openfc32w.rar
# I3 j7 Z4 m7 E
+ N. B8 n- W- [$ l
注意Forcal的矢量化代码第一次运行有时效率较低。
& \. ^' y) L- S+ w, U
3 \; `6 H8 U e, O! K
例子1中Forcal和matlab都是矢量化代码,但matlab跑不过Forcal。该例子的特点是函数调用频繁,临时变量生成多,但矩阵很小,矩阵的各种函数运行时耗时较少。故说明Forcal函数调用+变量管理效率优于matlab。
6 E+ c! V; Z3 p2 T" b1 s' l
; @- }3 C+ B6 m+ W1 l* f! t
例子2中Forcal的矢量化代码是最快的,但与matlab的矢量化代码相比仍有差距。该例子的特点是函数调用少,临时变量也少,但矩阵大。故说明Forcal的各种矩阵函数Sin、Cos及矩阵的加减运算等函数的内部设计不及matlab。
, L* `/ ^1 n: S8 g1 b
- c/ b$ _/ y9 u) z
如能在函数内部设计上下点功夫,例子2超越matlab也是可能的。在这方面,期待高手们的指点。
/ u) z7 G( `$ {4 O* m3 O, V
" H2 w8 O" ]) \" V" y
如果例子2速度也超越了matlab ,matlab矢量化的神秘面纱就揭开了。
9 O: K0 Z, t N! r' @' p
$ S) M9 P9 y2 k# t" f6 L( ^2 G
顺便说一下,例子1如果用C++的运算符重载来实现,速度将比Forcal慢一些,也就是说,在涉及运算符重载时,脚本的效率有时比C++还要高些。
* r" Y/ p$ A/ j+ V0 M' m( N0 U+ j
作者:
forcal
时间:
2010-10-16 16:59
讨论有益!以下是在其他论坛的讨论帖子:
) O# F! y4 D7 U1 M: c
simwe:
http://forum.simwe.com/thread-952532-1-3.html
. ?: i6 b0 L* a' }( |
csdn:
http://topic.csdn.net/u/20101006/21/2ed9e5c1-cc9f-4623-b1c0-ebd5d1b5a98a.html
* D+ L/ J c$ F S. b) r
cadn:
http://topic.csdn.net/u/20101010/15/3bcf2fe0-0abd-4c29-b854-b1d007b16863.html
2 H9 f6 ] }# l6 [# ?
作者:
forcal
时间:
2010-10-24 16:59
参考:
http://bbs.emath.ac.cn/thread-2709-1-1.html
0 p6 _5 [! v4 J3 }
- f- o; q5 ^' D
我在多个帖子中有不同说明,但将这些说明再集中到一个帖子中比较麻烦,大家相互参考一下,看能否把这个问题解决了。
作者:
forcal
时间:
2010-11-2 18:06
参考:
http://bbs.emath.ac.cn/thread-2727-1-1.html
2 m3 I6 y% g, I) v" D8 [5 e) W
6 v4 R# D" Z& {& n
关于最快速的矩阵乘实现的讨论。
& @5 ]5 S0 n% P: s) G, I
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5