forcal 发表于 2010-10-5 09:32

关于matlab代码矢量化的理解

代码矢量化是matlab的精髓,其基本特点是运行速度快和代码简洁,它是如何实现的?

按我的理解,代码矢量化的本质就是设计专门的函数对数组元素集中运算,这样可提高运行速度,同时兼有代码简洁的特点。

对matlab的理解比较肤浅,但也确实看不出有更深意义的东西,望解惑。

大家有什么看法,愿畅所欲言。

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 编辑

我正在练手设计的FcMath库也打算以矩阵运算为基础,设计一些专门的函数对数组元素集中运算,运行效率确实有所提高(甚至有些涉及矩阵的算法比matlab还快),代码也简洁了,但不知这是不是矢量化?

脚本运行效率应该取决于函数调度效率、对象管理效率和函数内部算法的实现。

我感觉,matlab的函数调度效率较低,对象管理效率这个不好说,但一些函数内部的设计比较优秀。故有些Forcal代码比matlab快,而有些慢。

以下例子体现了Forcal和matlab的效率差别所在。

这个matlab程序段是网友lin2009 给出的,理论结果是每个元素均为275000。clear all
clc
tic
k = zeros(5,5); % //生成5×5全0矩阵
% 循环计算以下程序段1000 00次:
for m = 1:1000 00
    a = rand(5,7);
    b = rand(7,5);%//生成5×7矩阵a,7×5矩阵b,用0~1之间的随机数初始化
    k = k + a * b + a(1:5, 2:6) * b(2:6, 1:5) - a(:, 7) * b(3, :);
end
k
toc
Forcal代码1:运行稍快的代码,比matlab约快10%吧?
!using["math","sys"];
mvar:
t0=clock(),
oo{k=zeros},
i=0,((i++)<100000).while{
  oo{
    a=rand, b=rand,
    k.oset
  }
},
k.outm(),
/1000;在我的电脑上运行时间为3.344秒。

Forcal代码2:比较好看些的代码,似乎也比matlab稍快吧?
!using["math","sys"];
(:t0,k,i,a,b)=
{
  t0=clock(),
  oo{k=zeros},
  i=0,((i++)<100000).while{
    oo{
      a=rand, b=rand,
      k.=k+a*b+a(0,4:1,5)*b(1,5:0,4)-a(neg:6)*b(3:neg)
    }
  },
  k.outm(),
  /1000
};在我的电脑上运行时间为3.579秒。

例子2:
一段程序的Forcal实现:
//用C++代码描述为:
s=0.0;  
for(x=0.0;x<=1.0;x=x+0.0011)  
{
  for(y=1.0;y<=2.0;y=y+0.0009)
  {
  s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));
  }
}  结果:
1008606.64947441
0.609 //时间

这个matlab程序段是网友yycs001给出的。
%file speedtest.m
function speedtest
format long
tic
=meshgrid(0:0.0011:1,1:0.0009:2);
s=sum(sum(cos(1-sin(1.2*x.^(y/2)+cos(1-sin(1.2*y.^(x/2)))))))
toc
Forcal代码1:**数组求和函数Sum,完全矢量化的代码
!using["math","sys"];
mvar:
t=clock(),
oo{
  ndgrid,
  Sum
};
/1000;结果:
1008606.64947441
0.625 //时间

或者这个,与上面效率差别不大:
!using["math","sys"];
mvar:
t=clock(),
oo{
  ndgrid,
  Sum]
};
/1000;
Forcal代码2:求和函数sum,非矢量化代码
f(x,y)=cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2)))));
sum["f",0,1,0.0011,1,2,0.0009];结果:
1008606.64947441
0.719 //时间

Forcal代码3:while循环
mvar:
t=sys::clock();
s=0,x=0,
while{x<=1,  //while循环算法;
   y=1,
   while{y<=2,
       s=s+cos(1-sin(1.2*x^(y/2)+cos(1-sin(1.2*y^(x/2))))),
       y=y+0.0009
      },
   x=x+0.0011
},
s;
/1000;结果:
1008606.64947441
0.734 //时间

大家可下载OpenFC进行测试:http://www.forcal.net/xiazai/forcal9/openfc32w.rar

注意Forcal的矢量化代码第一次运行有时效率较低。

例子1中Forcal和matlab都是矢量化代码,但matlab跑不过Forcal。该例子的特点是函数调用频繁,临时变量生成多,但矩阵很小,矩阵的各种函数运行时耗时较少。故说明Forcal函数调用+变量管理效率优于matlab。

例子2中Forcal的矢量化代码是最快的,但与matlab的矢量化代码相比仍有差距。该例子的特点是函数调用少,临时变量也少,但矩阵大。故说明Forcal的各种矩阵函数Sin、Cos及矩阵的加减运算等函数的内部设计不及matlab。

如能在函数内部设计上下点功夫,例子2超越matlab也是可能的。在这方面,期待高手们的指点。

如果例子2速度也超越了matlab ,matlab矢量化的神秘面纱就揭开了。

顺便说一下,例子1如果用C++的运算符重载来实现,速度将比Forcal慢一些,也就是说,在涉及运算符重载时,脚本的效率有时比C++还要高些。

forcal 发表于 2010-10-16 16:59

讨论有益!以下是在其他论坛的讨论帖子:
simwe:http://forum.simwe.com/thread-952532-1-3.html
csdn:http://topic.csdn.net/u/20101006/21/2ed9e5c1-cc9f-4623-b1c0-ebd5d1b5a98a.html
cadn:http://topic.csdn.net/u/20101010/15/3bcf2fe0-0abd-4c29-b854-b1d007b16863.html

forcal 发表于 2010-10-24 16:59

参考:http://bbs.emath.ac.cn/thread-2709-1-1.html

我在多个帖子中有不同说明,但将这些说明再集中到一个帖子中比较麻烦,大家相互参考一下,看能否把这个问题解决了。

forcal 发表于 2010-11-2 18:06

参考:http://bbs.emath.ac.cn/thread-2727-1-1.html

关于最快速的矩阵乘实现的讨论。
页: [1]
查看完整版本: 关于matlab代码矢量化的理解