Matlab mex-Datei mit mexCallMATLAB ist fast 300 mal langsamer als die entsprechende m-Datei

7

Ich habe angefangen, ein paar m-Dateien in C ++ zu implementieren, um die Laufzeiten zu reduzieren. Die m-Dateien erzeugen n-dimensionale Punkte und werten an diesen Stellen Funktionswerte aus. Die Funktionen sind benutzerdefiniert und werden als Funktionshandles an M-Files und Mex-Files übergeben. Die mex-Dateien verwenden mexCallMATLAB mit feval zum Auffinden von Funktionswerten.

Ich habe das folgende Beispiel konstruiert, in dem ein in der Matlab-Befehlszeile erstelltes Funktions-Handle fn an die Routinen matlabcallingmatlab.m und mexcallingmatlab.cpp übergeben wird. Mit einem frisch geöffneten Matlab wertet mexcallingmatlab diese Funktion 200000 in 241,5 Sekunden aus, während matlabcallingmatlab es in 0,81522 Sekunden auswertet, also eine 296-fache Verlangsamung mit der mex-Implementierung. Diese Zeiten sind die Ergebnisse der zweiten Läufe, da die ersten Läufe größer zu sein scheinen, wahrscheinlich aufgrund einiger Gemeinkosten, die beim ersten Laden des Programms auftreten.

Ich habe viele Tage damit verbracht, online nach diesem Problem zu suchen und habe einige Vorschläge dazu gemacht. Ich habe verschiedene mex compiling Flags ausprobiert, um das mex zu optimieren, aber es gab fast keinen Unterschied in der Leistung. In einem früheren Post in Stackoverflow hieß es, Matlab zu aktualisieren sei die Lösung, aber ich verwende wahrscheinlich die neueste Version MATLAB Version: 8.1.0.604 (R2013a) unter Mac OS X Version: 10.8.4. Ich habe die Mex-Datei mit und ohne LargeArrayDims-Flag kompiliert, aber das hat auch keinen Unterschied gemacht. Einige schlugen vor, dass der Inhalt des Funktions-Handles direkt in der cpp-Datei codiert werden könnte, aber das ist unmöglich, da ich diesen Code jedem Benutzer mit einem beliebigen Funktionstyp mit Vektoreingabe und reeller Zahlenausgabe bereitstellen möchte.

Soweit ich herausfand, müssen mex-Dateien die Feval-Funktion durchlaufen, um einen Funktions-Handle zu verwenden, während m-Dateien direkt Funktions-Handles aufrufen können, vorausgesetzt, die Matlab-Version ist neuer als eine Version.

Jede Hilfe würde sehr geschätzt werden.

Einfaches Funktionshandle, das in der Matlab-Befehlszeile erstellt wurde :

%Vor%

matlabcallingmatlab.m :

%Vor%

mexcallingmatlab.cpp :

%Vor%

Kompilierung der mex-Datei :

%Vor%     
Meteor 06.09.2013, 14:42
quelle

3 Antworten

17

Also habe ich versucht, das selbst umzusetzen, und ich glaube, ich habe den Grund für die Langsamkeit gefunden.

Grundsätzlich hat Ihr Code ein kleines Speicherleck, in dem Sie das lhs mxArray nicht freigeben, das von dem Aufruf an mexCallMATLAB . Es ist nicht genau ein Speicherverlust, da der MATLAB-Speichermanager den Speicher freigibt, wenn die MEX-Datei beendet wird:

  

MATLAB weist dynamischen Speicher zu, um mxArrays in plhs zu speichern.   MATLAB hebt automatisch den dynamischen Speicher auf, wenn Sie die MEX-Datei löschen.   Wenn der Heap-Speicherplatz jedoch zu hoch ist, rufen Sie mxDestroyArray when auf   Sie sind fertig mit den mxArrays plhs Punkten auf.

Noch expliziter ist besser als implizit ... Ihr Code betont also wirklich die Freigabe des MATLAB-Speichermanagers:)

mexcallingmatlab.cpp

%Vor%

MATLAB

%Vor%

Wenn ich den obigen Benchmark einige Male (um ihn aufzuwärmen) liefere, bekomme ich folgende konsistente Ergebnisse:

%Vor%

Nein, wo in der Nähe der langsamen Zeiten, die Sie ursprünglich hatten! Dennoch ist der reine MATLAB-Teil ungefähr doppelt so schnell, wahrscheinlich wegen des Overheads, eine externe MEX-Funktion aufzurufen.

(Mein System: Win8 läuft 64-bit R2013a)

    
Amro 06.09.2013, 17:06
quelle
4

Es gibt absolut keinen Grund zu erwarten, dass eine MEX-Datei im Allgemeinen schneller als eine M-Datei ist. Der einzige Grund, warum dies oft der Fall ist, ist, dass viele Schleifen in MATLAB viel Funktionsaufruf-Overhead zusammen mit Parameterüberprüfung und dergleichen verursachen. Das Umschreiben in C eliminiert den Overhead und gibt Ihrem C-Compiler die Möglichkeit, den Code zu optimieren.

In diesem Fall gibt es nichts, was der C-Compiler optimieren könnte ... er muss die MATLAB-Schnittstelle für jede Iteration aufrufen. Tatsächlich wird der MATLAB-Optimierer einen besseren Job machen, da er in manchen Fällen in die Funktion "hineinsehen" kann.

Mit anderen Worten vergessen Sie die Verwendung von MEX, um dieses Programm zu beschleunigen.

    
Peter 06.09.2013 15:15
quelle
1

Es gibt einige Overhead-Kosten bei Anrufen von Mex zu Matlab und umgekehrt. Der Overhead pro Anruf ist klein, aber es addiert sich in einer engen Schleife wie folgt. Wie Ihre Tests zeigen, kann reines Matlab in diesem Fall viel schneller sein! Ihre andere Option ist, den mexCallMATLAB -Aufruf zu eliminieren und alles in reinem C ++ zu machen.

    
shoelzer 06.09.2013 15:10
quelle