2011-10-06 103 views
6

我有大量的性能問題,我MATLAB代碼的希望只是一個很小的部分,你可能有一個想法如何改進:在單元陣列存儲處理對象時,性能下降

我在MATLAB中開發基於代理的模擬,創建大量的句柄對象。其中一些人可能是其他人的代理人,例如代理擁有的對象。

爲了清楚地識別各由一個「IdDistributor」對象發出這些處理對象每一個獲得一個唯一的ID(obj.Id)的。 IdDistributor本身被移交給每個對象的構造函數,這些對象將拒絕一個Id並從那裏調用以發出Id編號(GiveId)。

另外IdDistributor保持幾分是每個ID與對象相關聯電話簿(一IdRegistry)。因此,鑑於Id可以在IdRegistry中查找對象。

我通過使用單元格數組來實現此目的,該單元格數組恰好存儲了與其ID爲匹配的字段中的不同句柄對象。 (由於對象是不同的類,所以普通數組不起作用)。

測試我的模擬是很慢和MATLAB 探查顯示,99%的時間都花在與IdDistributor尤其是與存儲在IdRegistry的對象行(用了類似1當我嘗試創建約10,000個對象時,每個對象的秒數)。

現在我試圖找到一個類似的解決方案,它需要更少的時間。正如你在下面的代碼中看到的,我已經試圖通過預先分配來提高速度(當它已滿時,我將其擴展爲10,000個單元格,而不是一個一個地確定)。我也想過以某種方式嘗試獲得句柄對象的MATLAB內部Id,但是當我讀到Id不是永久性的並且可以由系統改變時並沒有遵循這個道路。

我真的很感激任何想法或者如何加快代碼或找到解決方案/改進我的概念!

這裏我的代碼:

最慢的線是IdDist.IdRegistry(IDNumber中)= {OBJ};

btw。將其更改爲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 
+0

我現在已經嘗試將預分配更改爲:_IdDist.IdRegistry(IdNumber + 10000)= {SomeDummyHandleObject}; _因爲朋友建議單元格的大小可能會從空單元{[]}更改爲當一個句柄對象引用被存儲並可能導致Matlab重新分配內存。但是,這在_IdDistributor.register_中的1.428秒自身時間內僅節省了0.009秒。 – Jacob

+0

當你運行'慢'時,你的內存消耗是什麼? 是否有可能製作對象的副本而不是隻存儲控制柄? – zeFrenchy

+1

因爲它們都是Matlab處理對象,所以如果它們被複制,我會感到驚訝。然而,我只是通過將IdRegistry類型從_Cell_更改爲_Map_來進行了重大改進。我只是想發佈我的解決方案,但stackoverflow迫使我等待8小時,因爲我是新的。簡而言之:更改屬性部分:IdRegistry = containers.Map('KeyType','int64','ValueType','any');拿出預先分配區塊;將註冊更改爲:IdDist.IdRegistry(IdNumber)= obj; ;現在只需要17%的時間。不知道爲什麼。在幾個小時內完全回答。 – Jacob

回答

2

既然你不刪除從註冊表中的對象,你可能想嘗試從matlab.mixin.Heterogeneous類派生所有對象,然後將它們存儲爲規則陣列。請注意,這將需要R2011a或更新版本。

我不知道這是否更快,但它是一些嘗試。當然,只有當所有的ID都由IdDistributor生成時,它纔會有用,因爲它們是順序的。

而且,我的測試表明,

length(IdDist.IdRegistry) 

也慢,所以你可以在註冊表的長度存儲在IdDistributor爲好。爲了安全起見,我建議將SetAccess設置爲protected

+0

真實長度(IdDist.IdRegistry)需要一些時間。當我更新我的程序版本時,我會嘗試minin.Heterogenous。 – Jacob

0

我進一步研究了這個問題,在我看來,實際上大部分時間都是在從另一個對象調用IdDistributer的giveId方法的過程中丟失的,而在方法內部卻沒有那麼多。

我也在我的程序中發現了類似問題的其他地方。特別是當許多句柄對象被構造和存儲在一個數組中時,這個數組被存儲爲一個對象的屬性。所以性能下降的原因可能在於此,因爲在創建新的句柄對象時通常會使用IdDistributer。

由於這是一個有點不同的話題,我發佈了另一個question,包括一些簡單的插圖代碼。

+0

在我的[新問題]下實際上有一些相關的答案(http://stackoverflow.com/questions/7726487/how-to-avoid-matlab-taking-exponential-time-when-creating-a-handle -object-array-a/7727501#7727501)。如果同一類的許多對象要一次存儲在另一個對象的屬性中,它們可能會有所幫助。 – Jacob