我尝试为此清理GCC手册页,但实际上还是不明白。
-march
和之间有什么区别-mtune
?
什么时候只使用-march
,而两者都用呢?有可能公正-mtune
吗?
Answers:
如果使用,-march
则GCC可以自由生成可在指定CPU上运行的指令,但(通常)不能在体系结构系列中的较早CPU上运行。
如果仅使用-mtune
,则编译器将生成可在其中任何一个上运行的代码,但会偏爱在您指定的特定CPU上运行最快的指令序列。例如,为该CPU适当设置循环展开试探法。
-march=foo
表示,-mtune=foo
除非您还指定了另一个-mtune
。这是为什么使用-march
优于仅启用选项-mavx
而不进行任何调整的原因之一。
注意:-march=native
在GCC不能明确识别的CPU上,仍将启用GCC可以检测到的新指令集,但会离开-mtune=generic
。如果希望它编写良好的代码,请使用一个足够了解您的CPU的新GCC。
march
暗示mtune
。因此,您反对的答案分别是“否”和“是”。
这就是我用谷歌搜索的内容:
该-march=X
选项采用CPU名称,X
并允许GCC生成使用的所有功能的代码X
。GCC手册准确解释了哪些CPU名称意味着哪些CPU系列和功能。
由于通常会添加但不会删除功能,因此使用内置的二进制文件-march=X
可以在CPU上运行X
,有很大的机会在低于的CPU上运行X
,但是几乎可以肯定不会在低于的版本上运行X
。某些指令集(3DNow !,我猜是?)可能特定于特定的CPU供应商,利用这些指令集可能会使您的二进制文件无法在竞争的CPU上运行,无论是更新版本还是其他版本。
该-mtune=Y
选件可调整生成的代码,使其Y
在其上可能比其他CPU上运行的速度更快。-march=X
暗示-mtune=X
。-mtune=Y
不会覆盖-march=X
,因此,举例来说,它可能是没有意义的-march=core2
,并-mtune=i686
-你的代码不会对任何事情比年长的运行core2
反正,因为-march=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>
and -mtune=generic
(-mtune=generic
此处是针对隐式的-mtune=<oldest CPU you want to run on>
,因为您可能不想针对最早的CPU进行优化)。或者只是-march=native
,如果您只想在构建同一台计算机上运行。
-march=native
表示tune=native
正常。那篇文章只提出了坏情况。较新的GCC版本通常可提供更好的代码,尤其是在使用AVX2和AVX-512等新指令时。而且,为您的CPU设计调整设置(例如循环展开启发式)绝对是一件好事。因此,如果您足够在意使用这些选项的性能,请使用新的GCC,至少要有一个了解您的CPU的GCC ,最好是当前稳定的relese。
tune=generic
令人吃惊的是,GCC不能比同一个微体系结构家族的新成员做得更好,尤其是像Kaby Lake这样的产品,其在字面上与Skylake微体系结构完全相同。但是我认为它的家族/步骤仍然不同,因此仅了解Skylake和更老版本的GCC可能无法识别它以进行调整。