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大牛给出了更多地建议

  1. 虽然for-loop的速度有了很大改善,vectorization(向量化)仍旧是改善效率的重要途径,尤其是在能把运算改写成矩阵乘法的情况下,改善尤为显著。
  2. 在不少情况下,for-loop本身已经不构成太大问题,尤其是当循环体本身需要较多的计算的时候。这个时候,改善概率的关键在于改善循环体本身而不是去掉for-loop。
  3. MATLAB的函数调用过程(非built-in function)有显著开销,因此,在效率要求较高的代码中,应该尽可能采用扁平的调用结构,也就是在保持代码清晰和可维护的情况下,尽量直接写表达式和利用built-in function,避免不必要的自定义函数调用过程。在次数很多的循环体内(包括在cellfun, arrayfun等实际上蕴含循环的函数)形成长调用链,会带来很大的开销。
  4. 在调用函数时,首选built-in function,然后是普通的m-file函数,然后才是function handle或者anonymous function。在使用function handle或者anonymous function作为参数传递时,如果该函数被调用多次,最好先用一个变量接住,再传入该变量。这样,可以有效避免重复的解析过程。
  5. 在可能的情况下,使用numeric array或者struct array,它们的效率大幅度高于cell array(几十倍甚至更多)。对于struct,尽可能使用普通的域(字段,field)访问方式,在非效率关键,执行次数较少,而灵活性要求较高的代码中,可以考虑使用动态名称的域访问。
  6. 虽然object-oriented从软件工程的角度更为优胜,而且object的使用很多时候很方便,但是MATLAB目前对于OO的实现效率很低,在效率关键的代码中应该慎用objects。
  7. 如果需要设计类,应该尽可能采用普通的property,而避免灵活但是效率很低的dependent property。如非确实必要,避免重载subsref和subsasgn函数,因为这会全面接管对于object的接口调用,往往会带来非常巨大的开销(成千上万倍的减慢),甚至使得本来几乎不是问题的代码成为性能瓶颈。

doubanclaim43f1a75046c8210a

Q.E.D.


上一篇:Matlab的优化工具箱2010年9月23日
最近做了些东西,用到了Matlab的优化工具箱,optimization toolbox。因为以前没用过这东西,今天把这个工具箱的帮助文档基本上翻了一遍。 这个工具箱

下一篇:整数规划思想求解数独游戏2010年9月25日
最近做一些优化问题,找到了YALMIP工具包。在其帮助文件里看到如何使用该工具包求解sudoku,整个思路是将问题转化为整数规划问题。这样的思路以前


  • 支持使用微薄、微信和QQ的账户登陆进行评论。由各自网站直接认证,不会泄露你的密码。
  • 登陆后可选择分享评论到所绑定的社交网络,如微薄、人人和QQ空间。
  • 评论提交后无法修改。如需修改,请删除原评论再重新提交。
  • 评论支持LaTeX代码,行内公式请用\(a+b=c\),行间公式请用\[a+b=c\]。公式只支持英文字符。