【问题标题】:Why don't I see a significant speed-up when using the MATLAB compiler?为什么我在使用 MATLAB 编译器时没有看到显着的加速?
【发布时间】:2010-09-13 07:32:44
【问题描述】:

我有很多很好的 MATLAB 代码,它们运行速度太慢,用 C 重写会很痛苦。C 的 MATLAB 编译器似乎没有太大帮助,如果有的话。是否应该加快执行速度?我是不是搞砸了?

标签: c performance matlab matlab-compiler


【解决方案1】:

根据我的经验,缓慢的 MATLAB 代码通常来自未对代码进行矢量化(即,编写 for 循环而不是仅仅将数组相乘(简单示例))。

如果您正在执行文件 I/O,请注意一次读取一个数据。在帮助文件中查找 fscanf 的矢量化版本。

不要忘记 MATLAB 也包含一个分析器!

【讨论】:

    【解决方案2】:

    您所说的 Matlab 编译器可能是指命令 mcc,它通过绕过 Matlab 解释器来稍微加快代码速度。显着加速 MAtlab 代码(50-200 倍)的是使用由 mex 命令编译的实际 C 代码。

    【讨论】:

      【解决方案3】:

      我会回应 dwj 所说的:如果您的 MATLAB 代码很慢,这可能是因为它没有充分矢量化。如果您在可以对整个数组执行操作时执行显式循环,那就是罪魁祸首。

      这同样适用于所有面向数组的动态语言:Perl 数据语言、Numeric Python、MATLAB/Octave 等。在编译的 C 和 FORTRAN 编译的代码中甚至在某种程度上是正确的:专门设计的向量化库通常使用小心手-编码的内部循环和 SIMD 指令(例如 MMX、SSE、AltiVec)。

      【讨论】:

        【解决方案4】:

        正如其他人所指出的,缓慢的 Matlab 代码通常是向量化不足的结果。

        但是,有时即使是完美的矢量化代码也很慢。然后,您还有更多选择:

        1. 看看是否有可以使用的库/工具箱。这些通常写得非常优化。
        2. 分析您的代码,找到漏洞并用纯 C 重写这些代码。将 C 代码(例如 DLL)连接到 Matlab 很容易,文档中对此进行了介绍。

        【讨论】:

          【解决方案5】:

          如果您使用的是MATLAB complier(在最新版本的 MATLAB 上),那么您几乎肯定不会看到任何加速。这是因为编译器实际上所做的只是为您提供了一种打包代码的方法,以便可以将其分发给没有 MATLAB 的人。它不会将它转换为更快的东西(例如机器代码或 C)——它只是将它包装在 C 中以便你可以调用它。

          它通过让您的代码在本质上是 MATLAB 计算内核的 MATLAB Compiler Runtime (MCR) 上运行来实现 - 您的代码仍在被解释。由于必须调用 MCR 所带来的损失,您可能会发现编译后的代码比在 MATLAB 上运行时运行得更慢。

          换一种说法 - 你可能会说编译器实际上并没有编译 - 至少在这个词的传统意义上。

          旧版本的编译器工作方式不同,在某些情况下可能会出现加速。对于 Mathwork 对此的看法,请访问

          http://www.mathworks.com/support/solutions/data/1-1ARNS.html

          【讨论】:

            【解决方案6】:

            mcc 根本不会加速你的代码——它不是真正的编译器。

            在你放弃之前,你需要运行分析器并弄清楚你所有的时间都花在了哪里(工具->打开分析器)。此外,明智地使用“tic”和“toc”会有所帮助。在你知道时间在哪里之前不要优化你的代码(不要试图猜测)。

            请记住,在 matlab 中:

            • 位级操作真的很慢
            • 文件 I/O 很慢
            • 循环通常很慢,但向量化很快(如果您不了解向量语法,请学习)
            • 核心运算速度非常快(例如矩阵乘法、fft)
            • 如果您认为可以在 C/Fortran/etc 中更快地完成某些事情,您可以编写一个 MEX 文件
            • 有将 matlab 转换为 C 的商业解决方案(谷歌“matlab to c”)并且它们有效

            【讨论】:

              【解决方案7】:

              首先,我对上面所有关于剖析和矢量化的 cmets 表示赞同。

              从历史的角度来看...

              旧版本的 Matlab 允许用户通过预先解析 m 代码并将其转换为一组 matlab 库调用,将 m 文件转换为 mex 函数。这些调用具有解释器所做的所有错误检查,但旧版本的解释器和/或在线解析器速度很慢,因此编译 m 文件有时会有所帮助。通常当你有循环时它会有所帮助,因为 Matlab 足够聪明,可以在 C 中内联其中的一些。如果你有这些版本的 Matlab 之一,你可以尝试告诉 mex 脚本保存 .c 文件,你可以确切地看到它是什么正在做。

              在更新的版本中(可能是 2006a 及更高版本,但我不记得了),Mathworks 开始使用即时编译器作为解释器。实际上,这个 JIT 编译器会自动编译所有 mex 函数,因此显式地离线执行它根本没有帮助。从那时起,在每个版本中,他们也付出了很多努力来提高解释器的速度。我相信较新版本的 Matlab 甚至不允许您将 m 文件自动编译为 mex 文件,因为它不再有意义。

              【讨论】:

                【解决方案8】:

                您是否尝试过分析您的代码?你不需要向量化你的所有代码,只需要控制运行时间的函数。 MATLAB 分析器将为您提供一些关于您的代码花费最多时间的提示。

                您应该阅读 MathWorks 手册中的 Tips For Improving Performance 部分的许多其他内容。

                【讨论】:

                  【解决方案9】:

                  您可以将您的代码移植到“Embedded Matlab”,然后使用 Realtime-Workshop 将其翻译成 C。

                  嵌入式 Matlab 是 Matlab 的一个子集。它不支持单元阵列、图形、动态大小的 Marice 或某些矩阵寻址模式。移植到嵌入式 Matlab 可能需要付出相当大的努力。

                  Realtime-Workshop 是代码生成产品的核心。它提供通用 C,或者可以针对一系列嵌入式平台进行优化。您最感兴趣的可能是 xPC-Target,它将通用硬件视为嵌入式目标。

                  【讨论】:

                    【解决方案10】:

                    MATLAB 编译器封装您的 m 代码并将其分派到 MATLAB 运行时。因此,您在 MATLAB 中看到的性能应该是您在编译器中看到的性能。

                    根据其他答案,对代码进行矢量化很有帮助。但是,如今 MATLAB JIT 已经相当不错了,而且很多东西在矢量化方面的表现大致相同。这并不是说矢量化没有性能优势,只是它不再是曾经的灵丹妙药。真正分辨的唯一方法是使用分析器找出您的代码在哪里遇到瓶颈。通常,您可以在某些地方进行本地重构以真正提高代码的性能。

                    您可以采用其他几种硬件方法来提高性能。首先,大部分线性代数子系统都是多线程的。如果您在多核或多处理器平台上工作,您可能需要确保已在首选项中启用该功能。其次,您可以使用并行计算工具箱来更多地利用多个处理器。最后,如果您是 Simulink 用户,您也许可以使用 emlmex 将 m-code 编译成 c。这对于定点工作特别有效。

                    【讨论】:

                      【解决方案11】:

                      我会投票支持分析 + 然后看看瓶颈是什么。

                      如果瓶颈是矩阵数学,你可能不会做得更好......除了一个大问题是数组分配。例如如果你有一个循环:

                      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 已经在 J​​VM 上运行,并且它非常容易与任意 JAR 文件接口。我查看了与 C/C++ 的接口,它真的很难看。 Microsoft COM 还可以(仅在 Windows 上),但在学习 Java 之后,我想我再也不会回到那个了。

                      【讨论】:

                        猜你喜欢
                        • 2013-05-15
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2014-10-08
                        • 2016-02-18
                        • 1970-01-01
                        相关资源
                        最近更新 更多