在单元格数组中存储句柄对象时性能下降

Jac*_*cob 6 arrays oop performance matlab

我只有一小部分MATLAB代码存在大量性能问题,希望您可以了解如何改进它:

我正在MATLAB中开发一个基于代理的模拟,它创建了许多句柄对象.其中一些是代理,其他可以是例如代理所拥有的对象.

为了清楚地识别每个句柄对象,每个句柄对象都获得由" IdDistributor "对象发出的唯一Id(obj.Id).所述IdDistributor本身被移交给各对象的构造也就是resive ID和从那里调用来发出一个Id-数(giveId).

此外,IdDistributor还保留了一种电话簿(IdRegistry),它将每个Id与对象相关联.因此,鉴于Id,可以在IdRegistry中查找对象.

我通过使用一个单元格数组来实现这一点,该数组数组将不同的句柄对象存储在与其Id匹配的字段中.(正常数组不起作用,因为对象属于不同的类).

测试我的模拟非常慢,MATLAB Profiler显示99%的时间用在IdDistributor上,特别是在IdRegistry中存储对象的(当我尝试创建大约10,000时,每个对象需要花费1秒钟)对象).

现在我想尝试一种类似的解决方案,花费更少的时间.正如你在下面的代码中看到的那样,我已经尝试通过预分配来提高速度(当它已满时,我将IdRegistry扩展10,000个单元,而不是逐个增加1).我还想过试图以某种方式获得当我读到Id不是永久性的并且可以被系统更改时,句柄对象的MATLAB内部Id但没有遵循那条道路.

我非常感谢任何想法如何加快代码或找到解决方法/改进我的概念!

在这里我的代码:

最慢的行是IdDist.IdRegistry(IdNumber)= {obj};

顺便说一句.将其更改为IdDist.IdRegistry {IdNumber} = obj; 没多大帮助

classdef IdDistributor < handle

properties
    Id=int64(1); %Her own ID
    LastId=int64(1);
    IdRegistry={}
end

methods
    function IdDist=IdDistributor()
        IdDist.Id=int64(1);
        IdDist.LastId=int64(1);
        IdDist.register(IdDist);
    end
    function IdNum=giveId(IdDist,obj)
        IdNum=IdDist.LastId+int64(1);
        IdDist.LastId=IdNum;
        IdDist.register(obj,IdNum)
    end
    function register(IdDist,obj,IdNum)
        if nargin==2      
            IdNumber=obj.Id;
        elseif nargin==3
            IdNumber=IdNum;
        end
            if IdNumber>=length(IdDist.IdRegistry) %Extend the Register by 10000
              IdDist.IdRegistry(IdNumber+10000)={[]};    
            end
            if IdNumber >0
              IdDist.IdRegistry(IdNumber)={obj};
            end
    end %function
    end %methods
    end %class
Run Code Online (Sandbox Code Playgroud)

Nzb*_*buu 2

由于您没有从注册表中删除对象,因此您可能想尝试从matlab.mixin.Heterogeneous类派生所有对象,然后将它们存储为常规数组。请注意,这将需要 R2011a 或更高版本。

我不知道这是否更快,但值得尝试。当然,只有当您的所有 ID 都是由 IdDistributor 生成时它才会有用,因为它们是连续的。

另外,我的测试表明

length(IdDist.IdRegistry)
Run Code Online (Sandbox Code Playgroud)

也很慢,因此您也可以将注册表的长度存储在其中IdDistributor。为了安全起见,我建议将属性设置SetAccessprotected