Matlab mex 文件比它的直接 C 等效文件慢

Posted

技术标签:

【中文标题】Matlab mex 文件比它的直接 C 等效文件慢【英文标题】:Matlab mex file is slow compared to its straight C equivalent 【发布时间】:2011-07-10 20:19:47 【问题描述】:

我无法解释(并避免)Matlab mex 程序和没有 Matlab 接口的相应 C 程序之间的速度差异。我一直在分析一个数值分析程序:

int main()

Well_optimized_code();


使用 gcc 4.4 针对 Matlab-Mex 等价物进行编译(直接使用 gcc44,这不是 Matlab 当前支持的版本,但出于其他原因需要它):

void mexFunction(int nlhs,mxArray* plhs[], int nrhs, const mxArray* prhs[])

Well_optimized_code(); //literally the exact same code


我的时间安排如下:

$ time ./C_version

对比

>> tic; mex_version(); toc

时间上的差异是惊人的。从命令行运行的版本平均需要 5.8 秒。 Matlab 中的版本运行时间为 21 秒。就上下文而言,mex 文件替换了 SimBiology 工具箱中运行大约需要 26 秒的算法。

与 Matlab 的算法相比,C 和 mex 版本都使用对 openMP 的调用线性扩展至最多 27 个线程,但出于分析目的,这些调用已被禁用并被注释掉。

除了编译为 mex 文件所需的标志外,两个版本的编译方式相同: -fPIC --shared -lmex -DMATLAB_MEX_FILE 应用于 mex 编译/链接。我已经删除了对 mex 文件左右参数的所有引用。也就是说,它不接受任何输入,也不提供输出,它只是用于分析。

伟大而光荣的 Google 告诉我,与位置无关的代码不应该是减速的根源,除此之外我不知所措。

任何帮助将不胜感激,

安德鲁

【问题讨论】:

最初的猜测可能是应用于可执行文件的优化并未应用于共享库。如何让您的可执行文件调用 MEX 函数而不是包含代码本身?这可能有助于找出性能瓶颈所在。 @Pablo 我不确定你的意思。如何让可执行文件在不进入 Matlab 的情况下调用 mex 函数? MEX 文件只是一个共享库(.dll 或 .so),它导出一个众所周知的函数,即 mexFunction。您可以这样做,以便您的可执行文件加载共享库并在其中调用 mexFunction。这样,您为 Well_optimized_code() 运行的代码应该是相同的。 matlab 下的内存分配器的行为与独立环境下的内存分配器的行为不同,这似乎是合理的。你能修改优化后的代码以不同的方式使用内存吗?此外,减速是在您使用该功能时发生,还是仅在第一次出现? @Alex 它一直在发生。我报告的时间来自第一次之后的电话。虽然平均而言,第一次通话似乎较慢,但并非如此。谢谢你的想法。 【参考方案1】:

在与我在 Mathworks 的联系人通过电子邮件发送一个月后,使用我自己的代码,并以各种方式分析我的代码,我得到了答案;然而,这可能是我对技术问题的最不满意的答案:

简短版是“升级到Matlab 2011a版(上周正式发布),这个问题现在已经解决了”。

较长的版本涉及与 2010b 及更早版本中的 mex 网关相关的开销问题。我能够提取的最好的解释是,这种开销不会被评估一次,而是每次函数调用链接库中的另一个函数时我们都会支付一点。

虽然这让我感到困惑,但它至少与我所做的 SHARK 分析一致。当我分析和比较本机应用程序和 mex 应用程序之间的差异时,会出现一个反复出现的模式。我为应用程序编写的源代码中的函数所花费的时间没有改变。在本机实现和 mex 实现之间进行比较时,花费在库函数上的时间略有增加。用于构建此库的另一个库中的函数大大增加了差异。随着我们越来越深入,时间差会继续增加,直到我们通过 BLAS 实现。

几个大量使用的 BLAS 函数是罪魁祸首。在本机应用程序中占用我约 1% 计算时间的函数在 mex 函数中以 30% 的时间运行。

mex 网关的实施似乎在 2010b 和 2011a 之间发生了变化。在我的 macbook 上,本机应用程序大约需要 6 秒,而 mex 版本需要 6.5 秒。这是我可以处理的开销。

至于根本原因,我只能推测。 Matlab 源于解释性编码。由于 mex 函数是动态库,我猜每个 mex 库直到运行时才知道它所链接的内容。由于 Matlab 建议用户很少使用 mex,然后仅用于小型计算密集型块,我假设很少实现大型程序(例如 ODE 求解器)。这些程序和我的程序一样,是受害最严重的程序。

我已经分析了几个我知道用 C 语言实现然后使用 mex 编译的 Matlab 函数(尤其是在动力学模型上调用 sbioaccelerate 后的 sbiosimulate,这是 SimBiology 工具箱的一部分),并且似乎有一些显着的加速。因此,2011a 更新似乎比通常的半年升级更广泛有益。

祝其他遇到类似问题的程序员好运。感谢所有帮助我朝着正确方向迈进的有用建议。

--安德鲁

【讨论】:

【参考方案2】:

回想一下,Matlab 将数组存储为主要列,而 C/C++ 存储为主要行。您的循环结构/算法是否有可能以行主要方式迭代,导致 Matlab 中的内存访问时间很短,但 C/C++ 中的访问时间很快?

【讨论】:

我只有从 C++ 调用 matlab 的经验(即:不是 MEX),而且我已经被 col/row 的主要混淆所困扰。发生了什么事……问题是什么?我以前见过不正确的索引会导致这些速度差异。我知道 mxArray* 是 col-major 的。因此,如果不考虑这一点.... //edit bleh,请尽早按 Enter。 @Chris 我读到 OP 甚至没有使用发送到 mex 文件的参数。如果他是,那么他的问题就错了! @Chris 出于分析的目的,我没有使用传递给 mex 函数的参数,并且它与 mx 或 mex 例程没有接口。我还对必须处理行/列排序的代码部分进行了计时,它们占用的计算量不到总计算量的 0.5%。这也是我的第一个猜测。 啊,有趣。我喜欢@pablo的建议。祝你好运!

以上是关于Matlab mex 文件比它的直接 C 等效文件慢的主要内容,如果未能解决你的问题,请参考以下文章

使用 Matlab Coder 将 Matlab m 文件转换为 C/C++ 代码,包括 mex 文件 (mxArray)

尝试在 MatLab 中编译 C mex 文件

MATLAB mex文件

matlab中imagesc如何用C语言去实现

matlab中的plot函数怎样在c语言中实现

Matlab调用C程序