我尝试为此擦洗 GCC 手册页,但仍然不明白,真的。
-march
和-mtune
有什么区别?
什么时候一个人只使用
-march
,什么时候两者都使用?有可能只是-mtune
吗?
如果您使用
-march
,那么 GCC 将可以自由生成在指定 CPU 上运行的指令,但(通常)不能在架构系列中的早期 CPU 上运行。
如果您只使用
-mtune
,那么编译器将生成适用于其中任何一个的代码,但会优先考虑在您指定的特定 CPU 上运行最快的指令序列。 例如为该 CPU 适当设置循环展开启发式。
-march=foo
意味着 -mtune=foo
,除非您还指定了不同的 -mtune
。 这就是为什么使用 -march
比仅启用 -mavx
等选项而不做任何调整更好的原因之一。
警告:在 GCC 未明确识别的 CPU 上,
-march=native
仍将启用 GCC 可以检测到的新指令集,但会保留 -mtune=generic
。 如果您希望它编写出好的代码,请使用一个足够新的、了解您的 CPU 的 GCC。
这是我用谷歌搜索到的:
-march=X
选项采用CPU名称X
,并允许GCC生成使用X
所有功能的代码。 GCC 手册准确解释了哪些 CPU 名称意味着哪些 CPU 系列和功能。
因为功能通常会添加,但不会删除,所以使用
-march=X
构建的二进制文件将在 CPU X
上运行,很有可能在比 X
新的 CPU 上运行,但几乎可以肯定不会在任何较旧的 CPU 上运行比X
。某些指令集(3DNow!,我猜?)可能特定于特定的 CPU 供应商,利用这些指令集可能会为您提供无法在竞争的 CPU(更新或其他)上运行的二进制文件。
-mtune=Y
选项可调整生成的代码,使其在 Y
上运行得比在其他 CPU 上运行得更快。 -march=X
意味着-mtune=X
。 -mtune=Y
不会覆盖 -march=X
,因此,例如,它可能对 -march=core2
和 -mtune=i686
没有任何意义 - 你的代码无论如何都不会在任何早于 core2
的东西上运行,因为 -march=core2
,所以你究竟为什么要针对比 core2 更旧(功能较少)的东西进行优化? -march=core2 -mtune=haswell
更有意义:不要使用超出 core2
提供的任何功能(这仍然比 -march=i686
为您提供的功能多得多!),但要针对较新的 haswell
CPU 优化代码,而不是针对core2
。
还有
-mtune=generic
。 generic
使 GCC 生成在当前 CPU 上运行最佳的代码(generic
的含义从一个版本的 GCC 更改为另一个版本)。 Gentoo 论坛上有传言称,-march=X -mtune=generic
生成的代码在 X
上运行的速度比 -march=X -mtune=X
生成的代码运行得更快(或者只是 -march=X
,如 -mtune=X
所暗示的那样)。 不知道这是否属实。
一般来说,除非你确切地知道你需要什么,否则最好的做法似乎是指定
-march=<oldest CPU you want to run on>
和-mtune=generic
(-mtune=generic
在这里是为了对抗隐式的-mtune=<oldest CPU you want to run on>
,因为你可能不想优化对于最旧的 CPU)。或者只是 -march=native
,如果您只想在构建的同一台机器上运行。