2016-07-05 14 views
1
Ich arbeite an einem Projekt in objektorientierten Matlab (2016a) geschrieben und ich versuche derzeit, etwas Code zu optimieren, um die Laufzeit zu verbessern. Unter Verwendung des Profilers habe ich eine mögliche Leistungsverbesserung identifiziert --- es gibt eine Funktion, die wir viel verwenden, die besonders ineffizient und nicht besonders "Matlab" in seiner Implementierung scheint.

Im Wesentlichen möchte ich wissen, ob es eine effiziente Möglichkeit gibt, in ein CellArray von Klassenobjekten zu indizieren, um nur diejenigen hervorzuheben, die einen bestimmten Eigenschaftswert haben, an dem wir interessiert sind Schleifen und ich frage mich, ob ich etwas tun kann, um es zu vektorisieren oder möglicherweise eine Art von logischer Indizierung zu verwenden. Leider scheinen meine Suchen keine Antwort zu finden, eine logische Indizierung in CellArrays mit Objekten scheint nicht etwas zu sein, was viele Leute machen möchten ...Matlab: Extrahieren von Objekten innerhalb einer Zelle Array mit einem bestimmten Eigenschaftswert

Hier ist ein minimales funktionierendes Beispiel der Funktion I ' Ich versuche mich zu verbessern. Andere Code-Teile für einen MWE sind unten.

Ich bin mir bewusst, dass es klüger sein kann, dieses Problem zu beheben, indem Sie den Rest der Implementierung ändern, um dies überhaupt zu vermeiden. Ich würde es jedoch vorziehen, dies möglichst zu vermeiden.

EDIT: In meinem typischen Anwendungsfall ist die Anzahl der Zellobjekte klein (etwa 10 oder 20), aber die ineffiziente Methode wird oft aufgerufen (Tausende von Malen). So kleine Array, finden viele Operationen.

%% 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 

Klassendefinitionen:

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 

und ein anderer:

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

end 

Script, das Ganze zu nennen:

% 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); 

Antwort

1

Okay, das war eine knifflige Frage. Um die Dinge zu beschleunigen, würde ich versuchen, den Keller zu vermeiden. In der Funktion wird die Zelle auf ein Array von Objekten geändert, dann als Vektor abgetastet, um die Schleife zu beschleunigen, dann auf eine Zelle

Versuchen Sie, diese

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 

es könnte geändert wieder ein Weg, es zu machen, noch schneller durch Vorbelegung des Ausgangsarrays. Ich versuche es jetzt. bearbeiten die Arbeit den Ball hielt ... aber der erste Teil es

einen viel besseren Weg zu finden
+0

Danke. Ich werde es versuchen und sehen, wie es mit den "echten" Klassen funktioniert, die viel mehr los sind. – FakeDIY

+0

Interessanterweise ist Ihre Methode schneller, wenn die Anzahl der Objekte groß ist, aber langsamer, wenn das Objekt cellarray klein ist (versuchen Sie es mit einem Array von 10 Objekten, aber machen Sie den Fundprozess viel mehr).Ich nehme an, dies ist, weil der Overhead von Mat2cell usw. auf eine kleine Anzahl von Objekten nicht lohnt. – FakeDIY

0

ich es geschafft (für meine spezifischen Anwendungsfall), die die Tatsache ausnutzt tun sollten, dass die Eigenschaft ich bin passend ist ein Aufzählungstyp Trotzdem würde ich gerne sehen, ob es noch generische Lösungen gibt. @Finns Antwort ist ebenso gut, wenn die Anzahl der Objekte groß ist.

Hier ist meine aktualisierte Version. Es kann möglich sein, weitere Verbesserungen vorzunehmen.