gpt4 book ai didi

gcc - 为什么 -march=native 很少使用?

转载 作者:行者123 更新时间:2023-12-02 22:51:54 24 4
gpt4 key购买 nike

对于大多数 C/C++ 编译器,都有一个可传递给编译器的标志 -march=native,它告诉编译器针对主机 CPU 的微架构和 ISA 扩展调整生成的代码。即使名称不同,基于 LLVM 的编译器通常也有等效的选项,例如 rustc 或 swiftc。

根据我自己的经验,这个标志可以为数字密集型代码提供巨大的加速,并且它听起来对于您刚刚为自己的机器编译的代码来说不会有任何妥协。也就是说,我认为我没有见过任何默认启用它的构建系统或静态编译器:

  • 显然,任何需要您传递它的命令行编译器可执行文件默认情况下都不会使用它。

  • 我想不出有任何 IDE 默认启用此功能。

  • 我想不出我使用过的任何常见构建系统(cmakeautomakecargospm 等),默认情况下启用它,即使对于优化的构建也是如此。

我可以想到一些原因,但没有一个真正令人满意:

  • 使用 -march=native 不适用于将分发到其他计算机的二进制文件。也就是说,我发现自己为自己的机器编译源代码的频率比为其他机器编译源代码的频率要高得多,这并不能解释它在调试版本中缺乏使用的原因,因为调试版本中无意分发。

  • 至少在 Intel x86 CPU 上,据我所知,很少使用 AVX 指令可能会降低性能或电源效率,因为 AVX 单元在不使用时会断电,需要通电才能使用,许多 Intel CPU 降频以运行 AVX 指令。不过,它只是解释了为什么 AVX 不会被启用,而不是为什么代码不会针对特定微架构处理常规指令进行调整。

  • 由于大多数 x86 CPU 使用奇特的无序超标量管道和寄存器重命名,因此针对特定微架构调整代码可能并不是特别重要。不过,如果它可以提供帮助,为什么不使用它呢?

最佳答案

保守

如果您仔细查看列表中最古老的编译器 gcc 的默认值,您会发现它们非常保守:

  • 默认情况下,在 x86 上,仅激活 SSE 2;甚至 SSE 4 都没有。
  • -Wall-Wextra 中的标志集多年来没有改变;有新的有用警告,它们不会添加到 -Wall-Wextra 中。
为什么?因为它会破坏东西!

整个开发链都依赖于这些方便的默认设置,任何更改都会带来破坏它们或生成无法在目标上运行的二进制文件的风险。

用户越多,威胁就越大,因此 gcc 的开发人员非常非常保守,以避免全局范围内的破坏。下一批编译器的开发人员追随前辈的脚步:事实证明它是有效的。

注意:rustc 将默认为静态链接,并声称您只需复制二进制文件并将其放到另一台机器上即可;显然 -march=native 会成为一个障碍。

大众友好

事实上,这可能并不重要。其实你自己也认出来了:

In my own experience, this flag can provide massive speedups for numerically-intensive code

大多数代码充满了虚拟调用和分支(通常是面向对象代码),并且根本不是数字密集型的。因此,对于大多数代码,SSE 2 通常就足够了。

无论如何,性能真正重要的少数代码库将需要在代码和编译器级别的性能调优上投入大量时间。如果矢量化很重要,它不会由编译器随意决定:开发人员将使用内置的内在函数并自己编写矢量化代码,因为它比安装监控工具来确保自动矢量化确实发生要便宜.

此外,即使对于数字密集型代码,主机和目标计算机也可能略有不同。编译受益于大量内核,即使是在较低频率下也是如此,而执行则受益于高频率和可能更少的内核,除非工作可以轻松并行化。

结论

默认不激活-march=native可以让用户更容易上手;因为即使是追求绩效的人也可能不太关心它,这意味着失去的比得到的更多。

<小时/>

在另一种历史中,默认值从一开始就是-march=native;用户将用于指定目标架构,我们不会进行此讨论。

关于gcc - 为什么 -march=native 很少使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52653025/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com