私が作成した Mex 関数 (Matlab から呼び出すことができる C++ の関数) があり、valgrind/kcachegrind を使用してそれをプロファイリングしたいと考えています。C++ プログラムを直接実行している場合に valgrind/kcachegrind を使用する方法は知っていますが、Matlab から C++ プログラムを呼び出している場合にこのプロファイリングを行う方法はありますか?
2 に答える
MEXファイルは共有ライブラリであるため、MEXファイルのプロファイリングには注意が必要です。Linuxでは、標準の「gprof」アプローチを使用して実行することはできません。gprofは単にそれを実行しません。sprofを使おうとしましたが、「PLTRELnotfounderror」</a>が表示されます。sprofも使用できません。ここに以前の投稿がありますが、誰も最終的な答えを出しませんでした。
幸いなことに、 Linuxでvalgrindを使用してそれを実行できる方法があります。まず、mexファイルをロードし、呼び出すmexFunctionシンボルを提供し、MEXファイルのパラメーターを設定する「実行中」のコードを作成する必要があります。私はMATLABでこれを行うための推奨される方法を使用することを選択しました-MATLABエンジンを使用します。次のコード(test.cとして保存)は、MEXファイルをロードしてmexFunctionシンボルを検索し、以前に「input.mat」として保存されたファイルから入力データをロードし(MATLABでsaveコマンドを使用して実行できます)、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ファイルをプロファイリングするには、コマンドラインから「test」プログラムを実行する必要があります。テストファイルと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」は失敗します。
もう1つ問題があります。MATLABエンジンでは、システムにcshをインストールする必要があります(任意のシェルを使用できます。cshは/ binに存在する必要があります)。したがって、お持ちでない場合は、これを機能させるためにインストールする必要があります。
このMatlabCentral スレッドで説明されているように、-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 はメモリ エラーを報告する代わりにクラッシュしました。