【发布时间】:2010-09-13 07:32:44
【问题描述】:
我有很多很好的 MATLAB 代码,它们运行速度太慢,用 C 重写会很痛苦。C 的 MATLAB 编译器似乎没有太大帮助,如果有的话。是否应该加快执行速度?我是不是搞砸了?
标签: c performance matlab matlab-compiler
我有很多很好的 MATLAB 代码,它们运行速度太慢,用 C 重写会很痛苦。C 的 MATLAB 编译器似乎没有太大帮助,如果有的话。是否应该加快执行速度?我是不是搞砸了?
标签: c performance matlab matlab-compiler
根据我的经验,缓慢的 MATLAB 代码通常来自未对代码进行矢量化(即,编写 for 循环而不是仅仅将数组相乘(简单示例))。
如果您正在执行文件 I/O,请注意一次读取一个数据。在帮助文件中查找 fscanf 的矢量化版本。
不要忘记 MATLAB 也包含一个分析器!
【讨论】:
您所说的 Matlab 编译器可能是指命令 mcc,它通过绕过 Matlab 解释器来稍微加快代码速度。显着加速 MAtlab 代码(50-200 倍)的是使用由 mex 命令编译的实际 C 代码。
【讨论】:
我会回应 dwj 所说的:如果您的 MATLAB 代码很慢,这可能是因为它没有充分矢量化。如果您在可以对整个数组执行操作时执行显式循环,那就是罪魁祸首。
这同样适用于所有面向数组的动态语言:Perl 数据语言、Numeric Python、MATLAB/Octave 等。在编译的 C 和 FORTRAN 编译的代码中甚至在某种程度上是正确的:专门设计的向量化库通常使用小心手-编码的内部循环和 SIMD 指令(例如 MMX、SSE、AltiVec)。
【讨论】:
正如其他人所指出的,缓慢的 Matlab 代码通常是向量化不足的结果。
但是,有时即使是完美的矢量化代码也很慢。然后,您还有更多选择:
【讨论】:
如果您使用的是MATLAB complier(在最新版本的 MATLAB 上),那么您几乎肯定不会看到任何加速。这是因为编译器实际上所做的只是为您提供了一种打包代码的方法,以便可以将其分发给没有 MATLAB 的人。它不会将它转换为更快的东西(例如机器代码或 C)——它只是将它包装在 C 中以便你可以调用它。
它通过让您的代码在本质上是 MATLAB 计算内核的 MATLAB Compiler Runtime (MCR) 上运行来实现 - 您的代码仍在被解释。由于必须调用 MCR 所带来的损失,您可能会发现编译后的代码比在 MATLAB 上运行时运行得更慢。
换一种说法 - 你可能会说编译器实际上并没有编译 - 至少在这个词的传统意义上。
旧版本的编译器工作方式不同,在某些情况下可能会出现加速。对于 Mathwork 对此的看法,请访问
http://www.mathworks.com/support/solutions/data/1-1ARNS.html
【讨论】:
mcc 根本不会加速你的代码——它不是真正的编译器。
在你放弃之前,你需要运行分析器并弄清楚你所有的时间都花在了哪里(工具->打开分析器)。此外,明智地使用“tic”和“toc”会有所帮助。在你知道时间在哪里之前不要优化你的代码(不要试图猜测)。
请记住,在 matlab 中:
【讨论】:
首先,我对上面所有关于剖析和矢量化的 cmets 表示赞同。
从历史的角度来看...
旧版本的 Matlab 允许用户通过预先解析 m 代码并将其转换为一组 matlab 库调用,将 m 文件转换为 mex 函数。这些调用具有解释器所做的所有错误检查,但旧版本的解释器和/或在线解析器速度很慢,因此编译 m 文件有时会有所帮助。通常当你有循环时它会有所帮助,因为 Matlab 足够聪明,可以在 C 中内联其中的一些。如果你有这些版本的 Matlab 之一,你可以尝试告诉 mex 脚本保存 .c 文件,你可以确切地看到它是什么正在做。
在更新的版本中(可能是 2006a 及更高版本,但我不记得了),Mathworks 开始使用即时编译器作为解释器。实际上,这个 JIT 编译器会自动编译所有 mex 函数,因此显式地离线执行它根本没有帮助。从那时起,在每个版本中,他们也付出了很多努力来提高解释器的速度。我相信较新版本的 Matlab 甚至不允许您将 m 文件自动编译为 mex 文件,因为它不再有意义。
【讨论】:
您是否尝试过分析您的代码?你不需要向量化你的所有代码,只需要控制运行时间的函数。 MATLAB 分析器将为您提供一些关于您的代码花费最多时间的提示。
您应该阅读 MathWorks 手册中的 Tips For Improving Performance 部分的许多其他内容。
【讨论】:
您可以将您的代码移植到“Embedded Matlab”,然后使用 Realtime-Workshop 将其翻译成 C。
嵌入式 Matlab 是 Matlab 的一个子集。它不支持单元阵列、图形、动态大小的 Marice 或某些矩阵寻址模式。移植到嵌入式 Matlab 可能需要付出相当大的努力。
Realtime-Workshop 是代码生成产品的核心。它提供通用 C,或者可以针对一系列嵌入式平台进行优化。您最感兴趣的可能是 xPC-Target,它将通用硬件视为嵌入式目标。
【讨论】:
MATLAB 编译器封装您的 m 代码并将其分派到 MATLAB 运行时。因此,您在 MATLAB 中看到的性能应该是您在编译器中看到的性能。
根据其他答案,对代码进行矢量化很有帮助。但是,如今 MATLAB JIT 已经相当不错了,而且很多东西在矢量化方面的表现大致相同。这并不是说矢量化没有性能优势,只是它不再是曾经的灵丹妙药。真正分辨的唯一方法是使用分析器找出您的代码在哪里遇到瓶颈。通常,您可以在某些地方进行本地重构以真正提高代码的性能。
您可以采用其他几种硬件方法来提高性能。首先,大部分线性代数子系统都是多线程的。如果您在多核或多处理器平台上工作,您可能需要确保已在首选项中启用该功能。其次,您可以使用并行计算工具箱来更多地利用多个处理器。最后,如果您是 Simulink 用户,您也许可以使用 emlmex 将 m-code 编译成 c。这对于定点工作特别有效。
【讨论】:
我会投票支持分析 + 然后看看瓶颈是什么。
如果瓶颈是矩阵数学,你可能不会做得更好......除了一个大问题是数组分配。例如如果你有一个循环:
s = [];
for i = 1:50000
s(i) = 3;
end
这必须不断调整数组的大小;预先确定数组的大小(从零或 NaN 开始)并从那里填充它要快得多:
s = zeros(50000,1);
for i = 1:50000
s(i) = 3;
end
如果瓶颈是重复执行大量函数调用,那就很难了。
如果瓶颈是 MATLAB 无法快速完成的事情(某些类型的解析、XML 等),那么我会使用 Java,因为 MATLAB 已经在 JVM 上运行,并且它非常容易与任意 JAR 文件接口。我查看了与 C/C++ 的接口,它真的很难看。 Microsoft COM 还可以(仅在 Windows 上),但在学习 Java 之后,我想我再也不会回到那个了。
【讨论】: