MATLAB benötigt lange nach der letzten Zeile einer Funktion

8

Ich habe eine Funktion, deren Ausführung lange dauert. Wenn ich es profiliere, finde ich heraus, dass mehr als die Hälfte der Zeit (26 von 50 Sekunden) nicht in der zeilenweisen Zeitaufteilung berücksichtigt wird, und ich kann zeigen, dass die Zeit nach dem Ausführen der Funktion verbraucht wird, bevor sie die Kontrolle zurückgibt mit der folgenden Methode:

%Vor%

Die erste Zeile der aufgerufenen Funktion ist ts2 = tic und die letzte Zeile ist

%Vor%

Das Ergebnis ist

  

Aufruf der Funktion

     

letzte Zeile der Funktion - 24.0043

     

Steuerung kehrte zum Aufrufer - 49.857

zurück

Ich stochere in den Interwebs herum und denke, dass dies ein Symptom dafür ist, wie MATLAB das Gedächtnis verwaltet. Bei Funktionsrückgaben wird die Zuordnung aufgehoben, und manchmal dauert dies sehr lange. Die Funktion weist einige große (~ 1 Million Element) Arrays zu. Es funktioniert auch mit Handles, erstellt jedoch keine neuen Handle-Objekte oder speichert Handles explizit. Meine Fragen sind:

  1. Ist das definitiv ein Speicherverwaltungsproblem?
  2. Gibt es einen systematischen Weg zu diagnostizieren, was ein Problem in dieser Funktion verursacht, im Gegensatz zu anderen, die schnell zurückkehren?
  3. Gibt es allgemeine Tipps zur Verkürzung der Zeit, die MATLAB beim Beenden einer Funktion aufräumt?
Marc 24.11.2010, 14:55
quelle

3 Antworten

2

Ich habe eine Lösung für mein spezifisches Problem gefunden, die allgemein anwendbar ist.

Die Funktion, deren Exit lange dauerte, wurde für ein Basisobjekt aufgerufen, das einen Vektor von Handle-Objekten enthielt. Wenn ich die Definition des Basisobjekts in Extend-Handle änderte, eliminierte ich die Verzögerung beim Schließen der Funktion.

Was ich glaube, geschah: Wenn ich das Basisobjekt an meine Funktion übergeben habe, hat es eine Kopie dieses Objekts erstellt (MATLAB ist standardmäßig pass-by-value). Das dauert nicht viel Zeit, aber als die Funktion beendet wurde, zerstörte sie die Objektkopie, was dazu führte, dass sie durch den Vektor von Handle-Objekten guckte, um sicherzustellen, dass keine Waisen vorhanden waren, die bereinigt werden mussten. Ich glaube, dass diese Operation MATLAB lange Zeit in Anspruch nahm.

Wenn ich das Objekt änderte, das ich an ein Handle übergeben hatte, wurde im Funktionsarbeitsbereich keine Kopie erstellt, sodass am Ende keine Säuberung des Objekts erforderlich war.

Das deutet auf eine allgemeine Regel hin:

Wenn eine Funktion viel Zeit benötigt, um ihren Arbeitsbereich beim Beenden zu bereinigen, und Sie viele Daten oder komplexe Strukturen wertmäßig übergeben, versuchen Sie, die Argumente für diese Funktion in einem Handle-Objekt zu kapseln

Dadurch vermeiden Sie doppelte und damit zeitaufwendige Bereinigung beim Beenden. Der Nachteil ist, dass Ihre Funktion jetzt Ihre Eingaben unerwartet ändern kann, weil MATLAB nicht wie in C ++ ein Argument const deklarieren kann.

    
Marc 02.12.2010, 14:32
quelle
4

Sie haben recht, es scheint die Zeit zu sein, die Sie für Garbage Collection ausgegeben haben. Ich fürchte, es ist ein grundlegender MATLAB-Fehler, der seit Jahren bekannt ist, aber MathWorks hat ihn nicht einmal in der neuesten MATLAB-Version 2010b gelöst.

Sie könnten versuchen, Variablen manuell auf [] zu setzen, bevor Sie die Funktion verlassen - also die Garbage Collection manuell durchführen. Diese Technik hilft auch gegen Speicher Lecks in früheren MATLAB-Versionen. Jetzt wird MATLAB Zeit nicht auf end , sondern auf myVar=[];

verbringen

Sie könnten Probleme bei der Arbeit ohne jegliche Art von Referenzen lindern - anonyme Funktionen, verschachtelte Funktionen, Handle-Klassen, die nicht cellfun und arrayfun verwenden.

Wenn Sie an der "Leistungsbarriere" von MATLAB angekommen sind, sollten Sie vielleicht einfach die Umgebung ändern. Ich sehe sowieso keinen Sinn, wenn Sie heute ein neues Projekt in MATLAB starten, außer wenn Sie SIMULINK verwenden. Python Rocks für technisches Rechnen und mit C # können Sie auch viele Dinge tun, die MATLAB mit freien Bibliotheken macht. Und beide sind echte Programmiersprachen und sind im Gegensatz zu MATLAB frei.

    
Mikhail 24.11.2010 17:58
quelle
0

Eine einfache Lösung könnte dies sein: Ordnen Sie die großen Arrays vorab zu und übergeben Sie sie als Argumente an Ihre FunktionCall (). Dadurch wird das Problem der Aufhebung der Zuordnung an den Aufrufer von functionCall () rückgängig gemacht. Es könnte jedoch sein, dass Sie functionCall häufiger aufrufen als das übergeordnete Element. In diesem Fall beschleunigt dies Ihren Code.

%Vor%

Innerhalb von functionCall können Sie WorkArr initialisieren und / oder neu setzen, zum Beispiel

%Vor%     
ric0liva 27.11.2010 00:27
quelle