首页 > 解决方案 > GCC最高指令集兼容多种架构

问题描述

我正在由具有不同架构的机器组成的集群上运行作业: gcc -march=native -Q --help=target | grep -- '-march=' | cut -f3给我以下之一:broadwellhaswellivybridge或.sandybridgeskylake

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

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

gcc 版本:8.1.1

标签: cgcccpu-architecture

解决方案


英特尔从未在同一 CPU 的未来版本中删除指令集。即适用于旧英特尔 CPU 的二进制文件始终适用于较新的英特尔 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尝试一下可能会很有趣:当 gcc 使用 256 位向量自动向量化时,一些循环会变得混乱。


SnB/IvB 的 AVX 加载/存储效率低下,因此 tune=sandybridge sets -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,那就不同了。


推荐阅读