22

我无法解释(并避免)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 文件左右参数的所有引用。也就是说,它不接受任何输入,也不提供输出,它仅用于分析。

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

任何帮助将不胜感激,

安德鲁

4

2 回答 2

14

在与我在 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 语言实现的 Matlab 函数,然后使用 mex 编译(尤其是在动力学模型上调用 sbioaccelerate 后的 sbiosimulate,这是 SimBiology 工具箱的一部分),并且似乎有一些显着的加速。因此,2011a 更新似乎比通常的半年升级更广泛有益。

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

- 安德鲁

于 2011-04-22T16:02:18.367 回答
3

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

于 2011-03-08T16:33:11.007 回答