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将上限通道设置为零,而SHUFPS则将其保持不变。
答案 0 :(得分:6)
与vpermilps
(对于Knight's Landing除外)相比,立即使用vshufps
-速成通常是错过优化的情况,因为相同操作和相同性能会浪费1个字节的代码大小。
我认为vpermilps
的要点是它可以与向量控制操作数一起使用。在AVX之前,唯一的可变控制随机播放是整数pshufb
。
VPERMILPS ymm1, ymm2, ymm3/m256
-使用ymm3 / m256中的控件在ymm2中置换单精度浮点值,并将结果存储在ymm1中。
但是,当然,立即数形式具有完全独立的操作码,您在问为什么它存在。英特尔肯定可以只包含矢量版本,因此问题变为“为什么它们包含立即版本?” 。它至少需要一点额外的解码硬件。随机播放单元已经具有以这种形式解包立即控制操作数的硬件,因为它与vshufps
相同,因此实现起来便宜吗?
您无法使用即时vpermilps
执行的唯一操作vshufps
是在一条指令中加载+随机播放,例如vpermilps ymm0, [rdi], 0b00011011
进行反转源中每个通道中的元素。但是,像大多数带有立即数的指令一样,它无法对存储器操作数进行微融合,因此前端仍为2个融合域。 (在AMD CPU上,它确实确实节省了前端带宽。)不过,与vmovups ymm0, [rdi]
/ vshufps ymm0,ymm0,ymm0, 0b00011011
相比,它节省了代码大小。
除此之外,我没有多大意义。它们在两个128位通道中都执行相同的混洗,为两个通道重用立即数的4x 2位字段。 (虽然vpermilpd
和vshufpd
在其立即数中都使用1位字段,并且可以在每个通道中执行不同的混洗;较高通道使用位2和3。ZMM版本使用位4。 7为高位256。因此,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
-immediate与vshufps
相比是错过优化的方法,除非您可以将其与内存源一起使用。 vshufps
将需要两次相同的内存源,这显然是无法编码的。
AVX的设计比KNL提前了好几年,但也许ISA设计师铭记在心,将来某些CPU可能会通过更简单的改组来提高效率。
常规Silvermont(KNL所基于的无序Atom)不支持AVX,但它具有1 uop / 1个周期的吞吐量和shufps
的延迟。 Goldmont对于shufps
的吞吐量为0.5c。
AFAIK,英特尔仍未使用AVX制造低功耗内核(至强融核除外)。我不认为他们打算与Tremont或Gracemont(Goldmont Plus的继任者)一起使用。