【问题标题】:How to correctly determine -march and -mtune for Intel processors?如何正确确定 Intel 处理器的 -march 和 -mtune?
【发布时间】:2019-07-03 12:44:50
【问题描述】:

我目前正在从源代码构建一个对我来说性能至关重要的软件。因此,我想优化它以在我的特定 Intel CPU 上运行。构建过程需要我设置 -march 和 -mtune 标志。

如果在我的处理器节点上我使用

gcc -march=native -Q --help=target|grep march
gcc -mtune=native -Q --help=target|grep mtune

我得到了 March 的“core-avx2”和 mtune 的“generic”。然而与

cat /proc/cpuinfo

我明白了:

processor   : 23
vendor_id   : GenuineIntel
cpu family  : 6
model       : 63
model name  : Intel(R) Xeon(R) CPU E5-2670 v3 @ 2.30GHz
stepping    : 2
microcode   : 0x3d
cpu MHz     : 2599.993
cache size  : 30720 KB
physical id : 1
siblings    : 12
core id     : 13
cpu cores   : 12
apicid      : 58
initial apicid  : 58
fpu     : yes
fpu_exception   : yes
cpuid level : 15
wp      : yes
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt xsave avx f16c rdrand lahf_lm abm epb intel_ppin ssbd ibrs ibpb tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid cqm xsaveopt cqm_llc cqm_occup_llc dtherm ida arat pln pts
bogomips    : 4599.35
clflush size    : 64
cache_alignment : 64
address sizes   : 46 bits physical, 48 bits virtual
power management:

