我开始在 C++ 中实现一些 m 文件以减少运行时间。m 文件生成 n 维点并评估这些点的函数值。这些函数是用户定义的,它们作为函数句柄传递给 m 文件和 mex 文件。mex 文件使用 mexCallMATLAB 和 feval 来查找函数值。
我构造了下面的示例,其中将在 Matlab 命令行中构造的函数句柄 fn 传递给 matlabcallingmatlab.m 和 mexcallingmatlab.cpp 例程。使用新打开的 Matlab,mexcallingmatlab 在 241.5 秒内评估此函数 200000,而 matlabcallingmatlab 在 0.81522 秒内评估它,因此使用 mex 实现慢了 296 倍。这些时间是第二次运行的结果,因为第一次运行似乎更大,可能是由于第一次加载程序等相关的一些开销。
我花了很多天在网上搜索这个问题并尝试了一些建议。我尝试了不同的 mex 编译标志来优化 mex,但性能几乎没有差异。Stackoverflow 上的一篇文章指出升级 Matlab 是解决方案,但我在 Mac OS X 版本:10.8.4 上使用的可能是最新版本的 MATLAB 版本:8.1.0.604 (R2013a)。我确实编译了带有和不带有 –largeArrayDims 标志的 mex 文件,但这也没有任何区别。有人建议函数句柄的内容可以直接编码在 cpp 文件中,但这是不可能的,因为我想将此代码提供给任何具有向量输入和实数输出的任何类型函数的用户。
据我所知,mex 文件需要通过 feval 函数才能使用函数句柄,而 m-files 可以直接调用函数句柄,前提是 Matlab 版本比某些版本更新。
任何帮助将不胜感激。
在 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] );
}
}
mex文件的编译:
>> mex -v -largeArrayDims mexcallingmatlab.cpp