2012-06-27 4 views
13

私が書いたMex関数(Matlabから呼び出せるC++の関数)があり、valgrind/kcachegrindを使用してプロファイリングしたいのですが。私はvalgrind/kcachegrindの使い方を知っていますが、C++プログラムを直接実行しているのですが、MatlabからC++プログラムを呼び出している場合にこのプロファイリングを行う方法はありますか?MatlabのMEX関数をプロファイルするには

+0

大きな質問ですが、私はしばしばこれについて疑問に思っています。悲しいことに答えはわかりませんが、Visual StudioでMexコードをプロファイリングすることは可能です。 –

+0

@BillCheatham本質的にダイナミックライブラリであるMEXファイルを読み込むために、ラッパーコードを使ってLinux上でvalgrindを使用することができます。私の答えを見てください。 – angainor

+0

Alex、mexファイルをプロファイルする他の方法がありますか?気になります。 – angainor

答えて

9

MEXファイルのプロファイリングは、MEXファイルが共有ライブラリであるため、扱いにくいものです。標準的な 'gprof'アプローチを使ってLinux上で行うことはできません - gprofは単純にそうしません。私はsprofを使用しようとしましたが、私は“PLTREL not found error”を取得します - sprofも使用できません。以前の投稿hereがありますが、誰も最終的な答えを出しませんでした。

幸いなことに、valgrindでできることはLinuxです。まず、mexファイルをロードする「実行中の」コードを記述し、私たちが呼び出すmexFunctionシンボルを提供し、MEXファイルのパラメータを設定する必要があります。私はMATLAB engineを使用して、MATLABでこれを行うために推奨される方法を使用することを選択しました。次のコード(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を使用する必要があります。 valgrindのとMEXファイルをプロファイリング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 

は、コマンドラインから「テスト」プログラムを実行する必要があります。 MATLABへのパスと正しいアーキテクチャ依存のライブラリパスを設定する必要があること

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 

注:テストとMEXファイルの両方がコマンドを入力常駐するディレクトリで! MATLABの実行ファイルがPATHに存在しなければなりません。さもなければ、 'test'は失敗します。

もう1つキャッチがあります。 MATLABエンジンでは、システムにcshをインストールする必要があります(任意のシェルを使用できます.cshは/ binに存在する必要があります)。だから、もしあなたがそれを持っていなければ、これを動作させるためにそれをインストールしなければなりません。

4

このMatlabCentral threadに説明するようにあなたは、-DオプションでMATLABを起動することができます:

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がクラッシュしました。

関連する問題