我如何限制GCC的自动向量化级别?

4
换句话说,是否有可能将使用“-fast-math -ftree-vectorize”得到的自动向量化指令限制在类似于“AVX”的范围内,同时通过显式内部调用来使用“AVX512”?
目前,
- 不使用“-mavx512f”,GCC会失败并表示它无法编译没有AVX-512f支持的程序。很好。 - 使用“-mavx512f”,GCC开始无处不用它。
我没有找到任何选项让GCC在限制自身为自动向量化时使用显式的“AVX512”内部函数。
编辑:只是为了给出更多背景……我有skylake-avx512 Xeon Gold节点(2个FMA单元)和一个特定于域的程序。
当我使用“-Ofast -march = skylake-avx512 -mtune = skylake-avx512”编译并在一核上运行时,我比“-march = haswell…”获得30%以上的性能。
当我将核心数增加到所有24个核心时,“-march = haswell…”比“-march = skylake-avx512…”快两倍!
原因是臭名昭着的核心节流……
但我的特定于领域的软件已经包括手工矢量化部分。 我使用“-fno-tree-vectorize -march = skylake-avx512 ...”获得性能优势(但不足以击败具有24个核心和自动向量化的“-march = haswell …”),因此自动向量化很重要。
最后,如果我使用针对“AVX2”的手工矢量化内核和“-march = skylake-avx512…”,我也会得到糟糕的性能,因此我认为导致限制的昂贵部分是自动向量化,因此我的原始问题。

从技术角度讲,AVX512中的大部分256位向量指令可以以谓词形式使用,因此必须进行EVEX编码。 - Anton
@安东:注意我写的是 vmovdqu ymm,而不是 vmovdqu ymm{k1}{z}。显然,如果你确实在指令上使用了掩码,那么你需要使用 EVEX 编码。但是很多时候你并不需要。幸运的是,对于许多指令来说,没有单独的助记符,汇编程序会为像 vpaddb ymm1, ymm2, ymm3 这样的指令选择 VEX 和 EVEX 中最短的编码。但整数向量移动或位布尔运算(AVX512 之前没有元素宽度)确实有新的助记符。 - Peter Cordes
@PeterCordes 我的观点是,编译器应该利用谓词指令,如果有盈利,无论使用的向量大小如何。考虑到代码足够复杂,不可避免地会有可以转换为掩码构造和谓词指令序列的有条件执行片段。当然,如果一个AVX512之前的指令必须被语义相等的AVX512替代,那么掩码就没有意义了,但编译器应该是复杂的东西,可以做更多的事情。 :-) - Anton
1
没有任何黄金模型可以解释 AVX Turbo 缩放可以将 1.3 倍性能优势转化为 2 倍的劣势:甚至不接近,因此 AVX-512 缩放不是您观察到的主要原因。 - BeeOnRope
@Anton:是的,对于256位掩码指令,AVX512VL通常比AVX1 / AVX2的vblendvps更好。但许多SIMD循环不受掩码的影响,也不需要条件加载/存储。在最近更新问题之前,完全不清楚OP只是想避免512位向量,而不需要避免EVEX前缀。 - Peter Cordes
显示剩余5条评论
1个回答

1
你可以使用目标属性以基于函数的方式启用指令,从而允许调用本来不被允许的内部函数。
我猜你想根据运行时 CPU 的能力在特定函数实现之间进行切换... 如果是这样的话,你可能也需要查看 target_clones 属性。

我想避免改变代码。然而,这证实了我在文档中确实没有漏掉任何内容,并且在命令行级别上限制自动向量化水平并没有被实现。 - user11488411

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接