GCC最高指令集与多种架构兼容

我在由具有不同体系结构的计算机组成的集群上运行作业: gcc -march=native -Q --help=target | grep -- '-march=' | cut -f3 gcc -march=native -Q --help=target | grep -- '-march=' | cut -f3 gcc -march=native -Q --help=target | grep -- '-march=' | cut -f3给我其中一个: broadwellhaswellivybridgesandybridgeskylake

可执行文件需要是相同的,所以我不能使用-march=native但同时架构有共同点(我认为它们都支持AVX?)。

我知道gcc (与Intel icc相反)不允许在单个可执行文件中存在多个目标。 我想知道的是,是否有办法向gcc询问与上面列出的所有架构兼容的最高指令集。

gcc版本:8.1.1

评论建议我自己看看架构之间的“交叉点”。 以下bash脚本似乎可以完成这项工作。

 #!/usr/bin/env bash archs=("broadwell" "haswell" "ivybridge" "sandybridge" "skylake") for ar in ${archs[@]}; do gcc -march=$ar -Q --help=target | grep -- " -m" > "$ar.log" done cp "${archs[0]}.log" all.log for ar in ${archs[@]:1}; do join all.log "$ar.log" > tmp.log mv tmp.log all.log done cat all.log | grep "\[activé]" | grep -v "\[désactivé]" | cut -d' ' -f1 | tr '\n' ' ' 

(法语计算机:“activé”=>“启用”,“désactivé”=>“禁用”)

输出是

 -m128bit-long-double -m64 -m80387 -maes -malign-stringops -mavx -mcx16 -mfancy-math-387 -mfp-ret-in-387 -mfxsr -mglibc -mhard-float -mieee-fp -mlong-double-80 -mmmx -mpclmul -mpopcnt -mpush-args -mred-zone -msahf -msse -msse2 -msse3 -msse4 -msse4.1 -msse4.2 -mssse3 -mstv -mtls-direct-seg-refs -mvzeroupper -mxsave -mxsaveopt 

正如我所料,所有架构都支持SSE和AVX。

英特尔从未在同一CPU的未来版本中删除指令集。 即,在旧的Intel CPU上运行的二进制文件始终适用于较新的Intel CPU。

(一个例外是第一代Xeon Phi:Knight’s Corner使用了一种名为KNI的AVX512的不兼容变体,但后来Xeon Phi加速器卡/计算机使用AVX512。)


如果必须在所有CPU上使用相同的二进制文件,请使用gcc -march=sandybridge -mtune=haswell ,并确保重要的数组对齐32个字节。

也许值得用gcc -march=sandybridge (即使用tune = sandybridge)进行基准测试,看看哪种方法更适合你的代码。 -mprefer-avx128-mprefer-vector-width=256可能会很有趣:当gcc使用256位向量自动向量化时,某些循环会变得混乱。


SnB / IvB具有低效的未对齐AVX加载/存储,因此tune = sandybridge sets -mavx256-split-unaligned-load ,如果您的数据在运行时对齐但编译器不知道,那么这很糟糕。 额外的指令和-mtune=haswell对Haswell没有帮助,因此-mtune=haswell包括-mno-avx256-split-unaligned-load

不幸的是,gcc没有“tune = avx2”选项来调整所有具有AVX2的CPU,或者选择调整支持你启用的指令集的平均CPU。 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80568 。 您唯一的选择是调整特定CPU,或调整通用基线,或使用特定调整选项。


Gcc确实支持使用ifunc进行运行时调度

您必须在源中为特定function激活它。 有关函数多版本控制的更多信息,请参阅https://lwn.net/Articles/691932/ 。


最佳选择:为SnB / Haswell构建单独的二进制文件,并使用脚本或$PATH设置进行调度

在每个群集节点上,创建一个/etc/host-type或者其他什么,它们有haswellhaswell或者其他什么。 任何每个节点的文件系统都可以,或者在运行时使用gcc或更便宜的东西重新检测它。 在你的工作脚本中:

 #!/bin/sh bin_dir="./bin-$( 

根据需要创建符号链接以使bin-skylakebin-broadwell使用Haswell二进制文件。

Haswell推出了AVX2和FMA,以及BMI1 / 2。 如果你是数字运算,你真的想要FMA 。 BDW / SKL没有引入任何重要的ISA扩展,编译器可以使用这些扩展来使代码运行得更快。 调整BDW / SKL也没有什么不同。

如果你有任何Skylake-avx512 CPU,那就不一样了。

我想知道的是,是否有办法向gcc询问与上面列出的所有架构兼容的最高指令集。

这是一个NO。

Saner De Dycker评论说,如果你想要最佳性能,请查看胖二进制文件。

另一种解决方案是为每个指令集编译二进制文件和库,并在每个系统上设置PATH和LD_LIBRARY_PATH以选择最佳指令集。