AVX512 中的 128 位跨通道操作是否提供更好的性能?

Do 128bit cross lane operations in AVX512 give better performance?

在为 AVX256、AVX512 和有朝一日的 AVX1024 设计前瞻性算法并考虑 complexity/cost 大 SIMD 宽度的完全通用置换的潜在实现时,我想知道通常保持隔离的 128 位操作是否更好,即使在 AVX512 中?

特别是考虑到 AVX 有 128 位单元来执行 256 位操作。

为此,我想知道跨所有 512 位向量的 AVX512 置换类型操作与每个 4x128 位子 内的置换类型操作之间是否存在性能差异512 位向量的向量?

一般来说是的,在 SKX 上,通道内延迟仍然较低(1 个周期对 3 个周期),但通常 不值得花费额外的指令来使用他们 而不是强大的交叉车道洗牌。但是,vpermt2w 和其他一些洗牌需要多个洗牌端口 uops,因此它们的成本与多个更简单的洗牌一样多。

Shuffle 吞吐量 很容易成为瓶颈 如果你不小心最近的 Intel CPU(端口上只有一个 shuffle 执行单元5).有时甚至值得使用两个重叠加载而不是一次加载和混洗,即使用未对齐的加载作为混洗,因为 L1D 缓存很快,未对齐加载的加载端口处理也很快。 (不过,对于 AVX512 就不是这样了,尤其是因为每个未对齐的 512b 加载都会自动进行缓存行拆分,因为向量和缓存行都是 64 字节。)

对于 256 位加载,一个技巧是选择一个加载地址,将您关心的数据分成两个通道,这样您就可以使用 vpshufb (_mm256_shuffle_epi8) in-通道字节随机播放以获得需要的每个字节。

还有旋转(AVX512中的新)和移位指令(不是新的)。例如,如果您使用 32 或 16 的移位或旋转计数,则 64 位元素大小版本可以在较小的元素之间移动数据。 vprolq zmm, zmm, 32 是 1c 延迟,运行s 在端口 0(以及 xmm/ymm 版本的端口 1)上,将每个元素与其邻居交换。 Shifts/rotates 不要在 SKX 上竞争端口 5


For a horizontal sum,唯一真正的选择是按什么顺序洗牌。通常从 extract / add 开始到 128b,然后使用 __m128 洗牌(或整数移位),而不是每次随机播放都使用 vpermd/q。或者,如果您希望将结果广播到所有元素,请在前几次添加之间使用通道内洗牌,然后在 128b 和 256b 块中洗牌,并进行交叉洗牌。 (在 128b 块中洗牌并不比更小粒度的即时控制洗牌快,例如 SKX 上的 vpermq z,z,imm8,但这就是在使用 vshufpsvpermilps.)


请注意,某些未来的 AMD CPU 可能会将 512b 运算符拆分为两个 256b 运算符。那里的车道交叉洗牌要贵得多。即使 vperm2f128 在 Zen1 上也是 8 微指令,3c lat / 3c 吞吐量,而在 SKL 上是 1 微指令。车道内洗牌显然很容易分解为每个车道 1 uop,但车道交叉不会。


Xeon Phi(已停产)

在 KNL 上,重要的不是对线,而是 1 源与 2 源的洗牌
例如vshufps dst, same,same, imm8vpermilps dst, src, imm8.
吞吐量的一半 带有矢量控制的 1 源洗牌,如 vpermd v,v,v 仍然很快,但是(1 源 + 1 洗牌控制矢量)。

即使只有 1 uop,4-7c 延迟洗牌(2 输入)的吞吐量也比 2c 差。我想这意味着 KNL 的洗牌单元没有完全流水线化。


原始数据

https://uops.info/ is the go-to for uops / latency / ports microbenchmark info these days. Generally well-crafted microbenchmarks and detailed results that don't try to boil things down to a single number when there multiple uops and different latencies from different inputs to the ouput(s). And no manual typos like there sometimes are in Agner Fog's 否则很好的指令表。 Agner 的微架构指南是理解数字以及前端等可能的其他瓶颈的必备读物。

