【问题标题】:Where is VPERMB in AVX2?AVX2 中的 VPERMB 在哪里?
【发布时间】:2024-01-06 22:18:01
【问题描述】:

AVX2 有很多好东西。例如,它有很多指令,这些指令比它们的前身要强大得多。以VPERMD 为例:它允许您完全任意地从一个 256 位长的 32 位值向量广播/洗牌/置换到另一个,并在运行时选择置换1。从功能上讲,这淘汰了一大堆现有的旧解包、广播、置换、随机播放和移位指令3

酷豆。

那么VPERMB 在哪里?即,相同的指令,但在字节大小的元素上工作。或者,就此而言,对于 16 位元素,VPERMW 在哪里?在涉足 x86 汇编一段时间后,很明显 SSE PSHUFB 指令几乎是有史以来最有用的指令之一。它可以进行任何可能的排列、广播或逐字节洗牌。此外,它还可用于进行 16 次并行 4 位 -> 8 位表查找2

不幸的是,PSHUFB 在 AVX2 中没有扩展到跨车道,因此它仅限于车道内行为。 VPERM 指令可以进行交叉洗牌(实际上,“perm”和“shuf”似乎是指令助记符中的同义词?)——但省略了 8 位和 16 位版本?

似乎甚至没有模拟此指令的好方法,而您可以轻松地用较小宽度的随机播放来模拟较大宽度的随机播放(通常,它甚至是免费的:您只需要不同的掩码)。

我毫不怀疑英特尔知道PSHUFB 的广泛使用和大量使用,所以自然会产生一个问题,为什么在 AVX2 中省略了字节变体。该操作本质上是否更难在硬件中实现?是否存在强制省略的编码限制?


1在运行时可选择,我的意思是定义洗牌行为的掩码来自寄存器。这使得指令比采用立即 shuffle 掩码的早期变体更灵活一个数量级,就像 addinc 更灵活,或者变量移位比立即移位更灵活。

2或 AVX2 中的 32 个此类查找。

3如果旧指令的编码较短,或者避免从内存中加载掩码,则旧指令有时会很有用,但在功能上它们已被取代。

【问题讨论】:

  • s/babble/dabble/?此外,“在运行时可选择”的一个好术语是“可变随机播放”。变量移位指令(如vpsrlvd)已经使用了这个术语。
  • 是的,dabble,虽然 babble 有时也很有意义。我不确定“变量”。我认为这种转变几乎与“是否立即”的问题是正交的。问题是你不能为不同的向量元素发出不同的班次计数。有点像 if vector add 只允许向所有元素添加单个值。这与参数是否只能指定为立即不同。当然,这种转变有点特别,因为大多数人甚至没有这个问题,这就是我对英特尔所说的“变量”的印象。
  • 哦,好点,您已经可以在 xmm reg 的 low64 中获得所有元素的移位计数。我仍然认为“变量洗牌”在没有解释的情况下立即显而易见,考虑到一些上下文。
  • 顺便说一句,你可以用大约 11 条指令(13 微指令)模拟 vpermi2b。如果您可以预处理要多次使用的置换向量,这将减少到 5 条指令(7 微秒)。

标签: assembly x86 intel sse avx2


【解决方案1】:

我 99% 确定主要因素是晶体管的实施成本。它显然非常有用,而它不存在的唯一原因是实施成本必须超过显着的收益。

不太可能出现编码空间问题; VEX 编码空间提供了很多空间。真的很多,因为表示前缀组合的字段不是位字段,它是一个整数,其中大部分值未使用。

不过,他们决定为 AVX512VBMI 实施它,在 AVX512BW 和 AVX512F 中提供更大的元件尺寸。也许他们意识到没有这个有多糟糕,并决定无论如何都要这样做。 AVX512F 需要大量芯片面积/晶体管来实现,以至于英特尔决定甚至不在零售台式机 CPU 中实现它for a couple generations

