Matlab中用类封装函数
上次大规模使用Matlab还是本科的时候,当时还是5.3版,现在重新尝试它,已经是7.8(R2009a),而且R2010b版都已经发售。而这些版本引入的一个新玩意儿便是面向对象化编程(object-oriented programming,OOP)。
使用类(class)有很多好处,其中一个重要的好处便是解决变量名冲突和让函数、对象的结构清晰。class的static function可以在不定义类的实例直接调用类的成员函数,比如定义
classdef tools < handle methods (Static = true) function a = test(b, c) a = b + c; end end end
然后可以直接通过
a = tools.test(b, c);
调用test函数。这样做的好处是解决test的变量名冲突问题,而且可以将类似的函数封装到一块,使得函数结构显示层次化。
但这样做是有代价的,其中一个便是效率问题,假设还有一个完全一样的用普通m文件定义的test函数,下面两段代码测试了这两者各运行一百万次所需的时间:
tic for i = 1:1000000, test(i, i); end toc tic for i = 1:1000000, tools.test(i, i); end toc
那么普通函数的百万次调用的时间开销约0.25秒,而封装后的函数的百万次调用的时间开销高达14.5秒,相差约70倍。而且如果通过class的实例来调用,所需要的时间更长,下面这段代码显示百万次调用需要22.5秒。
t = tools; tic for i = 1:1000000, t.test(i, i); end toc
所以到底该不该封装,还需取决于实际情况,如果函数本身特别简单,并且会被循环调用,最好还是通过m文件函数的形式。之前MIT大牛给出了更多地建议
- 虽然for-loop的速度有了很大改善,vectorization(向量化)仍旧是改善效率的重要途径,尤其是在能把运算改写成矩阵乘法的情况下,改善尤为显著。
- 在不少情况下,for-loop本身已经不构成太大问题,尤其是当循环体本身需要较多的计算的时候。这个时候,改善概率的关键在于改善循环体本身而不是去掉for-loop。
- MATLAB的函数调用过程(非built-in function)有显著开销,因此,在效率要求较高的代码中,应该尽可能采用扁平的调用结构,也就是在保持代码清晰和可维护的情况下,尽量直接写表达式和利用built-in function,避免不必要的自定义函数调用过程。在次数很多的循环体内(包括在cellfun, arrayfun等实际上蕴含循环的函数)形成长调用链,会带来很大的开销。
- 在调用函数时,首选built-in function,然后是普通的m-file函数,然后才是function handle或者anonymous function。在使用function handle或者anonymous function作为参数传递时,如果该函数被调用多次,最好先用一个变量接住,再传入该变量。这样,可以有效避免重复的解析过程。
- 在可能的情况下,使用numeric array或者struct array,它们的效率大幅度高于cell array(几十倍甚至更多)。对于struct,尽可能使用普通的域(字段,field)访问方式,在非效率关键,执行次数较少,而灵活性要求较高的代码中,可以考虑使用动态名称的域访问。
- 虽然object-oriented从软件工程的角度更为优胜,而且object的使用很多时候很方便,但是MATLAB目前对于OO的实现效率很低,在效率关键的代码中应该慎用objects。
- 如果需要设计类,应该尽可能采用普通的property,而避免灵活但是效率很低的dependent property。如非确实必要,避免重载subsref和subsasgn函数,因为这会全面接管对于object的接口调用,往往会带来非常巨大的开销(成千上万倍的减慢),甚至使得本来几乎不是问题的代码成为性能瓶颈。
doubanclaim43f1a75046c8210a
Q.E.D., ©zhiqiang, 2010.09.24。请参考右边的相关文章列表。
原来大家都关注大牛Dahua的Blog。。还有大牛您老的Blog~~~ ;-)
zeros 预分配内存空间也能大幅提高效率,不过这个已经是常识了
今天碰到这个问题,但数组是字符串型的,这个该如何预分配内存?
为啥你回复我的时候系统没发邮件?
字符串型的么,就用 cell 初始化吧
我后来知道一个权宜方法,也不够完美:
你说的用cell初始化是怎么弄?
btw,这里不是每条回复都会发送邮件,只有我觉得有必要的时候(比如留言者问了个问题),我在回复时会勾选上邮件通知。
cell是初始化cell型的啊,a=cell(1000,1000);