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

时间:2018-06-28 08:22:09

标签: c gcc cpu-architecture

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

可执行文件必须相同,因此我不能使用-march=native,但同时架构具有共同点(我认为它们都支持AVX?)。

我知道gcc(与Intel icc相反)不允许在单个可执行文件中使用多个架构。我想知道的是,是否有一种方法可以向gcc提出与上述所有架构兼容的最高指令集。

gcc版本:8.1.1

3 个答案:

答案 0 :(得分:3)

评论建议我自己看看体系结构之间的“交叉点”。以下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é” =>“ enabled”,“désactivé” =>“ disabled”)

输出为

-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。

答案 1 :(得分:2)

Intel从未在同一CPU的未来版本中删除指令集。也就是说,在旧版Intel CPU上运行的二进制文件始终在新版Intel CPU上运行。

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


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

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


SnB / IvB的AVX加载/存储未对齐有效,因此tune = sandybridge设置-mavx256-split-unaligned-load,如果您的数据 在运行时对齐,这会很麻烦,但是编译器不知道那。多余的说明和改组对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的运行时调度

您必须在源代码中激活它才能使用特定功能。有关函数多版本的更多信息,请参见https://lwn.net/Articles/691932/


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

在每个群集节点上,创建一个/etc/host-type或任何具有sandybridgehaswell或其他任何值的对象。任何每个节点的文件系统都可以,或者在运行时使用gcc或更便宜的方法重新检测它。在您的工作脚本中:

#!/bin/sh

bin_dir="./bin-$(</etc/node-type)"
exec "$bin_dir/my_prog"  "$@"

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

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

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

答案 2 :(得分:1)

  

我想知道的是,是否有一种方法可以向gcc询问与上述所有架构兼容的最高指令集。

没有。

如果您想获得最佳性能,请参阅Saner De Dycker评论的胖二进制文件。

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