问题 为什么英特尔公布的一些Haswell AVX延迟比Sandy Bridge慢3倍?


在英特尔 内在的webapp,从Sandy Bridge到Haswell,几项行动似乎已经恶化。例如,许多插入操作(如_mm256_insertf128_si256)显示如下的成本表:

   Performance
 Architecture   Latency   Throughput
 Haswell        3         -
 Ivy Bridge     1         - 
 Sandy Bridge   1         - 

我发现这种差异令人费解。这有什么不同,因为有新的指令可以取代这些指令或补偿它的指令(哪些指令)?有谁知道Skylake是否进一步改变了这个模型?


1566
2018-03-08 05:08


起源

向量置换执行单元不像Sandy Bridge那样强大。还有其他事情也受到了打击(pmulld, roundss/sd/ps/pd)。这只是构建处理器的通常成本效益分析的一部分。在未来的设计中可能会牺牲“不太重要”的指令。也就是说,矢量置换非常重要,但至少它们将吞吐量保持在1 /周期。 - Mysticial
Haswell的重点是功耗。它确实这样做, 真 尽管功能缩小了。你不能兼得。 - Hans Passant


答案:


TL:DR:所有车道交叉shuffle /插入/提取在Haswell / Skylake上有3c延迟,但在SnB / IvB上有2c延迟,根据 Agner Fog的测试

这可能是执行单元中的1c +某种不可避免的旁路延迟,因为实际的执行单元在 通过Broadwell的SnB具有标准化的1,3或5个周期的延迟,而不是2或4个周期。 (SKL制作了一些uops uc 4c,包括FMA / ADDPS / MULPS)。

(请注意,在使用128b ALU执行AVX1的AMD CPU上(例如Bulldozer / Piledriver / Steamroller),insert128 / extract128比VPERM2F128之类的shuffle快得多。)


内在指南有时会出现虚假数据。我认为它适用于reg-reg形式的指令,除了负载内在函数的情况。即使它是正确的,内在指南也没有给出非常详细的性能图;请参阅下文,了解Agner Fog的表格/指南。


(我内心深处的一个问题就是难以使用 PMOVZX / PMOVSX 作为一个负载,因为提供的唯一内在函数需要一个 __m128i 来源,即使 pmovzxbd 仅加载4B或8B(ymm)。它和/或广播负载(_mm_set1_* 使用AVX1 / 2)是压缩内存中常量的好方法。应该有内在的东西 const char* (因为这允许别名))。


在这种情况下, Agner Fog的测量结果 表明SnB / IvB对reg-reg有2c延迟 vinsertf128/vextractf128虽然他对Haswell的测量(3c延迟,每1c输出一次)与英特尔的表一致。因此,英特尔内在指南中的数字是错误的另一种情况。 它非常适合寻找合适的内在数据,但不是可靠性能数据的良好来源。  它没有告诉你有关执行端口或总uop的任何信息,甚至经常忽略吞吐量数字。 无论如何,延迟通常不是向量整数代码中的限制因素。  这可能就是为什么英特尔让Haswell的延迟增加的原因。

reg-mem形式有很大不同。 vinsertf128 y,y,m,i 具有纬度/接收量:IvB:4/1,Haswell / BDW:4/2,SKL:5 / 0.5。它总是一个2-uop指令(融合域),使用一个ALU uop。 IDK为什么吞吐量如此不同。也许Agner的测试略有不同?

有趣的是, vextractf128 mem,reg, i 不使用任何ALU uops。它是一个2-fused-domain-uop指令,只使用存储数据和存储地址端口,而不是shuffle单元。 (Agner Fog的表将其列为在SnB上使用一个p015 uop,在IvB上使用0。但即使在SnB上,在任何特定列中都没有标记,因此IDK哪一个是正确的。)

这太愚蠢了 vextractf128 在立即操作数上浪费一个字节。我猜他们不知道他们将使用EVEX进行下一个向量长度扩展,并且正准备从0到3进行立即。但对于AVX1 / 2,你永远不应该使用immediate = 0来使用该指令。相反,只是 movups mem, xmm 要么 movaps xmm,xmm。 (我认为编译器知道这一点,当你使用index = 0的内在函数时就这样做了,就像他们那样做了 _mm_extract_epi32 等等 (movd)。)


延迟通常是FP代码中的一个因素,而Skylake是FP ALU的怪物。他们设法将FMA的延迟降低到4个周期,因此mulps / addps / fma ... ps都是4c延迟,每0.5c吞吐量一个。 (Broadwell是mulps / addps = 3c延迟,fma = 5c延迟.Haswell是addps = 3c延迟,mul / fma = 5c)。 Skylake放弃了单独的添加单元,因此addps实际上从3c恶化到4c,但吞吐量增加了一倍。 (Haswell / BDW只做了每1c吞吐量一次的添加,是mul / fma的一半。)所以 在大多数FP算法中使用许多向量累加器是必不可少的 如果存在循环携带的依赖性,则一次保持8或10个FMA在飞行中以使吞吐量饱和。否则,如果循环体足够小,则无序执行将立即在飞行中进行多次迭代。

整数通道内操作通常只有1c延迟,因此您需要更少的并行度来最大化吞吐量(并且不受延迟限制)。


将数据输入/输出ymm的高半部分的其他选项都没有更好

vperm2f128 或AVX2 vpermps 比较贵。通过内存将导致存储转发失败 - >插入的大延迟(2个窄存储 - >宽负载),所以它显然很糟糕。不要试图避免 vinsertf128 在它有用的情况下。

一如既往,尽量使用最便宜的指令序列。例如对于水平总和或其他减少,总是首先减少到128b向量,因为跨车道改组是缓慢的。通常它只是 vextractf128 / addps xmm那么平常 水平128b

正如Mysticial所提到的,Haswell以及后来对于128b向量具有SnB / IvB的一半的通道内矢量混洗吞吐量。 SnB / IvB可以 pshufb / pshufd 每0.5c吞吐量一个,但每1c只有一个 shufps (即使是128b版本);对于在AVX1中具有ymm版本的其他shuffle也是如此(例如 vpermilps,这显然只存在于FP load-and-shuffle可以在一条指令中完成。 Haswell完全摆脱了port1上的128b shuffle单元,而不是为AVX2扩展它。


回复:skylake

Agner Fog的指南/ insn表于12月更新,包括Skylake。另见  标记维基以获取更多链接。 reg,reg形式具有与Haswell / Broadwell相同的性能。


12
2018-03-09 06:04



我也很好奇他们删除了port1上的shuffle单元,以及这与观察有什么关系。我对该主题的有限知识表明,删除执行单元会影响吞吐量,而不是延迟。你有没有提到延迟增加的可能原因? - orm
我接受了你的回答,并喜欢阅读它并查看你推荐的一些链接。我认为其他一些寻求更快读取的人可能会从一开始就受益于TLDR。我认为关于替代方案的主要内容是,大多数(全部?)将数据移入/移出ymm寄存器的高半部分的事情在延迟方面是昂贵的,但不一定在吞吐量方面。 - orm
@orm:删除port1 shuffle单元对延迟没有影响,只有吞吐量。 (在资源冲突的情况下,如果insn在输入就绪后就无法启动,因为端口正在忙于运行也需要p5的旧版本。)感谢有关如何总结的建议;我完全不明白要把什么放进去;博士。 - Peter Cordes