数学建模社区-数学中国

标题: 关于matlab代码矢量化的理解 [打印本页]

作者: forcal    时间: 2010-10-5 09:32
标题: 关于matlab代码矢量化的理解
代码矢量化是matlab的精髓,其基本特点是运行速度快和代码简洁,它是如何实现的?
3 h" C6 C. s$ N4 [, o2 s! ]. `" x  ~
按我的理解,代码矢量化的本质就是设计专门的函数对数组元素集中运算,这样可提高运行速度,同时兼有代码简洁的特点。; P3 G1 N. c' U$ |
8 a0 m# ^+ B) V0 U6 ?3 r! R/ _
对matlab的理解比较肤浅,但也确实看不出有更深意义的东西,望解惑。% N6 f, j3 @; j; G9 ~
* p3 k; G# K* t/ O" ?- U
大家有什么看法,愿畅所欲言。
! C7 C, l5 N; M* \/ ^4 H* Z
作者: 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 编辑
6 P, i3 Y8 V4 ~
% X& c( C" b7 M6 G7 u我正在练手设计的FcMath库也打算以矩阵运算为基础,设计一些专门的函数对数组元素集中运算,运行效率确实有所提高(甚至有些涉及矩阵的算法比matlab还快),代码也简洁了,但不知这是不是矢量化?
5 |0 e9 v8 D  o7 p
" P0 s7 F5 z, ^8 v' o1 m# J# m; \3 t脚本运行效率应该取决于函数调度效率、对象管理效率和函数内部算法的实现。
0 |6 J4 }' o4 s, ^6 D2 L! x$ x. K2 ~+ o" O+ F
我感觉,matlab的函数调度效率较低,对象管理效率这个不好说,但一些函数内部的设计比较优秀。故有些Forcal代码比matlab快,而有些慢。
4 s6 _3 [8 t% t' t
, z! E, Z  F9 x. X5 h: U5 Y  b! p, g以下例子体现了Forcal和matlab的效率差别所在。- u. Q5 \: E) z0 M) ?5 Q% n
5 u& X4 ?6 Y0 v) U2 t
这个matlab程序段是网友lin2009 给出的,理论结果是每个元素均为275000。
  1. clear all' r) [& }  ~8 b" n! ]) P# [
  2. clc
    6 F5 o6 C, }1 x4 V
  3. tic
    * ^( H; f0 ~& V' ]5 h9 U: v$ o" [
  4. k = zeros(5,5); % //生成5×5全0矩阵
    1 i5 ^& }# h( p( T* c) z' W8 ]
  5. % 循环计算以下程序段1000 00次:6 r' p; e( j: c7 C7 F. b4 @
  6. for m = 1:1000 00
    . a1 E4 l. J2 j$ L
  7.     a = rand(5,7);
    9 P0 a0 ^7 \2 [! h9 p
  8.     b = rand(7,5);%//生成5×7矩阵a,7×5矩阵b,用0~1之间的随机数初始化
    % A+ u5 U* X: K/ `" Z2 B
  9.     k = k + a * b + a(1:5, 2:6) * b(2:6, 1:5) - a(:, 7) * b(3, :);  ~% Q7 J& L6 j: a& \6 \! b. Z
  10. end& w* s. S; z4 V. Q! V' e- _
  11. k7 `; }% j$ v: b' ~4 G
  12. toc
复制代码

