在我看来,在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实现对象的方式的一个基本问题,但我仍然不确定。
答案 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