(部分原因是我认为现在很多可以利用全新指令集的代码都被编写为在已知服务器上运行,而不是在客户端机器上使用运行时调度)。

根据 Wikipedia,AVX512VBMI 直到 Cannonlake 才会出现,但随后我们将拥有 vpermi2b,它从 128B 表(2 个 zmm 向量)中进行 64 次并行表查找)。 Skylake Xeon 只会带来vpermi2w 和更大的元素尺寸(AVX512F + AVX512BW)。


我很确定 32 个 32:1 多路复用器比 8 个 8:1 多路复用器贵很多,即使 8:1 多路复用器宽 4 倍。他们可以通过多个洗牌阶段(而不是单个 32:1 阶段)来实现它,因为车道交叉洗牌需要 3 个周期的时间预算来完成他们的工作。但还是有很多晶体管。

我希望看到有硬件设计经验的人给出一个不那么随意的回答。我曾经用面包板上的 TTL 计数器芯片构建了一个数字计时器(和 IIRC,从 TI-99/4A 上的 BASIC 读取计数器,这在大约 20 年前就已经过时了),但仅此而已。


很明显,SSE PSHUFB 指令几乎是有史以来最有用的指令之一。

是的。这是第一个变量洗牌,带有来自寄存器而不是立即数的控制掩码。根据 pcmpeqb / pmovmskb 结果从随机播放蒙版的 LUT 中查找随机播放蒙版可以做一些疯狂而强大的事情。 @stgatilov's IPv4 dotted-quad -> int converter 是我最喜欢的出色 SIMD 技巧示例之一。

【讨论】:

  • 确实如此。我坚持使用笔记本电脑,直到我能买到 Skylake 笔记本电脑。只是发现只有“Xeons”才能获得 AVX512,后来发现它意味着“服务器部件”,正如您所指出的(使 Xeon 品牌混乱)。内在函数指南在这个计数上也令人困惑,显示 vpermi2b 与大量内在函数相关联,其中许多在 VBMI 之前出现。不过好在 VBMI :(
  • @BeeOnRope 哦,英特尔几乎没有在 AVX2/Haswell 上投入太多精力。他们复制粘贴了他们的执行单元,并在其上添加了一个非常轻量级的 3 循环跨车道置换。我怀疑他们重新设计了整个置换单元。如果我不得不猜测,他们把所有的精力都花在了让 3 输入微指令工作(对于 FMA)上,而他们无法做任何其他事情。
  • 通过将所有置换移动到端口 5,他们消除了从其他端口进行任何跨通道路由的需要。据我所知,在 Haswell 上,每条跨越 64 位边界的向量指令都在端口 5 上。据此,我们可以推断,端口 5 是 only 端口(除了加载/存储单元)具有跨 64 位通道的路由。从处理器设计的角度来看,这非常重要。我非常强调路由,因为它确实占用了那么多空间。虽然路由在芯片中是可堆叠 (3D) 的,但它们仍然只有少数几层。
  • @BeeOnRope 现在更新了 AVX512 硬件。 vpermw 仅是 32 位和 64 位粒度排列吞吐量的一半。延迟也是 7 个周期而不是 3 个周期。这意味着它通过 32 位置换单元(每个 3 个周期)进行双周期,然后通过 MUX 以选择正确的输出(1 个周期)。因此,如果 Cannonlake 上的 vpermb 通过原生 16 位置换进行双循环,或者通过与 Skylake X 相同的 32 位置换进行四循环,请不要感到惊讶。尽管考虑到模具收缩,我不排除单周期吞吐量vpermb
  • 另一个更新:Cannon Lake 的置换单元看起来像原生的全对全 64 路字节置换。 vpermwvpermb 是单周期吞吐量。但是 2-vector vperm2b 是 2-cycle 吞吐量。所以不是 最好的 可能的情况,但非常接近。 /cc @BeeOnRope
最近更新 更多