2012-06-27 16 views
13

Tengo una función Mex (una función en C++ que puede llamar desde Matlab) que he escrito, y quiero perfilarla usando valgrind/kcachegrind. Sé cómo usar valgrind/kcachegrind si está ejecutando un programa de C++ directamente, pero ¿hay alguna forma de hacer este perfil si estoy llamando al programa de C++ de Matlab?Cómo perfilo una función MEX en Matlab

+0

Gran pregunta, a menudo me he preguntado sobre esto. Lamentablemente, no sé la respuesta, pero sé que es posible perfilar el código Mex con Visual Studio ... –

+0

@BillCheatham Puede usar valgrind en Linux utilizando el código de envoltura para cargar el archivo MEX, que es esencialmente una biblioteca dinámica. Eche un vistazo a mi respuesta. – angainor

+0

Alex, ¿encontraste alguna otra forma de perfilar archivos mex? Tengo curiosidad – angainor

Respuesta

9

Perfilar archivos MEX es complicado ya que los archivos MEX son bibliotecas compartidas. No se puede hacer en Linux utilizando el enfoque estándar 'gprof' - gprof simplemente no hace eso. Intenté usar sprof, pero obtengo “PLTREL not found error” - sprof no se puede usar tampoco. Hay una publicación anterior here, pero nadie dio una respuesta final.

Afortunadamente, hay una manera en que uno puede hacerlo con valgrind en Linux. Primero, tenemos que escribir el código 'en ejecución' que carga el archivo mex, proporciona el símbolo de función mex para que llamemos y establece los parámetros del archivo MEX. He elegido usar la forma recomendada de hacerlo con MATLAB, usando MATLAB engine. El siguiente código (guardar como prueba.c) carga un archivo MEX y encuentra el símbolo de función mex, carga los datos de entrada de un archivo previamente guardado como 'input.mat' (se puede hacer en MATLAB usando el comando guardar) y llama a la función 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; 
} 

El archivo MEX sí también debe compilado con el interruptor mex -g. El código anterior debe compilarse con mex -g y usar engopts.sh como parámetros de compilación. Desde MATLAB tipo de línea de comandos

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

o en una norma de ejecución terminal de Linux

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

perfilar el archivo MEX con valgrind requiere la ejecución del programa de 'prueba' de la línea de comandos. En el directorio en ambas pruebas y el archivo MEX residen escriba el 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 

Recuerde que la ruta a MATLAB y corregir las rutas de bibliotecas dependientes de la arquitectura deben fijarse! el ejecutable de matlab debe estar presente en la RUTA, de lo contrario, la 'prueba' fallará.

Hay una captura más. El motor de MATLAB requiere que se instale csh en el sistema (puede usar cualquier shell, csh solo necesita estar presente en/bin). Entonces, si no lo tiene, debe instalarlo para que funcione.

4

Se podría empezar MATLAB con la opción -D, tal como se describe en este MatlabCentral thread:

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

Yo añadiría a asegurarse de que usted tiene la última versión de valgrind. Cuando intenté depurar mi archivo MEX con valgrind versión 3.6, valgrind se bloqueó en lugar de informar errores de memoria.

Cuestiones relacionadas