2012-06-27 21 views
13

Ho una funzione Mex (una funzione in C++ che puoi chiamare da Matlab) che ho scritto, e voglio profilarla usando valgrind/kcachegrind. So come usare valgrind/kcachegrind se si sta eseguendo direttamente un programma C++, ma c'è un modo per fare questo profiling se sto chiamando il programma C++ da Matlab?Come faccio a profilare una funzione MEX in Matlab

+0

Ottima domanda, mi sono spesso chiesto questo. Purtroppo non conosco la risposta, ma so che è possibile profilare il codice Mex con Visual Studio ... –

+0

@BillCheatham È possibile utilizzare valgrind su Linux utilizzando il codice wrapper per caricare il file MEX, che è essenzialmente una libreria dinamica. Dai un'occhiata alla mia risposta. – angainor

+0

Alex, hai trovato un altro modo per profilare i file mex? Io sono curioso. – angainor

risposta

9

Il profiling dei file MEX è complicato poiché i file MEX sono librerie condivise. Non può essere fatto su Linux usando l'approccio standard "gprof" - gprof semplicemente non lo fa. Ho provato a usare lo sprof, ma ottengo “PLTREL not found error” - lo sprof non può essere usato neanche. C'è un precedente post here, ma nessuno ha dato una risposta definitiva.

Fortunatamente, c'è un modo in cui è possibile farlo con valgrind su Linux. Per prima cosa, dobbiamo scrivere il codice "in esecuzione" che carica il file mex, fornisce il simbolo mexFunction che dobbiamo chiamare e imposta i parametri del file MEX. Ho scelto di usare il metodo consigliato per farlo con MATLAB - usando MATLAB engine. Il seguente codice (salva come test.c) carica un file MEX e trova il simbolo mexFunction, carica i dati di input da un file precedentemente salvato come 'input.mat' (può essere fatto in MATLAB usando il comando save), e chiama 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; 
} 

Il file MEX stesso dovrebbe anche compilato con l'interruttore mex -g. Il codice sopra deve essere compilato con mex -g e usando engopts.sh come parametri di compilazione. Da MATLAB tipo di linea di comando

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

o in un terminale eseguire Linux standard di

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

Profiling il file MEX con valgrind richiede l'esecuzione del programma di 'test' dalla linea di comando. Nella directory in cui sia prova e il file MEX risiedono digitare il comando:

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 

Nota che il percorso a MATLAB e correggere architettura-dipendente percorsi di libreria devono essere impostati! l'eseguibile matlab deve essere presente nel PERCORSO, altrimenti 'test' fallirà.

C'è un altro fermo. Il motore MATLAB richiede che csh sia installato sul sistema (puoi usare qualsiasi shell, csh deve solo essere presente in/bin). Quindi se non ce l'hai, devi installarlo affinché funzioni.

4

Si potrebbe iniziare MATLAB con l'opzione -D, come descritto in questa MatlabCentral thread:

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

vorrei aggiungere per assicurarsi di avere l'ultima versione di Valgrind. Quando ho provato a eseguire il debug del mio file MEX con valgrind versione 3.6, valgrind si è arrestato in modo anomalo invece di segnalare errori di memoria.

Problemi correlati