在为AVX256,AVX512和一天AVX1024设计前瞻性算法时,考虑到大SIMD宽度的完全通用置换的潜在实现复杂性/成本,我想知道即使在AVX512中通常保持隔离128位操作是否更好?
特别是考虑到AVX有128位单元来执行256位操作。
为此,我想知道在所有512位向量中AVX512置换类型操作之间是否存在性能差异,而在512位向量的每个4x128位子向量中是否存在置换类型操作?
通常是的,车道内的SKX延迟仍然较低(1个周期对3个),但通常不值得花费额外的指令来使用它们而不是强大的车道交叉shuffle。然而,vpermt2w
和其他几个shuffle需要多个shuffle-port uops,因此它们的成本与多个简单的shuffle一样多。
如果您对最近的Intel CPU(端口5上只有一个shuffle执行单元)不小心,则Shuffle吞吐量很容易成为瓶颈。有时甚至值得使用两个重叠的加载而不是加载一次并进行混洗,即使用未对齐的加载作为shuffle,因为L1D高速缓存很快,因此未对齐的加载的加载端口处理也是如此。 (尽管AVX512不太常见,特别是因为每个未对齐的512b加载都是自动缓存行分割,因为向量和缓存行都是64字节。)
还有旋转(AVX512中的新增功能)和移位指令(不是新的)。例如,如果使用移位或旋转计数32或16,则64位元素大小版本可以在较小元素之间移动数据。 vprolq zmm, zmm, 32
是1c延迟并且在端口0(以及xmm / ymm版本的port1)上运行,用它的邻居交换每个元素。换档/旋转不会在SKX上竞争端口5。
For a horizontal sum,唯一真正的选择是什么顺序进行改组。通常从extract
/ add
开始到128b,然后使用__m128
shuffle(或整数移位),而不是使用vpermd/q
进行每次shuffle。或者,如果您希望将结果广播到所有元素,请在前几个添加之间使用通道内随机播放,然后在128b中随机播放,然后使用通道交叉随机播放256b块。 (在128b块中进行混洗并不比SKX上的vpermq z,z,imm8
这样的小粒度即时控制混洗更快,但是在使用vshufps
或vpermilps
进行内部通道之后,这就是你需要的所有内容。)
在KNL上,它不是通道,它是1源和2源shuffle重要。
例如vshufps dst, same,same, imm8
是vpermilps dst, src, imm8
吞吐量的一半。
像vpermd v,v,v
这样的矢量控制的1源shuffle仍然很快(1个源+ 1个shuffle控制向量)。
即使它们只有1个uop,4-7c延迟洗牌(2输入)的吞吐量也低于2c。我想这意味着KNL的shuffle单元没有完全流水线化。
请注意,未来的某些AMD CPU可能会将512b操作分成两个256b操作(或可能是四个128b操作)。过道洗牌在那里显得更加昂贵。甚至Ryzen上的vperm2f128
也是8 uops,3c lat / 3c吞吐量,而SKL则为1 uop。车道内洗牌显然很容易分解为每个车道1个uop,但是车道交叉没有。
原始数据
对于Skylake-AVX512(又名Skylake-X,又名SKL-SP或SKX),有InstLatx64(指令吞吐量/延迟)结果,IACA支持它。 InstLatx64的a spreadsheet (ODS OpenOffice/LibreOffice format)结合了来自IACA的数据(只是uop计数和端口),并由英特尔以PDF(吞吐量/延迟)和实际硬件(吞吐量/延迟)的真实实验测试发布。检查主InstLat页面以获取更新。
Agner Fog's指令表有Knight's Landing Xeon Phi(KNL)的数据,并且在他的microarch PDF中有一个关于它的基于Silvermont的微体系结构的部分。不幸的是,他还没有SKX测试结果。
如果他们的输入来自相同的执行单元(例如shuffle - > shuffle)而不是FMA - > shuffle,则KNL指令具有更好的延迟。 (参见Agner电子表格顶部的注释)。这就是4-7c延迟数的含义。转置或做一连串洗牌的事情可能会看到较低的延迟数。 (但KNL通常具有较高的延迟,这就是为什么它有4路超线程来试图隐藏它们)。
所有车道交叉洗牌最多1个uop,3c延迟,1c吞吐量。但即使像2输入vpermt2ps
那样复杂/强大的也是那么快。这包括所有随机播放整个通道,或插入/提取256b块的shuffle。
所有仅限通道内的shuffle是1c延迟(除了xmm版本的一些新的avx512车道交叉shuffle)。所以当你需要的时候使用vpshufd zmm, zmm, imm8
或vpunpcklqdq zmm, zmm, zmm
。或vpshufb
或vpermilps
与矢量控制输入。
像Haswell和SKL(非avx512)一样,SKX只能在端口5上运行shuffle uops。再次像那些早期的CPU一样,它只能使用加载端口进行广播加载,因此它与常规向量加载一样便宜。 AVX512广播负载可以微融合,使得存储器源广播比寄存器源更便宜(以随机吞吐量方式)。
甚至vmovsldup ymm, [mem]
/ vmovshdup ymm, [mem]
只使用256b shuffle的加载uop。 IDK约512b; Instlat没有测试内存源movsl / hdup,所以我们只有Agner Fog的数据。 (和IIRC我在我自己的SKL上证实了这一点)。
请注意,运行512b指令时,端口1上的向量ALU将被禁用,因此每个时钟的最大吞吐量为2个向量ALU uop。 (但是p1仍然可以运行整数。)并且向量加载/存储uop不需要p0 / p5,所以你仍然可以在代码中混合使用前端(每个时钟4个uop发出/重命名)的瓶颈-fused load,stores和ALU(以及整数循环开销,以及使用unfused-domain uop在重命名阶段处理的vmovdqa寄存器复制)。
SKX规则的例外情况:
VPMOVWB ymm, zmm
和类似的截断或有符号/无符号饱和指令是2 uops,4c延迟。 (或xc版本的2c)。 vpmovqd
是1 uop,3c(或1c xmm)延迟,因为它的最小粒度是dword,它只是截断,而不是饱和,因此它可以在内部使用pshufb
所需的相同硬件实现。 vpmovz/sx
指令仍然只有1个uop。vpcompressd/q
(基于掩码的左包)是2 uops(p5),3c延迟。 (或者6c根据英特尔发布的内容;也许Instlat正在测试矢量 - >矢量延迟,而英特尔正在给出k
寄存器 - >矢量延迟?不太可能它依赖于数据并且通过一个简单的掩码更快。)vpexpandd
也是2 uops 。vpermt2w
/ vpermi2w
为3 uops(p0 + 2p5),所有3个操作数大小为7c延迟(xmm / ymm / zmm)。小粒度宽洗牌在硬件上很昂贵(参见Where is VPERMB in AVX2?,包括评论)。这是一个双源16位元素shuffle,控件在第3个向量中。它最终可能在未来几代中变得更快,pshufb
(以及粒度小于8字节的所有全寄存器shuffle)was slow in first-gen Core2 Conroe/Merom,但在下一代(Penryn)的缩减中得到快速。vpermw
(单源跨越字随机播放)是2p5,6c延迟,2c吞吐量,因为它是一个跨越字道的shuffle。vpermt2b
在Cannonlake上变得更糟或更糟,即使Cannonlake确实改善了vpermt2w
/ vpermw
。vpermt2d/q/ps/pd
在SKX中都很有效,因为它们的粒度是dword(32位)或更宽。 (但是xmm版本显然仍然是3c延迟,所以他们没有构建单独的硬件来加速单通道版本)。这些甚至比跨越交叉的shufps
更强大:变量控制,并且不限制每个元素来自哪个源寄存器。它是一个完全通用的2源shuffle,您可以在其中索引2个寄存器的串联,覆盖索引(vpermi2*
)或其中一个表(vpermt2*
)。只有一个内在因为编译器处理寄存器分配和复制以保留仍然需要的值。Shuffle仅在FP0端口上运行,但前端吞吐量仅为每个时钟2个uop。因此,除非他们是半吞吐量混洗,否则你的总指令中的更多可以是混乱而没有瓶颈(与SKX相比)。
通常,像vperm2f128
/ vshuff32x4
或vshufps
这样的2输入shuffle是2c吞吐量/ 4-7c延迟,而像vpermd
这样的1输入shuffle是1c吞吐量/ 3-6c延迟。 (即,2个输入占用混洗单元一个额外的周期(半吞吐量)并且花费1个额外的延迟周期)。 Agner并不清楚未完全流水线的shuffle究竟是什么效果,但我认为它只是捆绑了shuffle单元,而不是端口FP0上的所有东西(如FMA单元)。
vpermilps
和vpermps
都很快(1c吞吐量,3-6c潜伏期),但vpermi2ps
和vshufps
都很慢(2c吞吐量,4-7c潜伏期)。对于KNL支持AVX512版本的说明,我没有看到任何例外情况。 (即不计算AVX2 vpshufb
,即几乎任何具有32位或更大粒度的东西)。vinserti32x4
等(插入/提取粒度至少为128b)是插入的2输入shuffle,但速度很快:3-6c lat / 1c tput。但是提取到内存是多个uop并导致解码瓶颈:例如VEXTRACTF32X4 m128,z
是4 uops,每8c吞吐量一个。 (主要是因为解码)。vcompress/ps/d
,vpcompressd/q
和v[p]expandd/q/ps/pd
是1 uop,3-6c潜伏期。 (在SKX上为2 uops)。但吞吐量仅为每3c一个:Agner并不表示这是否会占用2c的整个洗牌单元,或者只是这个部分没有完全流水线化。pshufb xmm
是5 uops / 10c吞吐量,vpshufb ymm
是12 uops / 12c吞吐量。 (MMX pshufb mm
是1 uop,2-6c延迟,1c吞吐量,所以我猜字节粒度shuffle单位是64b宽。)
pshuflw xmm
快1便士,但vpshuflw ymm
是4 uops,8c吞吐量。
使用128位AVX(vpsadbw xmm
很快),KNL上的视频编码可能几乎不值得,但AVX2 ymm指令通常比使用更多1 uop xmm指令慢。movss/sd xmm,xmm
是一种混合,而不是随机播放,具有0.5c吞吐量/ 2c延迟。vpmovzx
即使对于vpmovzxbw
也是3c延迟(不是3-6c?)和2c吞吐量。 vpmovsx
较慢:2 uops,因此解码瓶颈,使其8c延迟和7c吞吐量。变窄的截断指令(vpmovqb
等)是1 uop,3c lat / 1c tput,但是变窄的饱和指令是2 uop,因此很慢。 Agner没有用内存目的地测试它们。