【问题标题】:Performance Tradeoff - When is MATLAB better/slower than C/C++性能权衡 - MATLAB 何时比 C/C++ 更好/更慢
【发布时间】:2013-12-29 01:37:50
【问题描述】:

我知道 C/C++ 是一种低级语言,与任何其他高级语言相比,它会生成相对优化的机器代码。但我想还有很多,这从实践中也可以看出。

当我进行简单的计算(例如对高斯样本集合进行蒙特卡罗平均)时,我发现 C++ 实现或 MATLAB 实现之间没有太大区别,有时实际上 MATLAB 在时间上表现得更好。

当我继续使用数千行代码进行更大规模的模拟时,真实的画面会慢慢出现。 C++ 仿真显示出卓越的性能,例如在时间复杂度上比等效的 MATLAB 实现好 100 倍。

大多数时候,C++ 中的代码几乎是串行的,没有明确地进行高保真优化。然而,据我所知,MATLAB 本质上做了很多优化。例如,当我尝试生成大量随机样本时就会出现这种情况,而使用 IT++/GSL/Boost 等库的 C++ 中的等价物执行相对较慢(使用的算法相同,即 mt19937)。

我的问题只是想知道 MATLAB/C++ 在性能上是否存在更简单的权衡。是不是就像人们说的,“只要有可能,C/C++ 就更好”(经常遇到的)?换个角度来看,“MATLAB 除了舒适还有什么用处?”

顺便说一句,我认为编码效率参数在这里并不重要,因为在这两种情况下都是同一个程序员。而且,我认为像 python,R 这样的其他替代品在这里不相关。但是对我们使用的特定库的依赖应该很有趣。

[我是通信系统编码理论的博士生。我一直使用 matlab/C++ 进行模拟,并且在这两种情况下都有编写几万行代码的合理经验]

【问题讨论】:

  • 嗯,从性能的角度来看,matlab 更好,当你知道如何编码时,不知道如何编码 c++,其余时间 c++ 更好。
  • 我已经完成了 matlab 到 C++ 的翻译。对“普通”matlab 代码的典型期望是 C++ 的速度要快 20 倍。
  • @Richard 是的,我忽略了这方面只是为了避免太多问题。我相信这个翻译提供了一个很好的见解。但我主要尝试关注 Matlab 与 C++ 的“原因和时间”。
  • 我要提一下 MATLAB 的优点在于它的所有库都使用了相当强大的实现,因此您不必担心数值稳定性和选择哪种算法。另一方面,C++ 库可以提供所有相同的奢侈品……
  • MATLAB 中的许多关键部分都使用某种本机库(内部开发或使用 3rd 方库),并以编译语言(C/C++、Fortran)实现。例如,简单的 backslash operator x = A\b 实际上是十几种可能的底层实现的前端。对于在纯 MATLAB 中实现的其他部分,JIT 编译器有助于降低解释语言的成本。 MATLAB 也经常鼓励编写向量化代码(想想 SIMD 指令)。最后,GUI 的东西大部分是用 Java 实现的。

标签: c++ c performance matlab


【解决方案1】:

作为一名博士生,以及 10 年的 Matlab 用户,我很高兴分享我的 POV:

Matlab 是用于开发和原型设计算法的绝佳工具,尤其是在处理 GUI、高级分析(频域、LS 优化等)时:快速编码、强大的语法(想想 []、{} 等) .).

一旦您的处理链更加稳定和定义明确并且数据维度增长,就转移到 C/C++。

当考虑到它的语言类似于脚本时,主要的 Matlab 限制会上升:只要避免任何循环(使用 arrayfun、cellfun 或其他矩阵程序),性能就会很高,因为调用的子程序又是 C/C++。

