MATLAB parfor und C ++ - Klassenmex-Wrapper (Kopierkonstruktor erforderlich?)

8

Ich versuche, eine C ++ - Klasse in einen Matlab-Mex-Wrapper zu schreiben, indem ich den hier beschriebenen Ansatz hier verwende . Im Grunde habe ich eine Initialisierungs-Mex-Datei, die ein C ++ - Objekthandle zurückgibt:

%Vor%

Ich kann das dann an eine andere mex-Datei übergeben (z. B. myclass_amethod ), die den Handle verwendet, um Klassenmethoden aufzurufen, und schließlich auf myclass_delete , um das C ++ - Objekt freizugeben:

%Vor%

Ich habe dies in einer MATLAB-Klasse zusammengefasst, um die Benutzung zu vereinfachen:

%Vor%

Problem: Dies funktioniert nicht in parallelem Code

Dies funktioniert in nicht parallelem Code. Sobald ich es jedoch innerhalb von parfor anrufe:

%Vor%

Ich erhalte einen segfault, da eine Kopie der Klasse in der parfor -Schleife (in jedem Worker) erstellt wird, aber da jeder Worker ein separater Prozess ist, wird die C ++ - Objektinstanz nicht kopiert. führt zu einem ungültigen Zeiger.

Ich habe versucht, zunächst zu erkennen, wann jede Klassenmethode in einer parfor-Schleife ausgeführt wurde, und in diesen Fällen auch das C ++ - Objekt neu zuzuweisen. Da jedoch nicht überprüft werden kann, ob ein Objekt bereits für den aktuellen Worker zugewiesen wurde, führt dies zu mehreren Neuzuweisungen und dann nur einem Löschen (wenn der Worker beendet wird), was zu einem Speicherverlust führt (siehe Anhang im Frage für Details).

Lösungsversuch: Kopiere Konstruktoren und verwende matlab.mixin.Copyable

In C ++ würde dies mit Kopierkonstruktoren geschehen (so dass das C ++ - Objekt nur einmal neu zugewiesen wird, wenn die Wrapper-MATLAB-Klasse kopiert wird). Eine Schnellsuche öffnet den matlab.mixin.Copyable -Klassen-Typ scheint die erforderliche Funktionalität bereitzustellen (dh tiefe Kopien von MATLAB-Handle-Klassen). Daher habe ich folgendes versucht:

%Vor%

Testen dieser Klasse wie oben, d. h .:

%Vor%

Ergebnisse in der Ausgabe:

%Vor%

Mit anderen Worten, scheint, dass der Kopierkonstruktor nicht aufgerufen wird, wenn er workers für das parfor erzeugt. Hat jemand irgendwelche Hinweise, was ich falsch mache, oder ob es eine Möglichkeit gibt, das gewünschte Verhalten der Reinitialisierung des C ++ - Objekt-Handles zu erreichen, wenn die MATLAB-Wrapper-Klasse kopiert wird?

Alternativer Ansatz: Erkennen, wenn auf Arbeiter ausgeführt wird

Nur zur Referenz: Hier ist der alternative Ansatz, den ich verwende, wenn ich in einem Worker neu zugewiesen werde:

%Vor%

und die Ausgabe:

%Vor%

Wie oben zu sehen ist, tritt tatsächlich eine Neuzuweisung auf, wenn ein Arbeiter ausgeführt wird. Der -Destruktor wird jedoch nur einmal für jeden Worker aufgerufen, unabhängig davon, wie lange die C ++ - Klasse neu zugeordnet wurde, was zu einem Speicherverlust führte.

Lösung: Verwenden von loadobj

Folgendes funktioniert:

%Vor%     
Ken Chatfield 12.12.2012, 15:22
quelle

1 Antwort

7

Wenn Sie eine Objektinstanz in den Körper einer PARFOR -Schleife übergeben, verhält sich das Verhalten so, als ob Sie es in einer Datei gespeichert und dann erneut geladen hätten. Die einfachste Lösung ist wahrscheinlich, Ihre cpp_handle_ als Transient zu markieren. Dann müssen Sie SAVEOBJ und LOADOBJ implementieren, um Ihre Daten sicher zu transportieren. Weitere Informationen zum Anpassen des Speicher- / Ladeverhaltens Ihrer Klasse finden Sie auf dieser Seite .

    
Edric 12.12.2012, 15:55
quelle