通过访问 Intel(R) Xeon(R) CPU E5-2670 v3 @ 2.30GHz (https://ark.intel.com/content/www/de/de/ark/products/81709/intel-xeon-processor-e5-2670-v3-30m-cache-2-30-ghz.html) 的主页,我发现: 代号 -> 以前的产品 haswell

如果我使用

gcc -march=haswell -Q --help=target|grep march
gcc -mtune=haswell -Q --help=target|grep mtune

我对两者都有“haswell”。 那么我真的不应该使用 haswell 作为 March 而不是 core-avx2 吗?最好的选择是什么?

顺便说一句,我在 CentOS7 上使用 GCC 4.8.5。

谢谢!

编辑:

gcc -march=native -Q --help=target | grep -- '-march=' | cut -f3

-> 核心-avx2

gcc -mtune=native -Q --help=target | grep -- '-mtune=' | cut -f3

-> 通用

【问题讨论】:

  • 在 x86 处理器上,只需使用 -march=native。 GCC 将通过将 archtune 设置为相同的值来处理其余部分。 ARM 比较棘手,因为 GCC 在使用 -march=native 时有时会出现段错误。您还应该使用现代 GCC 或 Clang。 Clang 使用一些 SIMD 源代码创建了比 GCC 更好的代码。您需要进行基准测试以确定哪个对您的代码表现最好。
  • 您好,感谢您的回复!不幸的是,我必须使用 Docker 容器在我的本地机器上构建软件(由于缺少集群上稍后执行代码的权限),因此原生对我来说不是选择,因为它会针对我的本地机器进行优化。另外我必须坚持使用 GCC 4.8.5,因为很多人都在从事这个项目,他们曾经尝试升级 gcc,这导致项目中出现大量不兼容问题。
  • 那么听起来这句话是不正确的:“...我想优化它以在我的特定 Intel CPU 上运行”。您可能应该更新您的问题。
  • 是的,我很抱歉,我的意思是我要在其上部署我的软件的 CPU。上面列出的规格是我要优化的目标平台的规格。

标签: performance gcc x86 intel compiler-optimization


【解决方案1】:

在您使用的 gcc 版本中,Haswell 被称为 core-avx2。其他微架构也有蹩脚的名字。例如,Ivy Bridge、Sandy Bridge 和 Westmere 分别被称为 core-avx-i、corei7-avx 和 corei7。从 gcc 4.9.0 开始,使用微架构的实际名称,因此当在 Haswell 处理器上使用 gcc -march=native -Q --help=target|grep march 而不是 core-avx2 时,gcc 将打印 Haswell(参见 patch)。

当将-mtune=native 传递给gcc 并且您正在使用的gcc 版本不知道主机处理器时,它将应用generic 调整。您的处理器型号 (63) 只有 gcc 5.1.0 及更高版本才知道(请参阅patch)。

-Q --help=target 的名称打印部分必须为-march=native 选择一些名称。对于您的 GCC 无法特别识别的 CPU 太新,如果处理器支持 ADX,它将选择 Broadwell 之类的东西,或者支持主机处理器支持的最高 SIMD 扩展(最高 AVX2)的微架构(由 @987654330 确定@)。

-march=native的实际效果是启用所有适当的-mavx -mpopcnt -mbmi2 -mcx16等选项,所有使用cpuid单独检测。因此,出于代码生成目的,-march=native 始终可用于启用 GCC 知道如何使用的 ISA 扩展,即使它无法识别您的 CPU。

但是对于设置tune 选项,-march=native-mtune=native 完全失败,当它不能准确识别您的 CPU 时回退到generic。不幸的是,它不会为未知的英特尔 CPU 执行类似 tune=intel 的操作。


在您的处理器上,gcc 知道它支持 AVX2,因此它假设它是 Haswell 处理器(在您的 gcc 版本中称为 core-avx2),因为从 Haswell 开始支持 AVX2,但它不确定它实际上是 Haswell 处理器。这就是为什么它应用通用调优而不是调优 core-avx2(即 Haswell)。但在这种情况下,我认为这与调整 core-avx2 的效果相同,因为对于那个编译器版本,只有 Haswell 支持 AVX2,并且编译器知道主机处理器支持 AVX2。不过,一般来说,即使 -march 在未知 CPU 上被正确猜到,它也可能不会针对本机微架构进行调整。

(编者注:不,tune=generic 不适应启用了​​哪些指令集选项。它仍然是完全通用的调整,包括关心不支持 AVX2 的 AMD Phenom 或 Intel Sandybridge 等 CPU。见 @ 987654323@和Why doesn't gcc resolve _mm256_loadu_pd as single vmovupd?

这是为什么您应该使用-march=native-march=haswell(具有足够新的gcc)的原因之一,而不仅仅是-mavx2 -mfma。另一个原因是你可能会忘记-mbmi2 -mpopcnt -mcx16,甚至可能忘记-mfma)

【讨论】:

  • 它会选择支持所有指令的微架构这并不完全正确。 -march=native 部分不选择微架构并使用这些设置,它只是检查 GCC 知道使用cpuid 结果的每个CPU 功能。因此,在通过 CPUID 选择一组奇怪的东西来公开的 VM 中,-march=native 可能会启用 AVX2,但不会启用 popcnt 或 AES,如果这是 CPUID 报告的,即使没有 -march=xyz 设置可以做到这一点。跨度>
  • 但是是的,对于 tune 设置,GCC 必须专门识别处理器,如果您的 CPU 太新而 GCC 无法了解,则回退到 generic。可以说,将其识别为最新的英特尔主流 CPU 是可能的,并且选择 GCC 知道的最新的此类调整(例如tune=ivybridge)会更有用。或者至少-mtune=intel
  • @PeterCordes 是的,但如果处理器支持 AVX2 但不支持 popcnt,gcc 仍将打印“Haswell”。当然,在这种情况下它不会使用popcnt。不过,好点。记住这一点很重要。如果 gcc 不知道主机处理器的型号,我认为针对较旧的微体系结构(例如 Ivy Bridge)进行调整不是一个好主意,因为这可能导致性能比在不同微体系结构上的通用调整更差(例如哈斯韦尔)。
  • 您在回答中的措辞方式使它听起来仍然为特定的已知 uarch 选择一组扩展。就像 ADX 支持会导致 GCC 启用 AVX2,无论 cpuid 对 AVX2 说什么。这种猜测可能只存在于这个答案所询问的名称打印代码中,而不是大多数时候真正重要的-march=native 的重要部分。使用 -fverbose-asm 并查看 asm cmets 以查看 gcc 在启用/禁用 -m 选项时检测到的内容。
  • @tre95 如果您知道代码只能在支持 AVX2 的处理器上运行,请使用 -march=core-avx2(不需要显式的 -mtune=core-avx2,因为在这种情况下它是隐含的)。
【解决方案2】:

顺便说一句,我在 CentOS7 上使用 GCC 4.8.5。

如果性能很关键,您应该使用更新版本的 GCC。 The 4.8 release series dates back to 2013,并且缺少当前版本中存在的许多性能增强。当前版本具有significantly expanded tuning options for x86,包括-march 设置,适用于2013 年不存在的许多处理器系列。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-31
    • 1970-01-01
    • 2019-04-08
    • 2018-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多