【讨论】:

    【解决方案2】:

    我已经使用 Matlab 和 C++ 大约 10 年了。对于为我的研究实现的每种数值算法,我总是从使用 Matlab 进行原型设计开始,然后将项目转换为 C++,以获得 10 倍到 100 倍(我不是在开玩笑)的性能提升。当然,我将优化的 C++ 代码与完全矢量化的 Matlab 代码进行比较。平均而言,改进约为 50 倍。

    这两种编程语言背后都有很多微妙之处,以下是一些误解:

    1. Matlab 是一种脚本语言,但 C++ 是编译的

      Matlab 使用 JIT 编译器将您的脚本翻译成机器码,使用 Matlab 提供的编译器,您最多可以将速度提高 1.5 到 2 倍。

    2. Matlab 代码可能能够完全矢量化,但您必须在 C++ 中手动优化您的代码

      完全矢量化的 Matlab 代码可以调用用 C++/C/Assembly 编写的库(例如英特尔 MKL)。但是普通的 C++ 代码可以被现代编译器合理地向量化。

    3. Matlab 提供的工具箱和例程应该经过很好的调整并且应该具有合理的性能

      没有。除了线性代数例程外,性能普遍较差。

    与向量化的 Matlab 代码相比,您在 C++ 中获得 10 倍~100 倍性能的原因:

    1. 在 Matlab 中调用外部库 (MKL) 需要时间。

    2. Matlab 中的内存是动态分配和释放的。比如小矩阵乘法:
      A = B*C + D*E + F*G
      需要 Matlab 创建 2 个临时矩阵。而在 C++ 中,如果您事先分配内存,您将创建 NONE。现在想象你循环该语句 1000 次。 C++ 11 Rvalue 参考提供了 C++ 中的另一种解决方案。这是 C++ 最大的改进之一,现在 C++ 代码可以和普通 C 代码一样快。

    3. 如果要进行并行处理,Matlab 模型是多进程,C++ 方式是多线程。如果您有许多需要并行化的小任务,C++ 可以为多个线程提供线性增益,但您可能会在 Matlab 中获得负面的性能增益。

    4. C++ 中的向量化涉及使用内在函数/汇编,有时 SIMD 向量化只能在 C++ 中实现。

    5. 在 C++ 中,有经验的程序员可以完全避免 L2 缓存缺失甚至 L1 缓存缺失,从而将 CPU 推到其理论吞吐量极限。仅由于这个原因,Matlab 的性能可能落后于 C++ 10 倍。

    6. 在 C++ 中,计算密集型指令有时可以根据它们的延迟(在汇编或内在函数中仔细编码)和依赖关系(大部分时间由编译器或 CPU 硬件自动完成)进行分组,例如理论上的 IPC(每个时钟周期的指令) 可以到达并且 CPU 管道已被填满。

    不过,C++ 的开发时间也是 Matlab 的 10 倍!

    你应该使用 Matlab 而不是 C++ 的原因:

    1. 数据可视化。我认为我的职业生涯可以在没有 C++ 的情况下继续,但如果没有 Matlab,我将无法生存,因为它可以生成漂亮的情节!

    2. 效率低,但数学稳健的内置例程和工具箱。先得到正确答案再谈效率。人们可以在 C++ 中犯一些细微的错误(例如将 double 隐式转换为 int)并获得正确的结果.

    3. 表达您的想法并向您的同事展示您的代码。 Matlab 代码比 C++ 更容易阅读,也更短,而且 Matlab 代码无需编译器也能正确执行。我只是拒绝阅读其他人的 C++ 代码。我什至不使用 C++ GNU 科学库,因为无法保证代码质量。对于研究人员/工程师来说,将 C++ 库用作黑匣子并将准确性视为理所当然是很危险的。即使对于商业 C/C++ 库,我记得英特尔编译器去年在其 sin() 函数中出现了 sign 错误,并且在 MKL 中也出现了数值准确性问题。

    4. 使用交互式控制台和工作区调试 Matlab 脚本比 C++ 调试器高效得多。在 Matlab 中查找索引计算错误可以在几分钟内完成,但在 C++ 中,如果为了速度而取消边界检查,则可能需要数小时才能找出程序随机崩溃的原因。

    最后但并非最不重要的一点:

    因为一旦 Matlab 代码被向量化,程序员就没有太多可以优化的地方了,与 C++ 代码相比,Matlab 代码性能对代码质量的敏感度要低得多。因此,最好在 Matlab 中优化计算算法,稍微好一点的算法通常在 Matlab 中性能略好一些。另一方面,C++中的算法测试要求优秀的程序员编写或多或少以相同方式优化的算法,并确保编译器不会对算法进行不同的优化。

    我最近在 C++ 和 Matlab 方面的经验:

    去年做了几个大型的Matlab数据分析工具,苦于Matlab速度慢。但是通过以下技术,我能够将我的 Matlab 程序速度提高 10 倍:

    • 运行/分析 Matlab 脚本,在 C/C++ 中重新实现关键例程并使用 MEX 进行编译。关键例程很可能在逻辑上很简单,但在数字上很繁重。这将速度提高了 5 倍。

    • 通过注释所有不必要的安全检查和输出参数计算来简化 Matlab 工具箱附带的“.m”文件。请注意,修改后的代码不能与其余用户脚本一起分发。这将速度提高了 2 倍(在 C/C++ 和 MEX 之后)。

    改进后的代码在 Matlab 中约为 98%,在 C++ 中约为 2%。

    我相信如果整个工具都用 C++ 编码,那么速度可以再提高 2 倍(总共 20 倍),这是计算例程的大约 100 倍速度提高。硬盘驱动器 I/O 将支配程序运行时间。

    Mathworks 工程师的问题:

    当 Matlab 代码完全矢量化时,性能限制因素之一是矩阵索引操作。例如,需要对尺寸为 5000x5000 的矩阵 A 进行有限差分运算:

    B = A(:,2:end)-A(:,1:end-1)
    

    矩阵索引操作使 Matlab 代码比 C++ 代码慢数倍。矩阵索引性能能提高吗?

    【讨论】:

    • 这是一个漂亮的总结。这让我很想知道这位来自康奈尔大学的博士是谁,但“显然,这个用户更喜欢对他们保持神秘感”。自从我问这个问题以来已经超过 2 年了。没问题,尊重隐私。干杯!
    • 谢谢!我很高兴能提供帮助,并分享我过去的艰辛教训。
    • 第 3.6 点:由于写入时 JIT 复制,最新版本的 Matlab 不需要复制到第三个矩阵来交换 2 个矩阵。命令集:c = a; a = b; b = c;清除 c;只会生成引用,不会发生数据复制。
    • @Wybird666:MATLAB 一直有惰性复制(copy-on-write),这与 JIT 无关。
    • 谢谢 Wybrid666,您能帮我编辑帖子以反映您/正确的理解吗?
    【解决方案3】:

    一些 Matlab 代码使用内置多线程的标准线性代数虚构。因此,它们似乎比顺序 C 代码更快。

    【讨论】:

      【解决方案4】:

      我看到从 MATLAB 切换到 C++ 时速度提高了 5.5 倍。这是针对机器人控制器的 - 大量循环和 ode 求解。我花了很多时间尝试优化 MATLAB 代码,几乎没有时间优化 C++(我敢肯定,只要付出更多努力,它就会快 10 倍)。

      但是,为 MATLAB 代码添加 GUI 很容易,所以我仍然更经常地使用它。就像其他人所说的那样,首先在 MATLAB 上进行原型制作非常好。这使得在 C++ 上的实现更加简单。

      【讨论】:

        【解决方案5】:

        除了最终程序的速度之外,您还应该考虑代码的总开发时间,即不仅要编写时间,还要考虑调试等。 Matlab(及其开源对应物) , Octave) 由于其可视化功能,可以很好地进行快速原型制作。

        如果您直接使用 C++(即没有矩阵库),编写与 Matlab 代码等效的 C++ 代码可能需要更长的时间(例如,花费 10 个小时编写仅与需要 5 分钟编写的 Matlab 程序相比,运行速度快 10 秒)。

        但是,有专门的 C++ 矩阵库,例如 Armadillo,它们提供了类似于 Matlab 的 API。这对于编写可从 Matlab 调用的性能关键代码或将 Matlab 代码转换为“真实”程序很有用。

        【讨论】:

          【解决方案6】:

          Matlab 在线性代数和数组/矩阵运算方面做得很好,因为它们似乎一直在对底层运算进行一些额外的优化——如果你想在那里击败 Matlab,你需要一个类似优化的 BLAS/LAPACK 库。

          作为一种解释型语言,每当调用 Matlab 函数时,由于内部开销,Matlab 都会浪费时间,这在传统上意味着 Matlab 循环很慢。近年来,由于 JIT 编译器的显着改进(在 SO 上的 Matlab 上搜索“性能”问题,例如),这种情况有所缓解。由于函数调用开销,所有未在幕后用 C/C++ 实现的 Matlab 函数(调用 edit functionName 以查看它是否用 Matlab 编写)有可能比 C/C++ 对应物慢。

          最后,Matlab 试图变得用户友好,并且可能会进行“不必要的”输入检查,这可能需要一些时间(由于函数调用开销)。例如,如果您知道ismember 得到排序的输入,您可以直接调用ismembc(后台编译函数),节省不少时间。

          【讨论】:

            【解决方案7】:

            我认为你至少可以考虑四方面的差异。

            1. 编译 vs 解释
            2. 强类型与动态类型
            3. 性能与快速原型设计
            4. 特殊实力

            对于 1-3 可以很容易地概括为两个编程语言家族之间的比较。

            对于 4,MATLAB 针对矩阵运算进行了优化。因此,如果您可以对MATLAB 中的更多代码进行矢量化处理,则可以大幅提升性能。相反,如果需要多个loops,请毫不犹豫地使用C++ 或创建mex 文件。

            毕竟这是一个难题。

            【讨论】:

              【解决方案8】:

              根据我的经验(多年的计算机视觉和两种语言的图像处理),这个问题没有简单的答案,因为 Matlab 的性能在很大程度上取决于您的编码风格(并且远远超过 C++ 的性能)。

              通常,Matlab 封装了经典的基于 C++/Fortran 的线性代数库。所以像x = A\b 这样的东西会非常快。此外,Matlab 在为这些类型的问题选择最有效的求解器方面做得很好,因此对于x = A\b,Matlab 将查看矩阵的大小并选择适当的低级例程。

              如果您“矢量化”您的代码,即如果您避免 for 循环并使用索引数组或布尔数组来访问您的数据,Matlab 也会在大型矩阵的数据操作方面大放异彩。这东西是高度优化的。

              对于其他例程,一些是用 Matlab 代码编写的,而另一些则指向 C/C++ 实现(例如 Delaunay 的东西)。您可以通过键入edit some_routine.m 自行检查。这将打开代码,您会看到它是全部 Matlab 还是只是已编译内容的包装器。

              我认为,Matlab 主要是为了舒适——但舒适会转化为编码时间,最终转化为金钱,这就是为什么在行业中使用 Matlab。此外,对于计算机科学以外的其他领域的工程师来说,学习起来很容易,几乎不需要编程培训。

              【讨论】:

              • 感谢您的回答。但是考虑到 matlab 和 Fortran 优化级别的所有智慧,为什么 matlab 应该更慢!
              • 我的意思是,如果您看不到任何改进,在组装级别进行优化不是浪费精力吗?另外,尽管我明白您的观点,但“很大程度上取决于您的编码风格”是需要详细说明的。我实际上会要求,考虑双方合理的编程效率,这仍然有这个 100 倍的差异范围。
              • 重点是:Matlab 对于一些大型操作(矩阵和 lin.alg. 的东西,完成低级别)非常快,但对于其他所有操作都相当慢,它本质上是一种解释性脚本语言(使用比其他脚本语言复杂得多)。 Matlab 优化的问题是那些工作负载是大型矩阵和线性代数运算的问题,周围有很少(慢)样板代码。如果您的问题不是那种类型(即,如果您必须使用 for 循环和非矩阵运算编写大量代码)Matlab 速度会下降。
              • 顺便说一句,Matlab 的名称来自“矩阵实验室”——该产品最初是为了为 LAPACK 和其他软件包的快速 Fortran / C 线性代数例程提供舒适的接口。这就是语言的快速、优化和脚本部分之间的区别所在。
              • 我同意 DCS 的观点 - 一切都与您的编码方式有关。我看到很多用 Matlab 编写的代码没有使用内置函数并且没有向量化。做这两件事,它运行得非常快。如果与编写、测试和验证编写良好的 Matlab 代码所花费的时间相比,在 C/C++ 中运行代码所节省的总时间超过了编写、测试和验证优化代码所花费的总时间,我会感到惊讶!
              【解决方案9】:

              你的问题很难回答。一般来说,C++ 速度更快,但如果利用 Matlab 编写好的算法,它可以胜过 C++。在某些情况下,Matlab 可以并行化您的代码,这在 C++ 的许多情况下必须手动完成。 Mathlab 可以导出 C++ 代码。

              所以我的结论是,您必须衡量这两个程序的性能才能得到答案。但是然后你比较你的两个实现,而不是一般的 Matlab 和 C++。

              【讨论】:

                猜你喜欢
                • 2021-02-04
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2020-04-27
                • 2013-02-04
                • 1970-01-01
                相关资源
                最近更新 更多