【问题标题】:Do 128bit cross lane operations in AVX512 give better performance?AVX512 中的 128 位交叉通道操作是否提供更好的性能?
【发布时间】:2018-05-18 16:17:02
【问题描述】:

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

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

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

【问题讨论】:

  • 您对 KNL 还是 Skylake-X 更感兴趣?无论如何,都要为两者找到答案。但一般来说,SKX 对于车道内的东西仍然有 1c 的延迟,对于车道交叉有 3c 的延迟。一些更高级的 AVX512BW shuffle 甚至在 SKX 上使用多个微指令,例如 vpermt2w
  • 我对未来的规划更感兴趣,即高端通用面向消费者的桌面 CPU - 所以 Skylake X。谢谢。
  • @PaulR:IACA2.3 有 SKX 但没有 KNL:/ Instlat 为 SKX 制作了 IACA 的 uop 计数/端口分配的电子表格。 (见我的回答)IACA 的管道跟踪日志输出可能会给您带来延迟,但我认为这与英特尔以 PDF 形式单独发布的内容相匹配。
  • 鉴于 AVX512 atm 存在大量问题,我认为 AVX1024 至少在十年内(如果有的话)都不会出现。相比之下,引入 AVX 的问题相对较少。 EVEX 编码也没有为 1024 位版本的某些功能(如嵌入式舍入)留下空间,除非它们滥用操作码。因此,如果发生这种情况,英特尔很可能会更改编码(再次)。
  • @iam 1) 它至少被推迟了一年,但仍然不可用。 2) 需要一种更好的方法来为 AVX512 供电。您不能让一条指令搞乱整个应用程序和/或系统的时钟。 3)没有足够的内存带宽来支持它。 - 这还不包括实际使用它的通常开发开销。但这是所有 ISA 扩展的共同点。

标签: performance x86 intel avx avx512


【解决方案1】:

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

如果您对最近的 Intel CPU 不小心(端口 5 上只有一个 shuffle 执行单元),

Shuffle 吞吐量很容易成为瓶颈。有时甚至值得使用两个重叠的加载,而不是加载一次并进行混洗,即使用未对齐的加载作为混洗,因为 L1D 缓存很快,加载端口处理未对齐的负载也是如此。 (不过,对于 AVX512,情况就不那么好了,尤其是因为每个未对齐的 512b 加载都会自动拆分缓存行,因为向量和缓存行都是 64 字节。)

对于 256 位加载,一个技巧是选择一个加载地址,将您关心的数据分成两个通道,因此您可以使用 vpshufb (_mm256_shuffle_epi8) 通道内字节洗牌来获取每个字节在需要的地方。

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


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


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


至强融核(停产)

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

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


原始数据

https://uops.info/ 是这些天来获取微指令/延迟/端口微基准信息的首选。通常精心设计的微基准测试和详细结果不会试图将事情归结为一个数字,当有多个微指令和来自不同输入到输出的不同延迟时。 Agner Fog's 中没有像有时那样的手动拼写错误,否则很好的说明表。 Agner 的微架构指南是了解数字以及前端可能存在的其他瓶颈的必备读物。

首次编写此答案时,https://uops.info/ 不存在,Agner Fog 还没有 Skylake-X (SKX) aka SKL-SP 或 gcc -march=skylake-avx512 的测试结果。但是已经有InstLatx64(指令吞吐量/延迟)结果,以及IACA 支持。 InstLatx64 具有a spreadsheet (ODS OpenOffice/LibreOffice format) 结合来自 IACA 的数据(仅 uop 计数和端口),并由英特尔以 PDF 格式发布(吞吐量/延迟),以及真实硬件上的真实实验测试(吞吐量/延迟)。现在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 吞吐量。但即使是像 2-input vpermt2ps 这样的复杂/强大的也如此之快。这包括所有打乱整个通道或插入/提取 256b 块的打乱。

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

与 Haswell 和 SKL(非 avx512)一样,SKX 只能在端口 5 上运行 shuffle uops。再次与那些早期的 CPU 一样,它可以仅使用加载端口进行广播加载,因此与常规矢量加载一样便宜。 AVX512 广播负载可以微融合,使内存源广播比寄存器源更便宜(在随机吞吐量方面)。

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

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

SKX 规则的例外情况:

  • VPMOVWB ymm, zmm 和类似的截断或有符号/无符号饱和指令是 2 uop,4c 延迟。 (或 2c 用于 xmm 版本)。 vpmovqd 是 1 uop,3c(或 1c xmm)延迟,因为它的最小粒度是 dword,它只是截断而不是饱和,因此它可以在内部使用 pshufb 所需的相同硬件实现。 vpmovz/sx 指令仍然只有 1 uop。

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

  • AVX512BW vpermt2w / vpermi2w 为 3 微秒 (p0 + 2p5),所有 3 种操作数大小 (xmm/ymm/zmm) 的延迟为 7c。小粒度宽洗牌的硬件成本很高(请参阅Where is VPERMB in AVX2?,包括 cmets)。这是一个 2 源 16 位元素随机播放,控件位于第三个向量中。它最终可能会在未来几代中变得更快,就像pshufb(以及所有粒度小于 8 字节的全寄存器洗牌)was slow in first-gen Core2 Conroe/Merom,但在 die-shrink 下一代 (Penryn) 中变得更快。

  • AVX512BW vpermw(单源跨车道混词)是 2p5、6c 延迟、2c 吞吐量,因为它是跨车道混词。

  • 预计 AVX512VBMI vpermt2b 在 Cannonlake 上的表现会一样糟糕或更糟,即使 Cannonlake 确实改善了 vpermt2w / vpermw

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


骑士登陆:

Shuffle 仅在 FP0 端口上运行,但前端吞吐量仅为每个时钟 2 微秒。因此,您的总指令中的更多可以是随机播放而不会造成瓶颈(与 SKX 相比),除非它们是半吞吐量的随机播放。

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

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

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

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

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

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

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

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

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

  • vpmovzx 是 3c 延迟(不是 3-6c?)和 2c 吞吐量,即使对于 vpmovzxbwvpmovsx 较慢:2 uop,因此是解码瓶颈,使其延迟为 8c,吞吐量为 7c。收窄截断指令(vpmovqb 等)为 1 uop,3c lat / 1c tput,但收窄饱和指令为 2 uop,因此速度较慢。 Agner 没有用内存目标测试它们。

【讨论】:

  • 这是一个非常了不起的答案。也许 mystical 的评论“限制数据移动通常是个好主意..”构成了最后一个好的总结的基础?
  • 好的,突出显示效果很好,可以阻止我的大脑从头开始浏览:)
  • @iam:添加了一些更通用的性能背景资料,尝试提供一些通用建议是个好主意。例如有时您可以使用更多未对齐的加载和更少的随机播放。
  • 谢谢 - 在当前计划如何将基于 128 位的工作矢量代码扩展到 256 位及更高版本时非常有帮助。当前瓶颈与数据混洗/置换/收集相关,我担心与此相关的算法粒度。
  • “电子表格(ODS OpenOffice/LibreOffice 格式)”的链接已损坏
猜你喜欢
  • 1970-01-01
  • 2011-01-11
  • 1970-01-01
  • 2020-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多