对于大多数 C/C++ 编译器,有一个可传递给编译器的标志,-march=native
,它告诉编译器调整为主机 CPU 的微架构和 ISA 扩展生成的代码。即使它的名称不同,基于 LLVM 的编译器通常也有一个等效的选项,例如rustc
or swiftc
.
根据我自己的经验,这个标志可以为数字密集型代码提供巨大的加速,并且它sounds就像您为自己的机器编译的代码不会有任何妥协一样。也就是说,我认为我没有见过任何默认启用它的构建系统或静态编译器:
显然,任何需要您传递它的命令行编译器可执行文件默认情况下都不使用它。
我想不出有任何 IDE 默认启用此功能。
我想不出我使用过的任何常见构建系统(cmake
, automake
, cargo
, spm
等),默认情况下启用它,即使对于优化的构建也是如此。
我可以想到几个原因,但没有一个是真正令人满意的:
Using -march=native
不适用于将分发到其他计算机的二进制文件。也就是说,我发现自己为自己的机器编译源代码的频率比为其他机器编译源代码的频率要高得多,这并不能解释它在调试版本中缺乏使用的原因,因为在调试版本中没有分发的意图。
至少在 Intel x86 CPU 上,我的理解是,很少使用 AVX 指令可能会降低性能或电源效率,因为 AVX 单元在不使用时会断电,需要加电才能使用,而且很多 Intel CPU降频以运行 AVX 指令。尽管如此,它只是解释了为什么 AVX 不会被启用,而不是为什么代码不会针对特定微架构处理常规指令进行调整。
由于大多数 x86 CPU 使用带有寄存器重命名的奇特的无序超标量管道,因此针对特定微架构调整代码可能并不是特别重要。即便如此,如果could帮忙,为什么不使用它?
保守的
如果您仔细查看列表中最古老的编译器 gcc 的默认值,您会发现它们非常保守:
- 默认情况下,在 x86 上,仅激活 SSE 2;连SSE 4都没有。
- 中的标志集
-Wall
and -Wextra
多年来没有改变;有新的有用警告,它们没有添加到-Wall
or -Wextra
.
为什么?因为它会破坏东西!
整个开发链都依赖于这些方便的默认设置,任何更改都会带来破坏它们或生成无法在目标上运行的二进制文件的风险。
用户越多,威胁就越大,因此 gcc 的开发人员非常非常保守,以避免全球范围内的破坏。下一批编译器的开发人员追随前辈的脚步:事实证明它是有效的。
Note: rustc
将默认为静态链接,并声称您可以复制二进制文件并将其放在另一台机器上;明显地-march=native
那里将会成为一个障碍。
大众友好
事实上,这可能并不重要。其实你自己也认识到了:
根据我自己的经验,这个标志可以为数字密集型代码提供巨大的加速
大多数代码充满了虚拟调用和分支(通常是面向对象代码),并且根本不是数字密集型的。因此,对于大多数代码来说,SSE 2 通常就足够了。
无论如何,性能真正重要的少数代码库将需要在代码和编译器级别上投入大量时间进行性能调整。如果矢量化很重要,它不会由编译器随意决定:开发人员将使用内置的内在函数并自己编写矢量化代码,因为它比安装监控工具来确保自动矢量化确实发生要便宜。
此外,即使对于数字密集型代码,主机和目标机也可能略有不同。编译受益于大量内核,即使在较低频率下也是如此,而执行受益于高频率和可能更少的内核,除非工作可以轻松并行化。
结论
未激活-march=native
默认使用户更容易上手;因为即使是追求绩效的人也可能不太关心它,这意味着失去的比得到的更多。
在另一种历史中,默认情况是-march=native
从一开始就;用户将用于指定目标架构,我们不会进行此讨论。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)