Matlab:从循环中重复调用相同的mex函数会产生太多的开销吗?

sun*_*ica 8 performance matlab mex

我有一些需要加速的Matlab代码.通过分析,我已经确定了一个特定的函数作为减慢执行速度的罪魁祸首.这个函数在循环中被调用了数十万次.

我的第一个想法是将函数转换为mex(使用Matlab Coder)来加速它.然而,常见的编程意义告诉我Matlab和mex代码之间的接口会导致一些开销,这意味着调用这个mex函数数千次可能不是一个好主意.它是否正确?或者Matlab在重复调用相同的mex以消除开销时会做些什么?

如果显著的开销,我想重新编写代码,以增加循环函数本身和创造的一个MEX.在此之前,我想验证我的假设,以证明花在此上的时间.

更新:

我尝试了@ angainor的建议,并使用以下代码创建了donothing.m:

function nothing = donothing(dummy) %#codegen
nothing = dummy;
end
Run Code Online (Sandbox Code Playgroud)

然后,我创建了一个mex函数作为donothing_mex,并尝试了以下代码:

tic;
for i=1:1000000
    donothing_mex(5);
end
toc;
Run Code Online (Sandbox Code Playgroud)

结果是,对该功能的一百万次调用大约需要9秒.这对我们来说并不是一个重要的开销,所以现在我想我会将被调用的函数单独转换为mex.但是,从一个执行大约一百万次的循环调用一个函数回想起来似乎是一个非常愚蠢的想法,考虑到这是性能关键代码,所以将循环移动到mex函数仍然在书中,但优先级要低得多.

ang*_*nor 5

像往常一样,这一切都取决于你在MEX文件中的工作量.调用MEX函数的开销是恒定的,并且不依赖于例如问题的大小.这意味着参数不会复制到新的临时数组.因此,如果它足够工作,则不会显示调用MEX文件的MATLAB开销.无论如何,根据我的经验,MEX调用开销仅在第一次调用mex函数时才有意义 - 必须加载动态库,解析符号等.后续MEX调用具有非常小的开销并且非常有效.

由于这种高级语言的性质,几乎MATLAB中的所有内容都会产生一些开销.除非你有一个代码,你确定它是用JIT完全编译的(但是你不需要mex文件:))所以你可以选择一个开销而不是另一个...

总结一下 - 我不会太害怕MEX呼叫开销.

编辑正如在这里和其他地方经常听到的那样,在任何特定情况下唯一合理的做法当然是BENCHMARK并为您自己检查.您可以通过编写一个简单的MEX函数轻松估计MEX调用开销:

#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[ ], int nrhs, const mxArray *prhs[ ]) 
{      
}
Run Code Online (Sandbox Code Playgroud)

在我的电脑上你得到

tic; for i=1:1000000; mexFun; end; toc
Elapsed time is 2.104849 seconds.
Run Code Online (Sandbox Code Playgroud)

这是每个MEX呼叫的2e-6s开销.添加您的代码,计时并查看开销是否处于可接受的水平.

正如Andrew Janke在下面提到的那样(谢谢!),MEX函数开销显然取决于传递给MEX函数的参数数量.这是一个小依赖,但它是:

a = ones(1000,1);
tic; for i=1:1000000; mexFun(a); end; toc
Elapsed time is 2.41 seconds.
Run Code Online (Sandbox Code Playgroud)

它与大小无关a:

a = ones(1000000,1);
tic; for i=1:1000000; mexFun(a); end; toc
Elapsed time is 2.41805 seconds.
Run Code Online (Sandbox Code Playgroud)

但它与论点的数量有关

a = ones(1000000,1);
b = ones(1000000,1);
tic; for i=1:1000000; mexFun(a, b); end; toc
Elapsed time is 2.690237 seconds.
Run Code Online (Sandbox Code Playgroud)

因此,您可能希望在测试中考虑到这一点.