首页 > 解决方案 > CLMUL 是常数时间吗?

问题描述

无进位乘法指令是否在恒定时间内运行?换句话说,执行所需的时间是否与其参数无关?

标签: assemblyx86micro-optimizationgalois-field

解决方案


根据https://agner.org/optimize/并且PCLMULQDQ在任何给定的 CPU 上都有固定的延迟。(http://www.uops.info/table.html没有列出它的延迟,但对于大多数指令都有很好的东西)。

没有理由期望它依赖于数据——在现代高性能 CPU 中,通常只有除法/sqrt 具有依赖于数据的性能。常规乘法不会:相反,它们只是在执行单元内部具有大量硬件并行性的一般情况下使其快速。

当微指令具有固定延迟时,乱序指令调度会容易得多,为它们构建全流水线执行单元也是如此。调度程序(预留站)可以避免在同一端口上同时完成 2 个操作并产生回写冲突。或者更糟糕的是,在同一个执行单元中并导致其中的停顿。这就是固定延迟非常普遍的原因。

(具有分支的微编码多微指令pclmulqdq可能具有可变延迟,或者更合理的延迟取决于立即操作数:当立即操作数非零时,可能会有一个或两个额外的随机播放微指令。因此,单个微指令参数的固定延迟不一定适用于微编码指令,但pclmuqdq仍然足够简单,以至于您不会期望它实际上以必须的方式rep movsb在内部分支。)


正如@fuz 指出的那样,PCLMUL 是为加密而设计的,因此依赖数据的性能会使其容易受到定时攻击。 所以有一个非常充分的理由让 PCLMUL 成为常数时间。(或者在最坏的情况下,依赖于立即数,但不依赖于寄存器/内存源。例如,一个立即数0可能会花费额外的移位微指令来将源的高半部分馈送到 64x64 => 128 无进位乘法单元。)


Agner Fog 表格中的数字

自 Broadwell 以来,在 Intel 上pclmuludq是 1 uop。在 Skylake 上,它是 7 个周期延迟,每个时钟吞吐量 1 个。(因此,您需要保持 7 个独立的 PCLMUL 操作处于运行状态,以使端口 5 上的执行单元饱和)。Broadwell 有 5 个周期的延迟。使用内存源操作数,它是 1 个额外的 uop。

在 Haswell 上,它是 3 uops (2p0 p5),具有 7 个周期延迟和每 2 个时钟吞吐量一个。

在 Sandybridge/IvyBridge 上,它是 18 微指令,14c 延迟,每 8 个时钟吞吐量一个。

在 Westmere(第 2 代 Nehalem)上,延迟为 12c,每 8c 吞吐量一个。(未知数量的 uops,Agner Fog 和 uops.info 都没有。但我们可以放心地假设它是微编码的。)这是支持指令的第一代——从 Nehalem 到 Westmere 的极少数差异之一。


在 Ryzen 上,它是 4 uop,4c 延迟,每 2 个时钟吞吐量一个。 http://instlatx64.atw.hu/显示它有 4.5 个周期的延迟。我不确定他们的测试和 Agner 的测试有什么区别。

在 Piledriver 上,它是 5 uops,12c 延迟,每 7 个时钟吞吐量一个。


在 Jaguar 上,它是 1 uop,3c 延迟,每 1 个时钟吞吐量一个!

在 Silvermont 上,它是 8 微指令,10c 延迟/吞吐量。Goldmont = 3 uop,6c lat / 3c tput。


另请参阅预测现代超标量处理器上的操作延迟有哪些考虑因素以及如何手动计算它们?和 Agner Fog 的优化指南,了解延迟和吞吐量(以及前端瓶颈)如何影响乱序 CPU 的性能,具体取决于周围的代码。


推荐阅读