我想要一个长等待时间的单指令x861指令,以便创建长的依赖链,作为测试微体系结构功能的一部分。
目前,我正在使用fsqrt
,但是我想知道是否还有更好的东西。
理想情况下,该指令在以下标准上得分会很高:
延迟长
稳定/固定的延迟
一或几微码(特别是:未微码)
消耗尽可能少的uarch资源(加载/存储缓冲区,页面遍历器等)
能够自己链接(延迟)
能够通过GP寄存器链接输入和输出
不会干扰正常的OoO执行(除了消耗的ROB,RS等资源之外)
因此fsqrt
在大多数情况下都可以,但是等待时间不是那么长,并且似乎很难与GP规则链接。
1特别是在现代Intel x86上,如果它在AMD Zen *上也能很好地工作,则可以加分。
最佳答案
主流Intel CPU没有任何非常长的延迟单uup整数指令。在所有ALU端口上都有用于1周期等待时间的整数ALU,在端口1上有3周期等待时间的流水线ALU。我认为AMD是相似的。
div / sqrt单元是唯一真正的高延迟ALU,但是整数div / idiv是在Intel上进行微编码的,因此,请使用FP,其中div / sqrt通常是单uup指令。
AMD的整数div
/ idiv
是2 uop指令(可能要写入2个输出),并具有与数据相关的延迟。
同样,AMD Bulldozer / Piledriver(2个整数内核共享一个SIMD / FP单元)对于movd xmm, r32
(10c 2 uops)和movd r32, xmm
(8c 1 uop)具有很高的延迟。 Steamroller将其缩短1c。 Ryzen在任一方向上都有3个循环1个单位。
在Intel上,往返XMM regs的movd
便宜:1周期(Broadwell和更早版本)或2周期延迟(Skylake)的单Uop。 (https://agner.org/optimize/)sqrtss
具有固定的延迟时间(在IvB及更高版本上),可能输入不正常。如果带整数的链仅涉及任意整数位模式的movd xmm, r32
,则可能需要设置DAZ / FTZ以消除FP辅助的可能性。 NaN输入很好;不会导致SSE / AVX数学运算变慢,只有x87。
其他CPU(Sandybridge和更早的版本,以及所有AMD)都具有可变延迟sqrtss
,因此您可能希望在此处控制起始位模式。
如果您想使用sqrtsd
来实现每uop的延迟要比sqrtss
高,则同样如此。即使在Skylake上,延迟仍然是可变的。 (15-16个周期)。
您可以假设等待时间是输入位模式的纯函数,因此每次以相同的输入启动sqrtss
指令链将产生相同的等待时间序列。或者使用0.0
,1.0
,+inf
或NaN
作为开始输入,您将为序列中的每个uop获得相同的延迟。
(简单的输入(如1.0和0.0(输入和输出中的有效数字很少))可能以最低的延迟运行。sqrt(1.0)= 1.0和sqrt(0)= 0,所以它们是自持久的。sqrt(NaN )= NaN)
您可以在链中使用and reg, 0
或其他不中断零位的零位来控制输入位模式。也许or reg, -1
创建NaN。然后,您可以在Sandybridge或更早版本以及包括Zen在内的AMD上获得固定的延迟。
或者,也许pinsrw xmm0, eax, 7
(Intel 5端口为2 uops)仅修改XMM的高位qword,而将底部保留为已知的0.0
或1.0
。除非端口5的压力不是问题,否则将and
设为0并使用movd
可能更便宜。
要创建吞吐量瓶颈(而不是延迟),在Skylake上最好的选择是vsqrtpd ymm
-p0为1 uop,延迟= 15-16,吞吐量= 9-12。
在Broadwell和更早的版本上,这是3微秒(2p0 p15),但是我认为Skylake拓宽了SIMD分频器(我想是为准备AVX512)。