O arquivo mex do Matlab com mexCallMATLAB é quase 300 vezes mais lento que o arquivo m correspondente
Comecei a implementar alguns arquivos m em C ++ para reduzir os tempos de execução. Os arquivos-m produzem pontos n-dimensionais e avaliam os valores das funções nesses pontos. As funções são definidas pelo usuário e são passadas para arquivos-m e arquivos-mex como identificadores de função. Os arquivos mex usam mexCallMATLAB com feval para encontrar valores de função.
Eu construí o exemplo abaixo, onde um manipulador de função fn construído na linha de comando do Matlab é passado para as rotinas matlabcallingmatlab.m e mexcallingmatlab.cpp. Com um Matlab recém-aberto, o mexcallingmatlab avalia essa função 200000 em 241,5 segundos, enquanto o matlabcallingmatlab a avalia em 0,81522 segundo, portanto, uma desaceleração de 296 vezes com a implementação mex. Esses tempos são os resultados da segunda execução, já que as primeiras corridas parecem maiores, provavelmente devido a alguma sobrecarga associada ao carregamento pela primeira vez do programa, etc.
Passei muitos dias pesquisando on-line sobre esse problema e tentei algumas sugestões. Eu tentei mex diferentes bandeiras de compilação para otimizar o mex, mas quase não houve diferença no desempenho. Um post anterior no Stackoverflow afirmou que atualizar o Matlab era a solução, mas estou usando provavelmente a versão mais recente do MATLAB: 8.1.0.604 (R2013a) no Mac OS X Versão: 10.8.4. Eu compilei o arquivo mex com e sem sinalizador -largeArrayDims, mas isso também não fez diferença alguma. Alguns sugeriram que o conteúdo do identificador de funções poderia ser codificado diretamente no arquivo cpp, mas isso é impossível, pois eu gostaria de fornecer esse código para qualquer usuário com qualquer tipo de função com uma entrada de vetor e saída de número real.
Até onde eu descobri, os arquivos mex precisam passar pela função feval para usar um identificador de função, enquanto os arquivos m podem chamar diretamente identificadores de função desde que a versão do Matlab seja mais recente que alguma versão.
Qualquer ajuda seria muito apreciada.
manipulador de função simples criado na linha de comando do Matlab:
fn = @(x) x'*x
matlabcallingmatlab.m :
function matlabcallingmatlab( fn )
x = zeros(2,1);
for i = 0 : 199999
x(2) = i;
f = fn( x );
end
mexcallingmatlab.cpp:
#include "mex.h"
#include <cstring>
void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[] )
{
mxArray *lhs[1], *rhs[2]; //parameters to be passed to feval
double f, *xptr, x[] = {0.0, 0.0}; // x: input to f and f=f(x)
int n = 2, nbytes = n * sizeof(double); // n: dimension of input x to f
// prhs[0] is the function handle as first argument to feval
rhs[0] = const_cast<mxArray *>( prhs[0] );
// rhs[1] contains input x to the function
rhs[1] = mxCreateDoubleMatrix( n, 1, mxREAL);
xptr = mxGetPr( rhs[1] );
for (int i = 0; i < 200000; ++i)
{
x[1] = double(i); // change input
memcpy( xptr, x, nbytes ); // now rhs[1] has new x
mexCallMATLAB(1, lhs, 2, rhs, "feval");
f = *mxGetPr( lhs[0] );
}
}
Compilação do arquivo mex:
>> mex -v -largeArrayDims mexcallingmatlab.cpp