我开始使用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是解决方案,但我使用的可能是最新版本MATLAB Version: 8.1.0.604 (R2013a) on Mac OS X Version: 10.8.4。我确实用和没有用-largeArrayDims标志编译了mex文件,但这也没有任何区别。有些人建议可以直接在cpp文件中编写函数句柄的内容,但这是不可能的,因为我想为任何具有向量输入和实数输出的用户提供此代码。
据我所知,mex文件需要通过feval函数来使用函数句柄,而m文件可以直接调用函数句柄,前提是Matlab版本比某个版本更新。
非常感谢任何帮助。
在Matlab命令行中创建的简单函数句柄:
我构建了下面的示例,在Matlab命令行中构建的函数句柄fn被传递到matlabcallingmatlab.m和mexcallingmatlab.cpp程序中。在一个新打开的Matlab中,mexcallingmatlab在241.5秒内评估了这个函数200000次,而matlabcallingmatlab在0.81522秒内评估了它,因此mex实现的速度慢了296倍。这些时间是第二次运行的结果,因为第一次运行似乎更大,可能是由于一些开销与首次加载程序等相关。
我花了很多天在网上搜索这个问题,并尝试了一些建议。我尝试了不同的mex编译标志来优化mex,但性能几乎没有差别。Stackoverflow上的一篇早期帖子指出升级Matlab是解决方案,但我使用的可能是最新版本MATLAB Version: 8.1.0.604 (R2013a) on Mac OS X Version: 10.8.4。我确实用和没有用-largeArrayDims标志编译了mex文件,但这也没有任何区别。有些人建议可以直接在cpp文件中编写函数句柄的内容,但这是不可能的,因为我想为任何具有向量输入和实数输出的用户提供此代码。
据我所知,mex文件需要通过feval函数来使用函数句柄,而m文件可以直接调用函数句柄,前提是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
mexCallMATLAB
200000 次的开销吗? - High Performance MarkmxArray
来说可能非常缓慢。因此,如果你在调用后明确清理内存,问题就会消失。请参见我下面的答案... - Amro