2012-06-27 6 views
13

Ich habe eine Mex-Funktion (eine Funktion in C++, die Sie von Matlab aufrufen können), die ich geschrieben habe, und ich möchte es mit valgrind/kcachegrind profilieren. Ich weiß, wie valgrind verwenden/kcachegrind, wenn Sie ein C++ Programm direkt ausgeführt werden, aber gibt es eine Möglichkeit, diese Profilierung zu tun, wenn ich das C++ Programm von Matlab nenne?Wie profile ich eine MEX-Funktion in Matlab

+0

Große Frage, ich habe mich oft gefragt. Leider weiß ich die Antwort nicht, aber ich weiß, dass es möglich ist, Mex-Code mit Visual Studio zu profilieren ... –

+0

@BillCheatham Sie können valgrind unter Linux verwenden, indem Sie die MEX-Datei, die im Wesentlichen eine dynamische Bibliothek ist, mit Wrapper-Code laden. Schau dir meine Antwort an. – angainor

+0

Alex, hast du eine andere Möglichkeit gefunden, mex Dateien zu profilieren? Ich bin neugierig. – angainor

Antwort

9

Das Profiling von MEX-Dateien ist schwierig, da die MEX-Dateien gemeinsam genutzte Bibliotheken sind. Es kann nicht unter Linux mit dem Standard-Gprof-Ansatz durchgeführt werden - gprof macht das einfach nicht. Ich habe versucht, sprof zu verwenden, aber ich bekomme “PLTREL not found error” - sprof kann auch nicht verwendet werden. Es gibt einen früheren Post here, aber niemand gab eine endgültige Antwort.

Glücklicherweise gibt es einen Weg, in dem man es mit Valgrind auf Linux tun kann. Zuerst müssen wir einen "laufenden" Code schreiben, der die mex-Datei lädt, das mexFunction-Symbol für den Aufruf bereitstellt und die Parameter der MEX-Datei einrichtet. Ich habe den empfohlenen Weg gewählt, um dies mit MATLAB zu tun - mit MATLAB engine. Der folgende Code (als test.c speichert) lädt eine MEX-Datei und findet das mexFunction Symbol, laden Eingangsdaten von einer Datei, die zuvor als ‚input.mat‘ gespeichert (kann in MATLAB erfolgen Befehl speichern), und ruft die mexFunction.

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <errno.h> 
#include <dlfcn.h> 
#include "engine.h" 

typedef void (*mexFunction_t)(int nargout, mxArray *pargout [ ], int nargin, const mxArray *pargin[]); 

int main(int argc, const char *argv[]) 

{ 
    Engine *ep; 
    char buff[1024]; 
    int i; 

    /* matlab must be in the PATH! */ 
    if (!(ep = engOpen("matlab -nodisplay"))) { 
    fprintf(stderr, "Can't start MATLAB engine\n"); 
    return -1; 
    } 
    engOutputBuffer(ep, buff, 1023); 

    /* load the mex file */ 
    if(argc<2){ 
    fprintf(stderr, "Error. Give full path to the MEX file as input parameter.\n"); 
    return -1; 
    } 
    void *handle = dlopen(argv[1], RTLD_NOW); 
    if(!handle){ 
    fprintf(stderr, "Error loading MEX file: %s\n", strerror(errno)); 
    return -1; 
    } 

    /* grab mexFunction handle */ 
    mexFunction_t mexfunction = (mexFunction_t)dlsym(handle, "mexFunction"); 
    if(!mexfunction){ 
    fprintf(stderr, "MEX file does not contain mexFunction\n"); 
    return -1; 
    } 

    /* load input data - for convenience do that using MATLAB engine */ 
    /* NOTE: parameters are MEX-file specific, so one has to modify this*/ 
    /* to fit particular needs */ 
    engEvalString(ep, "load input.mat"); 
    mxArray *arg1 = engGetVariable(ep, "Ain"); 
    mxArray *arg2 = engGetVariable(ep, "opts"); 
    mxArray *pargout[1] = {0}; 
    const mxArray *pargin[2] = {arg1, arg2}; 

    /* execute the mex function */ 
    mexfunction(1, pargout, 2, pargin); 

    /* print the results using MATLAB engine */ 
    engPutVariable(ep, "result", pargout[0]); 
    engEvalString(ep, "result"); 
    printf("%s\n", buff); 

    /* cleanup */ 
    mxDestroyArray(pargout[0]); 
    engEvalString(ep, "clear all;"); 
    dlclose(handle); 
    engClose(ep); 

    return 0; 
} 

Die MEX-Datei selbst sollte auch mit dem mex -g Schalter zusammengestellt. Der obige Code muss mit mex -g kompiliert werden und engopts.sh als Kompilierungsparameter verwenden. Von MATLAB-Kommandozeile Typ

mex('-v', '-f', fullfile(matlabroot,... 
    'bin','engopts.sh'),... 
    'test.c'); 

oder in einem Standard-Linux-Terminal läuft

/path/to/matlab/bin/mex -g -f /path/to/matlab/bin/engopts.sh test.c 

Profil die MEX-Datei mit valgrind das 'Test' Programm von der Befehlszeile erfordert läuft. In dem Verzeichnis, in dem beide Test und der MEX-Datei den Befehl residieren Typ:

PATH=$PATH:/path/to/matlab/bin/ LD_LIBRARY_PATH=/path/to/matlab/bin/glnxa64/:/path/to/matlab/sys/os/glnxa64/ valgrind --tool=callgrind ./test ./mex_file.mexa64 

Beachten Sie, dass der Pfad zu MATLAB und korrekte architekturabhängige Bibliothekspfade müssen eingestellt werden! Die ausführbare Matlab-Datei muss im PATH vorhanden sein, andernfalls schlägt 'test' fehl.

Es gibt noch einen Haken. Die MATLAB-Engine erfordert, dass csh auf dem System installiert wird (Sie können eine beliebige Shell verwenden, csh muss nur in/bin vorhanden sein). Wenn Sie es nicht haben, müssen Sie es installieren, damit es funktioniert.

4

Sie könnten MATLAB mit der Option -D beginnen, wie auf dieser MatlabCentral thread beschrieben:

matlab -nojvm -nodesktop -nosplash -D"valgrind --error-limit=no --leak-check=yes --tool=memcheck -v --log-file=valgrind.log"

ich sicherstellen möchte hinzufügen, dass Sie die neueste Version von valgrind haben. Als ich versuchte, meine MEX-Datei mit valgrind Version 3.6 zu debuggen, stürzte Valgrind ab, anstatt Speicherfehler zu melden.