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, imm
与vshufpd dst, src,src, imm
相同,除非您使用内存源或使用改组控制向量而不是立即数。)
它使您想知道英特尔是否忘记了VEX编码将使无损vshufps
能够为立即洗牌做同样的事情。
或者,也许他们想起了低功耗CPU,例如Knight's Landing(至强披披),一站式洗牌更便宜:vpermilps
在那里有1个周期的吞吐量,但是vshufps
或vperm2f128
却有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/