【问题标题】:Speedup Matlab to C++ Conversion加速 Matlab 到 C++ 的转换
【发布时间】:2010-11-16 20:02:19
【问题描述】:

我有一些运行速度很慢的 Matlab 图像处理代码,我准备将其转换为 C/C++。我不太了解 matlab 的工作原理以及代码的执行方式,但我只是想听听我可能期望什么样的加速。显然有很多变量会影响这一点,但我只是在寻找可能来自您自己经验的指南。

谢谢

泽娜

【问题讨论】:

  • 嗯...一些代码示例会很好。您不能在 Matlab 中采用缓慢而蹩脚的算法并期望转换使其快速。你可能不是在和解释器作斗争,可能是算法

标签: c++ performance matlab image-processing


【解决方案1】:

这实际上取决于您的 Matlab 代码的质量以及您正在做什么。由 Matlab 专家编写的惯用 Matlab 代码将很难被击败,特别是如果您不是优化专家并且纯粹期望由于语言切换而加快速度。例如,我发现即使是一些更受好评的基于 C 的 FFT 库也无法与 Matlab 的 FFT 匹敌。

也就是说,将一个写得不好的 Matlab 程序与一个写得一般的 C++ 程序进行比较,我想说的是,根据我的经验,你看到的是一个数量级。

【讨论】:

  • 对于 FFT,Matlab 使用 FFTW(“西方最快的傅立叶变换”,参见 fftw.org),它是用 C 实现的(实际上是由 Objective Caml 生成的 C 代码,参见 fftw.org/pldi99.pdf )。
【解决方案2】:

您可能会获得什么样的加速问题的简短回答是“取决于”。

Matlab 是一个解释器,因此总体上它比原生 c++ 代码慢得多。但是,很多matlab函数都进行了很好的优化,最近的版本包括了JIT。所以你必须决定是用 C 重写你所有的 matlab 代码,只重写关键部分,还是优化 matlab 代码本身以更快地运行。

我建议您首先使用 Matlab 的内置分析工具来查找应用程序中的性能瓶颈。您可能会调整 matlab 代码以获得更好的性能。经验法则是通过使用向量化数组操作而不是一次迭代一个元素来避免循环。

【讨论】:

  • 随着 JIT 加速器的引入,“for 循环惩罚”不再像过去那样受到关注。使用分析器找到真正的瓶颈。
【解决方案3】:

例如 matlab 使用 FFTW 库来实现 fft 算法。该库的性能几乎无法被击败。我所知道的唯一具有可比性的是英特尔数学内核库(MKL),但它是商业的。所以首先我建议使用你能找到的每一个数学库。 Matlab 是在幕后做的。

确实有时很难击败matlab。但问题是,matlab 分析器并不总是为您提供有关如何改进代码的足够信息。您知道某些 matlab 方法占用了大部分时间,但您并不总是知道是否有方法可以提高性能以另一种方式调用它们,因为该方法是一个黑盒。

在 C/C++ 中,您拥有像 valgirnd 这样的工具,即使编译器正在生成汇编程序,您也可以进行检查,这样您就可以帮助编译器改进内联方法的代码。但是 matlab 再次在幕后使用专业的数学库,如果在执行 matlab 代码时大部分时间都花在这些库上,那么性能很难提高。

我希望你可以尝试不同的方法。您可以使用 matlab profiler 分析瓶颈,看看是否值得将该代码移至本机代码。 Matlab 允许你这样做。你也可以反过来做。您可以在 C/C++ 中实现一些胶水,并为某些操作调用 matlab,在这些操作中您体验到本机代码比 matlab 慢。

