如何提高MATLAB运行效率(1)
在我们的领域,MATLAB是进行实验的最主要的工具之一。我听到过很多抱怨说MATLAB很慢,可是
这往往不是MATLAB的问题,而是因为自己程序没有写好。MATLAB是我非常欣赏的一种语言,堪称
灵活易用和高效运算的结合典范。
作为解释语言,MATLAB进行高效运算的秘诀有几个方面:
(1) JIT即时编译技术。Matlab在第一次加载运行一个函数的时候,会在后台对它进行某种程度
的编译和优化,使得后续运行更快。因此,除了第一次运行需要进行语句解释之外,后面运行的
其实是已经放在内存中的经过优化的中间码。所以,很多时候我们可能会看到第一次运行一个新
函数,比它后面几次的运行明显慢一些。不过目前的JIT技术还不是非常成熟,和标准的编译语
言相比还有相当差距,仅凭这个MATLAB还不能称为高效。
(2) 向量化(Vectorization)。这是MATLAB最著名的特色。向量化配合经过高度优化的数值运算
引擎,是其高效运算的最重要的基石——很多MATLAB的使用者都明白这一点。能够转化成矩阵操
作的规则运算过程,使用MATLAB计算远比自己手工用C/C++实现高效。我自己做过很多次对比
profile,MATLAB在关键的核心运算上的实现可以比自己用C/C++按照标准的routine进行实现快
几十倍。
其实这不完全是MATLAB的功劳,其实MATLAB是建基于BLAS和LAPACK等的基础数学运算包的基础上
的。Intel和AMD都发布了这些东西的vendor-implementation,并且针对各自的CPU进行了大量的
优化,这非个人之力所能企及。因此,我从来都强烈不建议个人用C/C++去实现数值运算的关键
代码(学习数值分析课者除外)。
不过,对于向量化这个事情,也不宜极端化,下面的一些例子说明在哪些时候,for-loop比
vectorization更适合:
(a) 粗粒度的算法流程控制。比如,你要实现一个迭代算法,循环做一个事情直到收敛。只要循
环几次或者几十次,但是每个循环内部要进行大量的复杂运算,那么你就没有必要费心把这层循
环给vectorize掉了。除非收敛结果有某种close-form的解析解。
(b) 如果向量化可能导致产生巨型矩阵,则使用前要三思!很多情况下,向量化是一种用空间换
时间的行为,就是通过把数据组织成某种方式,从而使得内建的高效引擎能得以应用。但是,有
些时候要处理大量的数据,可能导致其组织过程需要耗费额外的数百兆乃至千兆内存空间,那么
这有可能造成效率的不升反降。原因有几个方面:
第一,数据组织过程也是需要时间的,最起码它也需要大量的操作进行密集的内存读写和用于定
位的偏移量计算。这方面增加的时间 vs. 向量化节省的运算时间,孰轻孰重,需要衡量。
第二,分配额外的大块内存是一件非常耗时的事情,它可能导致虚拟内存的使用,那么当对这块
矩阵进行读写和计算时可能涉及频繁的内存与外存交换区的I/O,这回造成效率的严重下降。我
一直不赞同在Out of Memory的情况下,通过增大虚存来解决问题,这样,即使你勉强让程序能继
续运行下去,运行时间也会变得极为缓慢——这时应该做的是对程序进行重新思考和设计,降低
其对内存的耗用。