* v( W; k5 h- r1 S" D% d# qForcal代码1:运行稍快的代码,比matlab约快10%吧?
- p. [+ d. @$ N' V
  1. !using["math","sys"];
    : o; L3 z! [9 _: W2 ~9 S
  2. mvar:
    5 F( Z& q0 U8 a9 i6 ]' U
  3. t0=clock(),% x3 Q1 u1 m% S3 t1 D3 T
  4. oo{k=zeros[5,5]},
    ( `. \, e! L* t. o" B1 b
  5. i=0,((i++)<100000).while{+ F% Q4 W- g0 q+ _6 A. D' Z
  6.   oo{
    1 L, J6 J# Y8 F2 ]; Y8 ^
  7.     a=rand[5,7], b=rand[7,5],. D8 j0 m4 p1 k, ~, W, B% N
  8.     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)]
    & o+ }% I" t) _4 i# I) X) b" u
  9.   }
    , z5 }% t* n  |( Z+ D2 }
  10. },! I  F; a4 P9 c4 o# ?, M/ r: p& Q
  11. k.outm(),
    * E! e& }( n9 N7 b% T, \" L
  12. [clock()-t0]/1000;
复制代码
在我的电脑上运行时间为3.344秒。9 s* w4 ?# [# R) {

: ?$ p1 p6 W6 A* v! U0 @" P& e: ~* ZForcal代码2:比较好看些的代码,似乎也比matlab稍快吧?
/ q) a- o' O% M& D
  1. !using["math","sys"];
    0 l, k3 J. _  z+ `$ G2 i- U, h8 Q8 a
  2. (:t0,k,i,a,b)=1 x* r% H) f+ e( f
  3. {
      K6 X$ S# e3 V, ^8 y+ l0 r' ?
  4.   t0=clock(),
    # ~3 E# ^5 R' q3 b  J  ?
  5.   oo{k=zeros[5,5]},
    % l9 ^- |% p* m/ l- y5 L+ J
  6.   i=0,((i++)<100000).while{7 C8 t6 B2 i1 z1 N! W/ a
  7.     oo{
    3 `3 D- ~2 Y  J  r7 h  C+ k9 l) q
  8.       a=rand[5,7], b=rand[7,5],/ v" {  z5 M0 j2 J4 X& e5 o
  9.       k.=k+a*b+a(0,4:1,5)*b(1,5:0,4)-a(neg:6)*b(3:neg)9 `" a- X9 E" l& {
  10.     }( U( o: \3 p; O
  11.   },& N1 Y  E/ G" j, `" g
  12.   k.outm(),
    # w# i& D5 u- R. v
  13.   [clock()-t0]/1000
    2 @2 @+ o# v: G
  14. };
复制代码
在我的电脑上运行时间为3.579秒。9 X/ I: X, `+ ^- {: Z1 w
' `: b$ t% F% L9 w1 x* C
例子2:
1 r- o6 [# p3 k一段程序的Forcal实现:, R& ?% G2 U% ^' i, K
  1. //用C++代码描述为:
    * Q- @7 E  _; y# _
  2. s=0.0;  
    4 z8 p' G" N8 z
  3. for(x=0.0;x<=1.0;x=x+0.0011)  5 q8 O5 p2 H- r5 i
  4. {3 @, u0 D2 k/ d, t5 w
  5.   for(y=1.0;y<=2.0;y=y+0.0009)! ?: D* _9 }8 y& d8 q0 }
  6.   {+ d$ s4 J. V& A& ~3 q2 E/ [( S! v
  7.   s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));% F; C5 \* |( Z5 j
  8.   }
    8 T2 G, V0 H- N# k* \# Z
  9. }  
复制代码
结果:
, k4 F% V) d- D8 d$ B1008606.64947441- z! u" c9 |" W
0.609 //时间
; A, [/ ^+ O3 i& G+ A0 H& |1 L3 k- E0 x$ O% A
这个matlab程序段是网友yycs001给出的。
; l0 @+ q  o! f, ^, R
  1. %file speedtest.m, t' u0 r. \+ B# z4 y; K
  2. function speedtest) G5 D" c, z9 K% C
  3. format long9 {' y0 O- W- x- |% u! L, v. n
  4. tic, u! [8 q4 Q5 }
  5. [x,y]=meshgrid(0:0.0011:1,1:0.0009:2);
    * y, A4 Q5 o$ h% ~6 H( I
  6. s=sum(sum(cos(1-sin(1.2*x.^(y/2)+cos(1-sin(1.2*y.^(x/2)))))))- a8 W  |# s9 @0 ?- |1 J, B
  7. toc
复制代码
3 ]0 b5 F, H( e$ a0 p$ K
Forcal代码1:**数组求和函数Sum,完全矢量化的代码
+ X* u( z3 P: ]; {, X: q$ G
  1. !using["math","sys"];
    - Z6 Q# T! w: X( F& B. G
  2. mvar:
    9 f. w( ~6 {' e
  3. t=clock(),
    . f- j, ~* A+ W% U
  4. oo{
    3 J6 }( n! L) |5 J7 Z. h
  5.   ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],
    # I& n  W, h" d2 C1 U7 a0 u$ \
  6.   Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2)))))),0]
    4 h- v7 o/ }1 ^# R  E
  7. };
    ! q5 C5 a2 @% W; `, ~+ D
  8. [clock()-t]/1000;
复制代码
结果:
5 @( g# `2 d3 B2 d! h) Y7 ?% U5 O: C! [1008606.64947441
3 V2 E" N1 u# o9 f. C  _0.625 //时间# u1 A  q' m( f! v5 v* T- x7 r
1 i- X2 w/ |% i( q2 \
或者这个,与上面效率差别不大:. y( K% E. X) J9 [( w/ A2 ]
  1. !using["math","sys"];9 }0 z" a6 e% c$ t
  2. mvar:5 u9 B& R' y5 L* V+ Y2 |  t5 A
  3. t=clock(),0 Z/ C; t, X. X) g. ~5 m! _, F
  4. oo{
    0 i9 l7 E* F! o4 A5 U
  5.   ndgrid[linspacex(0,1,0.0011),linspacex(1,2,0.0009),&x,&y],
    ! c5 k$ c0 Y% ?  o; H7 @
  6.   Sum[Sum[Cos(rn(1)-Sin(rn(1.2)*x^(y/rn(2))+Cos(rn(1)-Sin(rn(1.2)*y^(x/rn(2))))))]]
    ; ]& Q: S& z; R- W5 v
  7. };( a% i& W" f$ J# J' Q8 q( c% U8 b
  8. [clock()-t]/1000;
复制代码
  O) u  X$ n# C" [3 E