第一次写这个答案时,https://uops.info/ didn't exist, and Agner Fog didn't yet have test results for Skylake-X (SKX) aka SKL-SP or gcc -march=skylake-avx512. But there was already InstLatx64 (Instruction throughput/Latency) results, and IACA support. InstLatx64 has a spreadsheet (ODS OpenOffice/LibreOffice format) combining data from IACA (just uop count and ports), and published by Intel in a PDF (throughput/latency), and from real experimental testing on real hardware (throughput/latency). These days https://uops.info/ 可以很快测试新的微体系结构,但 InstLat 有时会在测试结果之前进行 CPUID 转储。

Agner Fog's 指令表包含 Knight's Landing Xeon Phi (KNL) 的数据,并且在他的微架构 PDF 中有一节是关于它的基于 Silvermont 的微架构。

如果 KNL 指令的输入来自同一执行单元(例如 shuffle -> shuffle)而不是 FMA -> shuffle,则它们的延迟会更好。 (请参阅 Agner 电子表格顶部的注释)。这就是 4-7c 延迟数字的含义。转置或执行一连串洗牌的操作可能主要看到较低的延迟数。 (但是 KNL 通常有很高的延迟,这就是为什么它有 4 路超线程 试图隐藏它们)。


SKX:Skylake-AVX512(可能还有未来的主流 Intel CPU)

所有通道交叉洗牌最多为 1 uop,3c 延迟,1c 吞吐量。但即使 complex/powerful 像 2-input vpermt2ps 这样的速度也很快。这包括所有洗牌整个通道的洗牌,或 insert/extract 256b 块。

所有仅车道内洗牌都是 1c 延迟(除了一些新的 avx512 车道交叉洗牌的 xmm 版本)。因此,当您需要时,请使用 vpshufd zmm, zmm, imm8vpunpcklqdq zmm, zmm, zmm。或 vpshufbvpermilps 带矢量控制输入。

像 Haswell 和 SKL(非 avx512)一样,SKX 只能运行 shuffle 端口 5 上的 uops。再次与那些早期的 CPU 一样,它可以仅使用加载端口进行广播加载,因此这与常规矢量加载一样便宜。 AVX512 广播负载可以微熔断,使内存源广播比寄存器源更便宜(就混洗吞吐量而言)。

甚至 vmovsldup ymm, [mem] / vmovshdup ymm, [mem] 也只使用加载 uop 进行 256b 洗牌。 IDK 约 512b; Instlat 没有测试 memory-source movsl/hdup,所以我们只有 Agner Fog 的数据。 (并且 IIRC 我在自己的 SKL 上确认了这一点)。

请注意,当 运行ning 512b 指令时,端口 1 上的向量 ALU 被禁用,因此每个时钟的最大吞吐量为 2 个向量 ALU 微指令。 (但是 p1 仍然可以 运行 整数。)向量 load/store uops 不需要 p0 / p5,所以你仍然可以在前端遇到瓶颈(每个时钟 4 uops issue/rename ) 在混合了非融合加载、存储和 ALU(以及整数循环开销和 vmovdqa 寄存器复制在重命名阶段使用未融合域 uop 处理)的代码中。

SKX 规则的例外情况:

  • VPMOVWB ymm, zmm 和类似的 t运行cate 或 signed/unsigned 饱和指令是 2 微指令,4c 延迟。 (或 2c 对于 xmm 版本)。 vpmovqd 是 1 uop,3c(或 1c xmm)延迟,因为它的最小粒度是 dword 并且它只是 t运行cating,而不是饱和,所以它可以使用与pshufb 例如。 vpmovz/sx 指令仍然只有 1 uop。

  • vpcompressd/q(基于掩码的左包)是 2 uops (p5),3c 延迟。 (或者根据 Intel 发布的 6c;也许 Instlat 正在测试向量-> 向量延迟,而 Intel 正在提供 k 寄存器 -> 向量延迟?它不太可能依赖于数据并且使用简单的掩码更快。)vpexpandd 也是 2 微指令。

  • AVX512BW vpermt2w / vpermi2w 是 3 微指令 (p0 + 2p5),所有 3 个操作数大小的 7c 延迟(xmm/ymm/zmm)。小粒度 wide shuffle 在硬件上很昂贵(参见 including the comments). This is a 2-source 16-bit-element shuffle with the control in a 3rd vector. It might get faster eventually in future generations, the way pshufb (and all full-register shuffles with granularity smaller than 8 bytes) was slow in first-gen Core2 Conroe/Merom,但在 die-shrink 下一代 (Penryn) 中速度很快。

  • AVX512BW vpermw (one-source lane-crossing word shuffle) 是 2p5, 6c latency, 2c throughput 因为它是 lane-crossing单词随机播放。

  • 预计 AVX512VBMI vpermt2b 在 Cannonlake 上会一样糟糕或更糟,即使 Cannonlake 确实有所改善 vpermt2w / vpermw.

  • vpermt2d/q/ps/pd 在 SKX 中都是有效的,因为它们的粒度是双字(32 位)或更宽。 (但 xmm 版本显然仍然有 3c 延迟,因此他们没有构建单独的硬件来加速单通道版本)。这些甚至比车道交叉口 shufps 更强大:一个变量控制并且没有限制每个元素来自哪个源寄存器。这是一个 完全 通用的 2 源混洗,您可以在其中对 2 个寄存器的串联进行索引,覆盖索引 (vpermi2*) 或其中一个表 (vpermt2*) .只有一个内在函数,因为编译器处理寄存器分配和复制以保留仍然需要的值。


