2012-06-27 57 views
13

我有一个Mex函数(可以从Matlab调用的函数,可以从Matlab调用),我想用valgrind/kcachegrind剖析它。如果你直接运行一个C++程序,我知道如何使用valgrind/kcachegrind,但是如果我从Matlab调用C++程序,是否有办法执行此分析?如何在Matlab中剖析MEX函数

+0

伟大的问题,我经常想知道这件事。可悲的是我不知道答案,但我知道可以使用Visual Studio来剖析Mex代码...... –

+0

@BillCheatham您可以在Linux上使用valgrind使用包装代码来加载MEX文件,该文件本质上是一个动态库。看看我的答案。 – angainor

+0

亚历克斯,你有没有找到其他方式来分析mex文件?我好奇。 – angainor

回答

9

由于MEX文件是共享库,因此对MEX文件进行性能分析非常棘手。它不能在Linux上使用标准的'gprof'方法来完成--gprof根本就没有这样做。我试图用sprof,但我得到“PLTREL not found error” - sprof也不能使用。以前有一篇文章here,但没有人给出最终答案。

幸运的是,有一种方法可以在valgrind上使用Linux。首先,我们需要编写加载mex文件的“运行”代码,提供mexFunction符号供我们调用,并设置MEX文件的参数。我选择了使用推荐的方法来使用MATLAB来完成此操作 - 使用MATLAB engine。下面的代码(保存为test.c)加载一个MEX文件并找到mexFunction符号,从之前保存为'input.mat'的文件加载输入数据(可以使用保存命令在MATLAB中完成),并调用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; 
} 

MEX文件本身也应该与mex -g开关编译。上面的代码必须使用mex -g编译并使用engopts.sh作为编译参数。从MATLAB命令行键入

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

或在标准Linux终端运行

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

绘制与所述Valgrind的MEX文件需要运行在命令行“测试”程序。在两个测试和MEX文件驻留键入命令的目录:

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 

需要注意的是,以MATLAB和正确的体系结构相关的库路径需要的路径设置! matlab可执行文件必须存在于PATH中,否则'test'将失败。

还有一个问题。 MATLAB引擎需要在系统上安装csh(您可以使用任何shell,csh只需要存在于/ bin中)。所以如果你没有它,你必须安装它才能工作。

4

你可以用-D选项启动MATLAB,因为在这个MatlabCentral thread描述:

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

我想补充,以确保您有最新版本的valgrind的。当我尝试使用valgrind版本3.6来调试我的MEX文件时,valgrind崩溃而不是报告内存错误。