为什么-march=native很少使用



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

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

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

  • 我想不出有任何IDE可以默认启用这一功能。

  • 我想不出我使用过的任何通用构建系统(cmakeautomakecargospm等)可以默认启用它,即使是优化的构建也是如此。

我能想出几个原因,但没有一个是真正令人满意的:

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

  • 至少在英特尔x86 CPU上,我的理解是,很少使用AVX指令可能会降低性能或电源效率,因为AVX单元在不使用时会断电,需要通电才能使用,而且很多英特尔CPU都会下锁以运行AVX指令。尽管如此,它只是解释了为什么AVX不会被启用,而不是为什么代码不会针对特定微架构对常规指令的处理进行调优。

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

保守

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

  • 默认情况下,在x86上,只有SSE 2被激活;甚至不是SSE 4
  • -Wall-Wextra中的标志集多年来没有改变;存在新的有用警告,它们不会添加到-Wall-Wextra

为什么?因为它会打碎东西!

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

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

注意:rustc将默认为静态链接,并吹嘘您可以复制二进制文件并将其放到另一台机器上;很明显CCD_ 14将是一个障碍

大众友好型

事实上,这可能并不重要。实际上你自己也认识到了:

根据我自己的经验,这个标志可以为数字密集型代码提供巨大的加速

大多数代码都充满了虚拟调用和分支(通常是OO代码),并且在数字上一点也不密集。因此,对于大多数代码来说,SSE 2通常就足够了。

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

此外,即使对于数字密集型代码,主机和目标机器也可能略有不同。编译得益于大量的核心,即使是在较低的频率下,而执行得益于高频率,可能更少的核心,除非工作很容易并行化。

结论

默认情况下不激活-march=native,让用户更容易上手;即使是追求业绩的人也可能不太关心它,这意味着得不偿失。


在另一个历史中,默认值从一开始就是-march=native;用户将被用来指定目标体系结构,我们不会进行此讨论

-march=native是一个破坏性标志。它使得二进制可能在许多硬件上不兼容(基本上是任何不是编译所用CPU的直接后代的CPU)。默认情况下启用此功能太危险了。

另一个需要考虑的重要事项是-march=native的主要最终用途是优化。默认的优化标志是-O0(无优化),因此从这个角度来看,默认启用它也没有意义。

您是从超级用户的角度进行思考的,但编译器工具链的主要受众不是超级用户,而是开发人员。

大多数开发人员都有独立的开发机器和目标生产系统。在消费者应用程序的情况下,此目标系统是具有所有差异的其他人的机器。为最常见的分母构建是一个安全的默认值,因为它减少了只在开发人员自己的机器之外发生错误的机会。

当然,在某些情况下,开发人员知道他们将为具有已知体系结构的单个目标机器开发应用程序。但即使在这种情况下,大多数应用程序也对性能不敏感,因此安全选项作为默认选项仍然足够好,而使用性能敏感应用程序的开发人员通常更愿意花时间调整构建配置。

答案已经得到回答,只是显示了O3和march=native之间的区别。我正在用大量的数学制作3D视频。原始,O3未设置,march=原生。

100 out of 900 %11.2222 time left: 0:0:7 time since: 1
200 out of 900 %22.3333 time left: 0:0:6 time since: 2
300 out of 900 %33.4444 time left: 0:0:5 time since: 3
400 out of 900 %44.5556 time left: 0:0:6 time since: 5
500 out of 900 %55.6667 time left: 0:0:4 time since: 6
600 out of 900 %66.7778 time left: 0:0:3 time since: 7
700 out of 900 %77.8889 time left: 0:0:2 time since: 8
800 out of 900 %89 time left: 0:0:1 time since: 9
Finished it took 0:0:10

如果我使用march=native进行O3优化,输出如下:

100 out of 900 %11.2222 time left: 0:0:0 time since: 0
200 out of 900 %22.3333 time left: 0:0:3 time since: 1
300 out of 900 %33.4444 time left: 0:0:1 time since: 1
400 out of 900 %44.5556 time left: 0:0:2 time since: 2
500 out of 900 %55.6667 time left: 0:0:1 time since: 2
600 out of 900 %66.7778 time left: 0:0:1 time since: 3
700 out of 900 %77.8889 time left: 0:0:1 time since: 4
800 out of 900 %89 time left: 0:0:0 time since: 4
Finished it took 0:0:5

因此,O3优化确实有帮助。

根据一条新的评论编辑,这个程序从昨天开始有了一些发展,所以时间有点高。这是O3三月=本地现在:

100 out of 900 %11.2222 time left: 0:0:15 time since: 2
200 out of 900 %22.3333 time left: 0:0:10 time since: 3
300 out of 900 %33.4444 time left: 0:0:9 time since: 5
400 out of 900 %44.5556 time left: 0:0:7 time since: 6
500 out of 900 %55.6667 time left: 0:0:6 time since: 8
600 out of 900 %66.7778 time left: 0:0:4 time since: 9
700 out of 900 %77.8889 time left: 0:0:3 time since: 11
800 out of 900 %89 time left: 0:0:1 time since: 12
Finished it took 0:0:14

如果我退出游行=本地:

100 out of 900 %11.2222 time left: 0:0:15 time since: 2
200 out of 900 %22.3333 time left: 0:0:13 time since: 4
300 out of 900 %33.4444 time left: 0:0:11 time since: 6
400 out of 900 %44.5556 time left: 0:0:9 time since: 8
500 out of 900 %55.6667 time left: 0:0:7 time since: 10
600 out of 900 %66.7778 time left: 0:0:5 time since: 12
700 out of 900 %77.8889 time left: 0:0:3 time since: 14
800 out of 900 %89 time left: 0:0:1 time since: 16
Finished it took 0:0:18

最新更新