300 likes | 510 Views
怎样提高 matlab 的效率. 王睿智 2011 年 4 月 15 日. 作业总结. 总结一. 一维矩阵代替多维矩阵 多维矩阵的 访问要比一 维矩阵要 慢,比如 bwlabel 里要记录每列的包的编号、开始行号、结束行号、所在列号、所在组号,如果使用五个 1 * n 的矩阵要比使用一个 5 * n 的矩阵要快近 4 近四倍。. 总结二. 给数组或矩阵预分配内存 特别是使用大型数组或矩阵时, Matlab 进行动态内存分配和取消时,可能会产生内存碎片,这将导致大量闲置内存产生,预分配可通过提前给大型数据结构预约足够空间来避免这个问题。 . 总结三.
E N D
怎样提高matlab的效率 王睿智 2011年4月15日
总结一 一维矩阵代替多维矩阵 多维矩阵的访问要比一维矩阵要慢,比如bwlabel里要记录每列的包的编号、开始行号、结束行号、所在列号、所在组号,如果使用五个1*n的矩阵要比使用一个5*n的矩阵要快近4近四倍。
总结二 给数组或矩阵预分配内存 特别是使用大型数组或矩阵时,Matlab进行动态内存分配和取消时,可能会产生内存碎片,这将导致大量闲置内存产生,预分配可通过提前给大型数据结构预约足够空间来避免这个问题。
总结三 用函数代替脚本文件因为每次调用MATLAB的脚本文件都需要将不必要的中间变量加载到内存中,每执行一次,就加载一次。函数在调用时被编译成了伪代码,只需要加载到内存一次。当多次调用同一个函数时会运行快一些。因此尽量多使用函数文件而少使用脚本文件,也是提高执行效率的一种方法。
总结四 注意Matlab的传参方式 Matlab的函数只有传值调用,因此会产生副本,开销很大,比如我第一次用深搜写bwlabel时,速度慢得像死机。。。 所以有时候不得不使用参数的值时,最好设定全局变量。 注:如果该参数在函数内部没有被修改,那么在实现时,它实质上用的是传引用调用(call by reference。所以有时候也不用过于担心参数传递的问题。
循环矢量化 Matlab是为矢量和矩阵操作而设计的,因此,可以通过矢量化方法加速M文件的运行。矢量化是指将for循环和while循环转换为等价的矢量或矩阵操作。 i=0;for n = 0:0.1:1000 i=i+1; y(i)=cos(n);end那么我们可以矢量化为:n= 0:0.1:1000;y=cos(n);
多重循环 在必须使用多重循环的情况下,如果两个循环执行的次数不同,则建议在循环的外环执行循环次数少的,内环执行循环次数多的。这样也可以显著提高速度。
问题 输入:一个1000000 x 1 的矩阵u 输出:一个 1000000 x 1 的矩阵v,且v(i)=u(i)+ 1
build-in function matlab自带的函数,多用c或fortran编写,算法考究,效率很高,熟练使用不仅能精简代码,也能保证一定的效率
m-file function 自己定义的函数 function y = fm(x) y = x + 1; 在调用时 for i = 1 : n v(i) = fm(u(i)); end
function handle 就是用@来把一个function赋到一个变量上,类似于C/C++的函数指针,或者C#里面的delegate的作用 fh = @fm; for i = 1 : n v(i) = fh(u(i)); end
anonymous function anonymous function是一种便捷的语法来构造简单的函数,类似于LISP, Python的lambda表达式 fa= @(x) x + 1; for i = 1 : n v(i) = fa(u(i)); end
inline function inline function是一种传统的通过表达式字符串构造函数的过程 fi = inline('x + 1', 'x'); for i = 1 : n v(i) = fi(u(i)); end
feval feval的好处在于可以以字符串方式指定名字来调用函数,当然它也可以接受别的参数。 v(i) = feval_r('fm', u(i)); v(i) = feval_r(fh, u(i)); v(i) = feval_r(fa, u(i));
分析一 m-function慢于直接计算过程 function handle和anonymous function的开销比使用普通的m-函数要高一些。这可能是由于涉及到句柄解析的时间,而普通的函数在第一次运行前已经在内存中进行预编译。 inline function的运行时间难以接受,这是因为matlab是在每次运行时临时对字符串表达式(进行parse。
分析二 feval_r(@fm, u(i)) > feval_r(fh, u(i)) 所以预先用一个变量把句柄接下,其效果就是预先完成了句柄解析,而如果直接把@fm写在参数列上,虽然写法简洁一些,但是解析过程是把参数被赋值到所调函数的局部变量时才进行,每调用一次解析一次,造成了巨大的开销。 feval_r('fm', u(i)) > feval_r(fh, u(i)) 因为这涉及到对函数进行搜索的时间
总结 Matlab支持多种函数调用方式,一般来说,函数调用一般按如下顺序选择: build-in function m-filefunction function handle anonymous function
matlab的集中数据访问方式 array-index A(i): cell-index: C{i}; structfield: S.fieldname structfield (dynamic): S.('fieldname')
cell array 元胞数组是MATLAB的一种特殊数据类型,可以将元胞数组看做一种无所不包的通用矩阵,或者叫做广义矩阵。组成元胞数组的元素可以是任何一种数据类型的常数或者常量,每一个元素也可以具有不同的尺寸和内存占用空间,每一个元素的内容也可以完全不同,所以元胞数组的元素叫做元胞(cell)。和一般的数值矩阵一样,元胞数组的内存空间也是动态分配的。
cell array >> a={'matlab',20;ones(2,3),1:10}a = 'matlab' [ 20] [2x3 double] [1x10 double]
分析 MATLAB对于单个数组元素或者静态的struct field的访问,可以达到不错的速度。而cell array的访问则明显缓慢,约每秒400万次(慢了50倍)。MATLAB还支持灵活的使用字符串来指定要访问域的语法(动态名字),但是,是以巨大的开销为代价的,比起静态的访问慢了200倍以上。
虽然object-oriented从软件工程的角度更为优胜,而且object的使用很多时候很方便,但是MATLAB目前对于OO的实现效率很低,在效率关键的代码中应该慎用objects。虽然object-oriented从软件工程的角度更为优胜,而且object的使用很多时候很方便,但是MATLAB目前对于OO的实现效率很低,在效率关键的代码中应该慎用objects。