AVX指令集引入了VPERMILPS,它似乎是SHUFPS的简化版本(对于两个输入寄存器都相同的情况)。

例如,以下指令:

c5 f0 c6 c1 00          vshufps xmm0,xmm1,xmm1,0x0

可以替换为:
c4 e3 79 04 c1 00       vpermilps xmm0,xmm1,0x0

如您所见,VPERMILPS版本多花了一个字节,并且执行相同的操作。根据指令表,两条指令占用1个CPU周期,并且具有相同的吞吐量。

引入这种指导的意义何在?我想念什么吗?

最佳答案

是的,与vpermilps相比,使用vshufps -immediate通常是错过优化的选项(除了Knight's Landing以外),对于具有相同性能的同一操作,浪费了1个字节的代码大小。

我认为vpermilps的要点是它可以与矢量控制操作数一起使用。在AVX之前,唯一的可变控制随机播放是整数pshufb



但是,当然,立即数形式具有完全独立的操作码,您在问为什么它存在。英特尔肯定可以只包含矢量版本,因此问题变成“为什么它们包含立即版本?” 至少需要一点额外的解码硬件。随机播放单元已经具有以这种形式解包立即控制操作数的硬件,因为它与vshufps相同,因此实现起来可能便宜吗?

即时vpermilps唯一无法使用vshufps进行的操作是在一条指令中执行 load + shuffle,例如vpermilps ymm0, [rdi], 0b00011011来反转源中每个 channel 的元素。但是,像大多数带有立即数的指令一样,它无法对存储器操作数进行微融合,因此前端仍为2个融合域。 (在AMD CPU上,它确实确实节省了前端带宽。)尽管如此,与vmovups ymm0, [rdi]/vshufps ymm0,ymm0,ymm0, 0b00011011相比,它节省了代码大小。

除此之外,我没有多大意义。它们在两个128位 channel 中都执行相同的混洗,为两个 channel 重用立即数的4x 2位字段。 (虽然 vpermilpd vshufpd 都在其立即数中使用1位字段,并且可以在每个 channel 中执行不同的混洗;较高 channel 使用位2和3。ZMM版本使用较高位256的位4..7。因此再次vpermilpd dst, src, immvshufpd dst, src,src, imm相同,除非您使用内存源或使用改组控制向量而不是立即数。)

它使您想知道英特尔是否忘记了VEX编码将使无损vshufps能够为立即洗牌做同样的事情。

或者,也许他们想起了低功耗CPU,例如Knight's Landing(至强披披),一站式洗牌更便宜:
vpermilps在那里有1个周期的吞吐量,但是vshufpsvperm2f128却有2个周期的吞吐量和一个额外的延迟周期。 (根据Agner Fog's instruction tables。)

因此,在相同的输入中两次使用vshufps会比较慢。

但是在Intel大核心主流CPU上,与vpermilps相比,使用vshufps -immediate是一种错过优化的方法,除非您可以将其与内存源一起使用。 vshufps将需要两次相同的内存源,这显然是不可编码的。

AVX的设计比KNL提前了好几年,但ISA设计师可能会想到,将来某些CPU可能会通过更简单的改组来提高效率。

常规Silvermont(KNL所基于的无序Atom)不支持AVX,但它具有1 uop/1个周期的吞吐量和shufps的延迟。 Goldmont对于shufps的吞吐量为0.5c。

AFAIK,英特尔仍未使用AVX制造低功耗内核(至强融核除外)。我不认为他们打算使用Tremont或Gracemont(Goldmont Plus的后继产品)。

关于assembly - VPERMILPS指令(_mm_permute_ps)有什么意义?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54168726/

10-11 15:38