2016-07-05 62 views
1

我正在編寫一個用面向對象的Matlab(2016a)編寫的項目,我正在嘗試優化一些代碼以改善運行時。使用探查器我已經確定了一種可能的性能改進---我們使用很多功能,它似乎效率特別低,在其實現中並不特別「matlab」。Matlab:提取單元格內的對象具有特定屬性值的數組

本質上,我想知道的是,如果有一種有效的方法來索引到一個Cellobject的類對象中,只抽出那些具有我們感興趣的特定屬性值的類型。目前我們使用for循環,我想知道是否有什麼我可以做矢量化或可能使用某種邏輯索引。不幸的是,我的搜索似乎沒有找到答案,邏輯索引到使用對象的CellArrays似乎並不是很多人想要做的事情...

這是一個最小的工作示例函數I'試圖改進。以下是MWE的其他代碼位。

我知道,通過更改其他實施以避免必須這樣做來解決此問題可能更爲明智。不過,如果可能的話,我寧願避免這樣做。

編輯:在我的典型用例中,單元格對象的數量很少(大約10或20),但效率低下的方法被調用了很多次(數千次)。這麼小的陣列,很多人都在找操作。

%% is there a "more matlab"/faster way to do this? 
function outputCellArray = ThereMustBeABetterWayToDoThis(cellArrayOfClassObjects,arrayOfTypesToFind) 
outputCellArray = {}; 

for iType = 1:numel(arrayOfTypesToFind) 
    thisType = arrayOfTypesToFind(iType); % this line is the real bottleneck according to the profiler 
    for iObject = 1:numel(cellArrayOfClassObjects) 


     thisClassObj = cellArrayOfClassObjects{iObject}; 

     if (thisClassObj.specificEnumType == thisType) % this line is also quite slow 
      outputCellArray{end+1} = thisClassObj; 
     end 
    end 
end 

類定義:

classdef MyClass < handle %% dummy example class 

    properties 
     specificEnumType; 
     x; 
     y; 
    end 

    methods 
     function this = MyClass(x,y,specificEnumType) 
      this.specificEnumType = specificEnumType; 
      this.x = x; 
      this.y = y; 
     end 
    end 
end 

和另:

classdef EnumType < uint32 %%dummy example class 
    enumeration 
     Type0 (0), 
     Type1 (1), 
     Type2 (2), 
     Type3 (3) 
    end 

end 

腳本調用整個事情:

% use this script to call the whole thing 

%% we have a cell array of class objects: they each have different enumTypes as a property 
cellArrayOfClassObjects{1} = MyClass(rand,rand,EnumType.Type0); 
cellArrayOfClassObjects{2} = MyClass(rand,rand,EnumType.Type1); 
cellArrayOfClassObjects{3} = MyClass(rand,rand,EnumType.Type2); 
cellArrayOfClassObjects{4} = MyClass(rand,rand,EnumType.Type3); 
cellArrayOfClassObjects{5} = MyClass(rand,rand,EnumType.Type3); 
cellArrayOfClassObjects{6} = MyClass(rand,rand,EnumType.Type2); 

%% we want to find the ones that have these specific enumTypes 
arrayOfTypesToFind = [EnumType.Type0,EnumType.Type2]; 

%% there must be a better way than this inefficient method 
outputArray = ThereMustBeABetterWayToDoThis(cellArrayOfClassObjects,arrayOfTypesToFind); 

回答

1

好吧,這是一個棘手的一個。爲了加快速度,我會盡量避免cellarray。在該函數的小區變更爲對象,那麼掃描爲載體,以加快循環的陣列,然後變回至細胞

嘗試此

cellArrayOfClassObjects=cell(10000,1); 
for i=1:10000 
    switch randi(4,1,1) 
     case 1 
      cellArrayOfClassObjects{i} = MyClass(rand,rand,EnumType.Type0); 
     case 2 
      cellArrayOfClassObjects{i} = MyClass(rand,rand,EnumType.Type1); 
     case 3 
      cellArrayOfClassObjects{i} = MyClass(rand,rand,EnumType.Type2); 
     case 4 
      cellArrayOfClassObjects{i} = MyClass(rand,rand,EnumType.Type3); 
    end 
end 

%% we want to find the ones that have these specific enumTypes 
arrayOfTypesToFind = [EnumType.Type0,EnumType.Type2]; 

%% there must be a better way than this inefficient method 
tic 
outputArray = ThereMustBeABetterWayToDoThis(cellArrayOfClassObjects,arrayOfTypesToFind); 
toc 
tic 
outputArray2 = ThereIs(cellArrayOfClassObjects,arrayOfTypesToFind); 
toc 


function outputCellArray = ThereIs(cellArrayOfClassObjects,arrayOfTypesToFind) 
outputCellArray = {}; 
X=[cellArrayOfClassObjects{:}];%matrix of the cell 

for iType = 1:numel(arrayOfTypesToFind) 
    %for each type check [X.specificEnumType]==arrayOfTypesToFind(iType) 
    % then get the objects by X([X.specificEnumType]==arrayOfTypesToFind(iType)) 
    % then put them in cells mat2cell(X(...) , 1 , sum of those X(...) 
    % and add the to the existing outputCellArray=outputCellArray+matcell 
    % in one line 
    outputCellArray=[outputCellArray mat2cell(X([X.specificEnumType]==arrayOfTypesToFind(iType)),1,sum([X.specificEnumType]==arrayOfTypesToFind(iType)))]; 
end 

end 

有可能是一個方法,使之通過預分配輸出陣列更快。我現在正在嘗試。 編輯 沒有工作......但第一部分應該這樣做

+0

謝謝。我會試一試,看看它如何與「真正」的類有更多的事情。 – FakeDIY

+0

有趣的是,當cellarray對象很大時,您的方法會更快,但cellarray對象很小時會更慢(嘗試使用10個對象的數組,但是執行查找過程的次數更多)。我認爲這是因爲在少量物體上做mat2cell等的開銷不值得。 – FakeDIY

0

我設法找到一個更好的方法(對於我的具體使用情況),它利用的事實,我對匹配的屬性枚舉類型。也就是說,我仍然想看看是否還有更多的通用解決方案。當對象的數量很大時@Finn的回答同樣好。

這是我的更新版本。有可能做出進一步的改進。

function outputCellArray = ExploitEnums(cellArrayOfClassObjects,arrayOfTypesToFind) 


typesCastToInts = uint32(arrayOfTypesToFind); 

objectTaskTypesTakenFromArray = cellfun(@(x) uint32(x.specificEnumType), cellArrayOfClassObjects); 

typesExistInBothArrays = ismember(objectTaskTypesTakenFromArray, typesCastToInts); 
matchingIndices = find(typesExistInBothArrays); 

if (~isempty(matchingIndices)) 
    outputCellArray = cellArrayOfClassObjects(matchingIndices); 
end 

end 
相關問題