在创建句柄对象数组作为对象属性时,如何避免Matlab采用指数时间

时间:2011-10-11 13:05:10

标签: arrays oop matlab properties memory-management

在我看来,在Matlab时间尺度上创建一个关于线性的简单句柄对象数组时。但是,如果我创建完全相同的数组并且将其存储为对象的属性,则时间按比例缩放 - 因此在创建许多对象时程序会变得非常慢。

我的问题是为什么会发生这种情况以及如何避免这种情况? 对象属性的预分配是否在我的代码中没有正确实现,或者Matlab处理这些事情的方式是否存在根本问题?

我写了一个简单的测试来说明这个问题:

简单对象代码:

classdef SomeSimpleObject < handle
% SomeSimpleObject defines an Object that has one property

properties
    property=0;
end

methods
    function SimpleObj=SomeSimpleObject()
        if nargin~=0
            SimpleObj.property=1;
        end
    end
end

end

使用以下脚本创建1x10.000这些简单对象的数组,取决于我的机器上的探测器0,4秒:

for n=10000:-1:1 % counting backwards for Memory pre-allocation
    ObjectList(n)=SomeSimpleObject();
end

然而,在类构造函数中执行相同的操作并将10.000个对象的数组存储为属性需要59秒,并且它会更快地变得更糟。通过从此类创建对象来尝试它(例如 a = HostingObject

classdef HostingObject < handle
% This Objects Hosts a List of Objects that are created in the
% constructor

properties
    ObjectList=SomeSimpleObject
end

methods
    function obj=HostingObject()    
        for n=10000:-1:1 % counting backwards for Memory pre-allocation
            obj.ObjectList(n)=SomeSimpleObject();
        end
    end
end

end

寻找答案我遇到了关于Matlab内存分配和garbage collection的讨论。 Mikhail的答案(也与我的问题没有直接关系)让我觉得它可能是Matlab实现对象的方式的一个基本问题,但我仍然不确定。

3 个答案:

答案 0 :(得分:4)

我不知道为什么你的代码很慢,但我找到了修复它的方法:使用单元格数组而不是普通数组。我自己并不觉得它非常直观,但这是我的分析结果:

>> tic,a=HostingObject;toc
Elapsed time is 105.320128 seconds.

>> tic,a=JonasHostingObject;toc
Elapsed time is 2.394570 seconds.

该对象定义如下:

classdef JonasHostingObject < handle
properties
    ObjectList
end
methods
    function obj=JonasHostingObject()    
        obj.ObjectList=cell(10000,1);
        for n=1:10000
            obj.ObjectList{n}=SomeSimpleObject();
        end
    end
end    
end

我正在使用MATLAB R2011a 64位,以防万一。

答案 1 :(得分:4)

受到@Jonas Heidelberg@Tobias Heß答案的启发,我提出了以下解决方案,根本不需要单元格数组。对象存储在辅助数组中,一旦完成,它们将被复制到属性数组中:

使用数组“post-allocation”的HostingObject代码:

classdef JacobHostingObject < handle
% This Objects Hosts a List of Objects that are created in the constructor

properties
    ObjectList=SomeSimpleObject
end

methods
    function obj=JacobHostingObject()         
        for n=10000:-1:1 % counting backwards for Memory pre-allocation         
            a(n)=SomeSimpleObject(); % auxiliary array for "post-allocation"           
        end            
         obj.ObjectList=a; % "post-allocation"
    end
end

end

那么三种解决方案(Jonas,Tobias和我的)如何表现?

我运行了一些测试(使用MATLAB R2011b 64位)来比较它们:

10.000物件

经过时间: Tobias:0,30秒;雅各布:0,31秒;乔纳斯:2,02秒;原文:56,79秒

100.000物件

经过时间: Tobias:2,42秒;雅各布:2,95秒;乔纳斯:203,03秒

1.000.000对象

经过的时间:托比亚斯:23,84秒;雅各布:29,18秒

所以看起来Tobias版本是最快的解决方案

值得注意的是,Jonas解决方案比原始解决方案要好得多,但对其他两个解决方案的影响要差得多。这证实了我在之前的问题"slow performance when storing handle objects in a cell array"中所做的观察。具有讽刺意味的是,使用导致我早期问题的技术结果证明是对这个问题的改进。然而,Tobias解决方案甚至回答了我的旧问题(我将在那里发布参考文献)。

但是,仍然不清楚MATLAB内部实际上会导致性能差异。了解这一点可能有助于避免将来遇到类似的问题!

答案 2 :(得分:2)

我发现了一个问题。我认为使用单元格数组并不是一个好的解决方案,因为对数组中的对象不一样。但您可以使用单元格作为问题的解决方法:

classdef HostingObject < handle
% This Objects Hosts a List of Objects that are created in the
% constructor

properties
    ObjectList=SomeSimpleObject
end

methods
    function obj=HostingObject()

        % Creating first a cell array
        helpCell = cell(10000,1);
        for n=1:10000 
            helpCell{n}=SomeSimpleObject();
        end

        % Convert the cell array to the object array
        obj.ObjectList = horzcat(helpCell{:});

    end

end

end