所以我尝试自己实现这个,我想我找到了缓慢的原因。
基本上你的代码有一个小的内存泄漏,你没有释放lhs
mxArray
从调用返回mexCallMATLAB。这并不完全是内存泄漏,因为 MATLAB 内存管理器会在 MEX 文件退出时释放内存:
MATLAB 分配动态内存来存储mxArrays
in plhs
。
当您清除 MEX 文件时,MATLAB 会自动释放动态内存。
但是,如果堆空间非常宝贵,请调用mxDestroyArray
什么时候
你已经完成了mxArrays
plhs
指着。
显式仍然比隐式好...所以你的代码确实给 MATLAB 内存管理器的释放器带来了压力:)
mexcallingmatlab.cpp
#include "mex.h"
#ifndef N
#define N 100
#endif
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
// validate input/output arguments
if (nrhs != 1) {
mexErrMsgTxt("One input argument required.");
}
if (mxGetClassID(prhs[0]) != mxFUNCTION_CLASS) {
mexErrMsgTxt("Input must be a function handle.");
}
if (nlhs > 1) {
mexErrMsgTxt("Too many output arguments.");
}
// allocate output
plhs[0] = mxCreateDoubleMatrix(N, 1, mxREAL);
double *out = mxGetPr(plhs[0]);
// prepare for mexCallMATLAB: val = feval(@fh, zeros(2,1))
mxArray *lhs, *rhs[2];
rhs[0] = mxDuplicateArray(prhs[0]);
rhs[1] = mxCreateDoubleMatrix(2, 1, mxREAL);
double *xptr = mxGetPr(rhs[1]) + 1;
for (int i=0; i<N; ++i) {
*xptr = i;
mexCallMATLAB(1, &lhs, 2, rhs, "feval");
out[i] = *mxGetPr(lhs);
mxDestroyArray(lhs);
}
// cleanup
mxDestroyArray(rhs[0]);
mxDestroyArray(rhs[1]);
}
MATLAB
fh = @(x) x'*x;
N = 2e5;
% MATLAB
tic
out = zeros(N,1);
for i=0:N-1
out(i+1) = feval(fh, [0;i]);
end
toc
% MEX
mex('-largeArrayDims', sprintf('-DN=%d',N), 'mexcallingmatlab.cpp')
tic
out2 = mexcallingmatlab(fh);
toc
% check results
assert(isequal(out,out2))
运行上述基准测试几次(以热身),我得到以下一致的结果:
Elapsed time is 0.732890 seconds. % pure MATLAB
Elapsed time is 1.621439 seconds. % MEX-file
与您最初度过的缓慢时光相差甚远!不过,纯 MATLAB 部分的速度大约是原来的两倍,这可能是因为调用外部 MEX 函数的开销。
(我的系统:Win8运行64位R2013a)