【讨论】:

    【解决方案4】:

    对于图像处理,您可以获得显着的加速。但这实际上取决于您编写 MATLAB 代码的能力。很多东西可以被矢量化或通过内置函数来处理。这种代码速度很快。

    但是,如果您发现您的代码包含大量循环(例如,循环遍历图像中的所有像素),它将非常缓慢,并且矢量化可以提供 100 倍或更多的加速。

    如果您的代码很难在 MATLAB 中“正确”执行,那么切换到 C 可能是一个可行的选择。我在学校做了一个计算机视觉项目(3D 点重建),清楚地表明了这一点。当我们用 C++ 和 OpenCV 实现的项目完成计算时,其他组中的一个项目甚至还没有加载图像。他们是用 MATLAB 编写的。我们从未计时,但我猜测是我们的版本运行速度快了大约 10 倍。

    但话又说回来,他们的 MATLAB 代码可能根本没有优化。因此,它作为基准并不是真正有用的。

    【讨论】:

    • 随着 JIT 加速器的引入,“for 循环惩罚”不再像过去那样受到关注。使用分析器找到真正的瓶颈。
    • 是的,我也听说过。不幸的是,我还没有使用最新的 MATLAB 版本的乐趣:(
    【解决方案5】:

    这主要取决于您在 Matlab 中循环的紧密程度。如果你只是简单地调用一系列内置的 Matlab 图像处理函数,你很可能无法提高性能(很可能会伤害它)。如果您正在循环图像像素或进行某种块处理,您可能会看到很大的改进。如果您正在执行一些循环,但每次迭代中的处理量很大,您可能只会看到很少或没有改进。

    我对 Matlab 的看法是,每条执行的行都有一定的开销。如果您可以将解决方案转换为矩阵乘法或其他一些向量/矩阵运算的形式,那么您只会遭受一次开销,并且可以忽略不计。但是,对于循环,每次循环迭代时都会产生开销。此外,Matlab 的大多数图像处理函数只是调用优化的库,所以不要尝试重新创建它们,除非您确定可以改进它们的地方。

    我发现最好的方法是结合使用 C 和 Matlab。当操作可以很容易地向量化(就向量/矩阵操作而言)时,我使用 Matlab。这可能意味着从与最直接的角度不同的角度来解决问题。此外,很难击败 Matlab 的绘图和可视化,所以我绝对不会转向全 C/C++ 解决方案,除非您有如何使用 C/C++ 显示的计划(如果这是您项目的一部分)。

    如果我不能想出一个相对简单的矢量化方法,我只需在可以从 Matlab 调用的 C mex 函数中实现需要紧密循环的处理部分。在这种情况下,我倾向于使用 C 而不是 C++,因为该过程应该相对较小并且不需要大量复杂的数据抽象,但 C++ 也可以正常工作。确保以列优先顺序访问图像数据以最大化缓存命中,因为这是 Matlab 组织其矩阵的方式。

    【讨论】:

    • 随着 JIT 加速器的引入,“for 循环惩罚”不再像过去那样受到关注。使用分析器找到真正的瓶颈。
    • 是的,我肯定会先走这条路,但我仍然发现有优化的 C 语言会更好。不过,这可能只是我对利用 JIT 编译器的有限了解。话虽如此,避免使用 Matlab 可以做得更好或更好的 C/C++ 是个好主意。
    • @MatlabDoug:您能否扩展 JIT 加速器和分析器?我做了很多 MATLAB 编程,但我从未听说过这些,但它们听起来很有趣。也许你可以提供几个链接?谢谢。
    【解决方案6】:

    正如其他人所说,使用 MATLAB 分析器来查看瓶颈是什么。如果它是矩阵数字运算,那么你有一个相当高的标准可以跳过来击败 MATLAB。如果您有很多条件语句或函数调用,则更有可能提高您的速度。

    确保尽量减少在 MATLAB 和 C++ 之间传输数据的次数。如果您要在一大堆中发送大型数据数组,它可能会很快。否则,如果你进行大量的数据来回传输,即使你的 C++ 程序速度很快,也可能会失去数据转换的速度优势。

    我还会查看您的算法并考虑使用 Java。从 MATLAB 调用自定义 Java 代码非常方便,因为 MATLAB 已经在 J​​RE 上运行。在 MATLAB 函数和我的自定义 Java 代码之间传输大型数据数组的速度给我留下了深刻的印象。几年前,我曾研究过用纯 C++(使用 MEX 或其他)实现一个算法来加速 MATLAB,而处理所有数据结构看起来就像一场噩梦。我最终改用 COM/ActiveX,因为我在 Windows 机器上运行,而且接口更容易。

    在完成大量低级编程来解决数值问题后,我对可能出现的问题有了更好的了解,从数值准确性到编程维护问题,除非有巨大的性能优势,否则我会选择比 C/C++ 更高级的语言。

    【讨论】:

      【解决方案7】:

      我在 c++ 中导出了一个 matlab 例程,并使用 Visual Studio c++ 作为 mex 进行编译。加速是 10 倍。如果我使用多核,那么我的速度可能也会提高 3 倍。

      如果你在斜坡中有斜坡并且对矩阵的单个分量做一些事情,比如 y(m,n) = x(m) * a - x(m-1) 和这个对于斜坡,那么你会加快速度。

      如果你使用很多matlab函数进行计算,而matlab函数本身做了很多操作,那么用c++导出代码就没有意义了。

      【讨论】:

        猜你喜欢
        • 2017-08-19
        • 1970-01-01
        • 1970-01-01
        • 2014-12-30
        • 2013-03-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-05
        相关资源
        最近更新 更多