骑士登陆地:

仅在 FP0 端口上 运行 随机播放,但前端吞吐量仅为每个时钟 2 微指令。因此,您的总指令中的更多部分可以在没有瓶颈的情况下进行洗牌(相对于 SKX),除非它们是半吞吐量洗牌。

一般来说,像 vperm2f128/vshuff32x4vshufps 这样的 2-input shuffle 是 2c throughput / 4-7c latency,而 1-input shuffle 如 vpermd是 1c 吞吐量/3-6c 延迟。 (即 2 个输入占用洗牌单元一个额外的周期(吞吐量的一半)并花费 1 个额外的延迟周期)。 Agner 不清楚不完全流水线洗牌的确切影响是什么,但我认为它只是捆绑了洗牌单元,而不是端口 FP0 上的所有内容(如 FMA 单元)。

  • 在KNL上是否穿越车道没有区别,例如vpermilpsvpermps 都很快(1c 吞吐量,3-6c 延迟),但 vpermi2psvshufps 都很慢(2c 吞吐量,4-7c 延迟)。对于 KNL 支持 AVX512 版本的说明,我没有看到任何例外情况。 (即不计算 AVX2 vpshufb,即几乎任何具有 32 位或更大粒度的东西)。

  • vinserti32x4 等等(insert/extract 粒度至少为 128b)是用于插入的 2-input shuffle,但速度很快:3-6c lat / 1c tput。但是提取到内存是多个 uops 并导致解码瓶颈:例如VEXTRACTF32X4 m128,z 是 4 微指令,每 8c 吞吐量一个。 (主要是因为解码)。

  • vcompress/ps/dvpcompressd/qv[p]expandd/q/ps/pd 是 1 uop,3-6c 延迟。 (与 SKX 上的 2 微指令相比)。但是每 3c 的吞吐量只有一个:Agner 没有指出这是否会占用 2c 的整个洗牌单元,或者是否只有这部分没有完全流水线化。

  • AVX2 byte/word 对于 256b 操作数大小的洗牌非常慢:pshufb xmm 是 5 uops / 10c 吞吐量,vpshufb ymm 是 12 uops / 12c 吞吐量。 (MMX pshufb mm 是 1 uop,2-6c 延迟,1c 吞吐量,所以我猜字节粒度洗牌单元是 64b 宽。)

    pshuflw xmm 快 1 微指令,但 vpshuflw ymm 是 4 微指令,8c 吞吐量。

    使用 128 位 AVX(vpsadbw xmm 很快),KNL 上的视频编码可能勉强值得,但 AVX2 ymm 指令通常比使用更多 1 uop xmm 指令慢。

  • movss/sd xmm,xmm 是一种混合,而不是随机播放,具有 0.5c 的吞吐量/2c 的延迟。

  • vpunpcklbw / wd 非常慢(xmm 版本除外),但即使对于 ymm / zmm 操作数大小,DQ 和 QDQ 也是常规速度。 (2c 吞吐量/4-7c 延迟,因为它是 2 输入随机播放)。

  • vpmovzx 是 3c 延迟(不是 3-6c?)和 2c 吞吐量,即使对于 vpmovzxbwvpmovsx 较慢:2 微指令,因此是解码瓶颈,使其成为 8c 延迟和 7c 吞吐量。缩小的 t运行cate 指令(vpmovqb 等)是 1 uop,3c lat / 1c tput,但缩小的饱和指令是 2 uops,因此很慢。 Agner 没有用内存目的地测试它们。