【问题标题】:How much overhead is created by the oop paradigm in matlabmatlab中的oop范式产生了多少开销
【发布时间】:2014-02-17 07:34:20
【问题描述】:

在 matlab 中,每个类方法看起来都像是一个普通方法,其第一个参数是对象本身。

这样的范例对于其他 oop 语言(例如 python)是完全可以接受的,因为类是通过引用传递的。另一方面,matlab 默认情况下按值传递对象(句柄类除外)。

从所有这些我推断,即使使用最简单的 setter 函数(或任何其他类方法)也会导致整个对象被复制。

例如,下面是matlab中某个类方法的签名:

classdef foo
  methods
    function obj = set.myParam(obj,value);
    function myfun(obj, value);
  end
end

在这种情况下,当我调用 fooObj.myfun(5) (或只是 myfun(fooObj,5))时,matlab 会复制整个 fooObj=foo() 吗?

这不是非常大的开销吗?在我看来,为每个类方法(和 setter)复制整个对象的效率非常低。

我错过了什么吗?有没有办法在 matlab 中避免这种情况,同时仍然使用 oop 技术?

我是否必须使用句柄类来防止这种性能开销?

【问题讨论】:

    标签: matlab oop matlab-class


    【解决方案1】:

    如果您希望您的类具有引用语义,那么可以,您需要使用句柄类而不是值类。

    但请注意,虽然默认情况下 MATLAB 按值传递参数,但它也使用延迟复制写入时复制,因此仅在以下情况下才会对输入参数进行复制需要修改输入参数。此外,如果输入参数是结构或对象,则仅对需要修改的部分(字段、属性)进行复制。

    此外,MATLAB 有一个就地优化,这样如果输出参数与输入参数相同,则可以在输入参数上进行操作 -place,则不需要制作副本。

    因此,例如,考虑这个函数:

    function y = timestwo(x)
    y = 2*x;
    

    如果您从基础工作区中的变量a 开始(假设它是一个非常大的双精度数组)并调用b = timestwo(a),则不会复制a,因为x 未被修改功能期间。仅在分配输出参数 y 时内存使用量才会增加。

    但是考虑一下这个函数:

    function y = timestwoconj(x)
    x = x';
    y = 2*x;
    

    现在在函数执行期间内存使用量会增加,因为在修改时会复制x。在计算y时分配相同的空间,然后在函数退出时清除x的临时副本。

    这说明了写入时的复制行为。

    还要考虑以下函数:

    function x = timestwo(x)
    x = 2*x;
    

    这里的输出参数和输入参数一样,所有的操作都可以就地完成。如果您调用a = timestwo(a),则根本不会进行任何复制,内存使用量也不会增加。这说明了优化的就地行为。

    尝试实现与上述类似的一些函数,将它们应用到一个大数组,然后在调试器中逐行逐行执行它们,同时在任务管理器中观察内存使用情况 - 你会明白的。

    在 MATLAB 中实现值类时,您通常会为方法使用语法,例如 function obj = myfun(obj, value),而不是 function myfun(obj, value)。方法具有与上述相同的工作方式,因此只有在方法期间修改对象时才会复制对象。

    当您使用值类时,这就是您想要发生的事情 - 如果您想要引用语义,请使用句柄类。

    希望有帮助!

    【讨论】:

    • @Lee 有关句柄和值类的部分已清楚记录。关于写时复制行为和就地优化的部分已记录在案,但不是很清楚或明确(例如,我认为文档中没有专门针对这两个主题的特定页面)。
    猜你喜欢
    • 2010-10-07
    • 2014-07-15
    • 2010-11-20
    • 2021-11-16
    • 2011-05-19
    • 1970-01-01
    • 1970-01-01
    • 2014-05-07
    • 2015-08-28
    相关资源
    最近更新 更多