Forcal代码2:求和函数sum,非矢量化代码
% p' g: N  y2 T" k2 X0 T" A
  1. f(x,y)=cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));
    ) h1 b+ @% D$ d# G! Y8 i
  2. sum["f",0,1,0.0011,1,2,0.0009];
复制代码
结果:7 M: _# W( n  n' e! v  l
1008606.64947441
1 \9 [8 S: [* e  ~# Y; W0.719 //时间+ a9 G7 k* d5 @9 J1 @9 Q+ q
! d  p% u" k" z$ b
Forcal代码3:while循环9 c' A1 x/ M7 H( c8 {, U# I+ \0 E
  1. mvar:
    ( q9 q+ D6 P7 D6 G8 m. M; B
  2. t=sys::clock();/ ~2 F* D0 x* E% b. [/ o
  3. s=0,x=0, 8 L' o$ G; t1 ^) _
  4. while{x<=1,  //while循环算法;
    % p0 `7 g5 H8 F  I; {
  5.    y=1, 8 R  y, L: F# k; |! l9 W, T( O
  6.    while{y<=2, ; k3 Z' B& `2 ]7 B. b: w
  7.        s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))),
    . X' t3 [0 A8 S" x( W- U4 q  F
  8.        y=y+0.0009
    1 j8 m/ ?6 j- B
  9.       }, $ c2 L! j4 q$ {& m
  10.    x=x+0.0011 6 {* t2 p: `/ M( Z
  11. }, 3 H; c/ D6 r" f9 @" V2 @$ {
  12. s;! O5 U1 c0 N2 z; O! b# _
  13. [sys::clock()-t]/1000;
复制代码
结果:
0 J2 t% `8 ?. \: Y9 h& K5 V1008606.64947441
3 G% Z1 V& d3 k# U/ |3 U0.734 //时间% V& Q3 c* k8 o; V2 @
' j6 c! z/ r3 i0 s' l8 i* E" n
大家可下载OpenFC进行测试:http://www.forcal.net/xiazai/forcal9/openfc32w.rar' ~4 }! M7 `" Z9 @( M: R$ N
; b  A+ y0 }1 [5 K
注意Forcal的矢量化代码第一次运行有时效率较低。. D& |- R1 c  d* h. t' Z8 j

  n; P) P5 b: v+ X! ]例子1中Forcal和matlab都是矢量化代码,但matlab跑不过Forcal。该例子的特点是函数调用频繁,临时变量生成多,但矩阵很小,矩阵的各种函数运行时耗时较少。故说明Forcal函数调用+变量管理效率优于matlab。
4 M8 ~* d- m2 L! p" A) U! {" Q2 d4 ~. ~* j7 l; F& \5 y# k1 s: m* o
例子2中Forcal的矢量化代码是最快的,但与matlab的矢量化代码相比仍有差距。该例子的特点是函数调用少,临时变量也少,但矩阵大。故说明Forcal的各种矩阵函数Sin、Cos及矩阵的加减运算等函数的内部设计不及matlab。% Z4 M0 e3 e, q; S  [+ Y; i+ b

2 V4 Z4 q4 Q2 o如能在函数内部设计上下点功夫,例子2超越matlab也是可能的。在这方面,期待高手们的指点。
/ h, f+ B0 i8 ?4 j0 Y
& y$ s+ P! E3 l: y8 `如果例子2速度也超越了matlab ,matlab矢量化的神秘面纱就揭开了。  C9 d/ D$ a8 s9 {0 t. j
3 l$ q( ~9 t& ~: y; B7 _6 U
顺便说一下,例子1如果用C++的运算符重载来实现,速度将比Forcal慢一些,也就是说,在涉及运算符重载时,脚本的效率有时比C++还要高些。
- ~0 B' ?. ^+ s7 {

作者: forcal    时间: 2010-10-16 16:59
讨论有益!以下是在其他论坛的讨论帖子:
' |0 M8 T  L7 v; t( Osimwe:http://forum.simwe.com/thread-952532-1-3.html) ]9 A4 y; Z* y9 `% g2 Q4 H
csdn:http://topic.csdn.net/u/20101006/21/2ed9e5c1-cc9f-4623-b1c0-ebd5d1b5a98a.html
/ m9 f7 p. i+ E9 M+ x+ y$ N2 Qcadn:http://topic.csdn.net/u/20101010/15/3bcf2fe0-0abd-4c29-b854-b1d007b16863.html
5 l1 v: s& k0 U' C$ g" V! q0 @
作者: forcal    时间: 2010-10-24 16:59
参考:http://bbs.emath.ac.cn/thread-2709-1-1.html
( m4 T! c- J6 [+ p
+ W0 n3 C5 @7 f$ i) |3 }我在多个帖子中有不同说明,但将这些说明再集中到一个帖子中比较麻烦,大家相互参考一下,看能否把这个问题解决了。
作者: forcal    时间: 2010-11-2 18:06
参考:http://bbs.emath.ac.cn/thread-2727-1-1.html
: n* [$ s0 i) |
0 p! |* H% f. o7 ~* \- h- X关于最快速的矩阵乘实现的讨论。
- K+ F2 l" F- A; ?( F




欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5