Подтвердить что ты не робот

Как профилировать MEX-функцию в Matlab

У меня есть функция Mex (функция в С++, которую вы можете вызывать из Matlab), которую я написал, и я хочу профилировать ее с помощью valgrind/kcachegrind. Я знаю, как использовать valgrind/kcachegrind, если вы используете программу С++ напрямую, но есть ли способ сделать это профилирование, если я вызываю программу С++ из Matlab?

4b9b3361

Ответ 1

Файлы профилирования MEX сложны, так как файлы MEX являются общими библиотеками. Этого нельзя сделать в Linux с использованием стандартного подхода "gprof" - gprof просто этого не делает. Я пытался использовать sprof, но я получаю "PLTREL не найдена ошибка" - sprof также не может быть использован. Предыдущее сообщение здесь, но никто не дал окончательного ответа.

К счастью, есть способ, которым можно сделать это с valgrind на Linux. Во-первых, нам нужно написать "исполняемый" код, который загружает файл mex, предоставляет символ mexFunction для вызова и устанавливает параметры файла MEX. Я решил использовать рекомендованный способ сделать это с помощью MATLAB - используя MATLAB engine. Следующий код (save as 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

Профилирование файла MEX с помощью valgrind требует запуска программы "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" не будет выполнен.

Есть еще один улов. Механизм MATLAB требует установки csh в систему (вы можете использовать любую оболочку, csh просто нужно присутствовать в /bin ). Поэтому, если у вас его нет, вы должны установить его для этого.

Ответ 2

Вы можете запустить MATLAB с опцией -D, как описано в этом MatlabCentral thread:

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

Я бы добавил, чтобы убедиться, что у вас есть последняя версия valgrind. Когда я попытался отладить мой файл MEX с valgrind версии 3.6, valgrind разбился, а не сообщал о ошибках памяти.