我正在学习SIMD内部函数和并行计算。我不确定英特尔对x86指令sqrtpd
的定义是否表明传递给它的两个数字的平方根将同时计算:
对源操作数(第二个操作数)中的两个、四个或八个压缩双精度浮点值的平方根执行SIMD计算,并将压缩双精度浮点数结果存储在目标操作数(第一个操作数。
我知道它明确表示SIMD计算,但这是否意味着对于该运算,将同时计算两个数字的根?
对于sqrtpd xmm
,是的,现代CPU确实是并行执行的,而不是一次通过一个更窄的执行单元运行。旧的(特别是低功耗的)CPU确实做到了这一点。对于AVXvsqrtpd ymm
,一些CPU确实将其分为两半执行。
但是,如果您只是将性能数字与较窄的操作进行比较,请注意,像Skylake这样的一些CPU可以将其宽div/sqrt单元的不同一半用于单独的sqrtpd/sd xmm
,因此这些CPU的吞吐量是YMM的两倍,即使它可以并行执行完整的vsqrtpd ymm
。
与AVX-512vsqrtpd zmm
相同,即使是Ice Lake也将其分为两半,正如我们从中看到的,它是3个uops(2个用于端口0,Intel将div/sqrt单元放在端口0上,它可以在其他端口上运行。)
3 uops是sqrt指令比Intel上的执行单元更宽的关键信号,但您可以查看YMM与XMM与标量XMM的吞吐量,了解它如何能够独立地为宽执行单元的不同管道提供更窄的操作。
唯一的区别是性能;目标x/y/zmm寄存器肯定具有每个输入元素的平方根。检查上的性能数字(和uop计数)https://uops.info/(目前下降,但通常非常好),和/或https://agner.org/optimize/.
允许但不能保证CPU内部有宽的执行单元,与它们支持的最宽向量一样宽,从而真正在并行管道中计算所有结果。
全宽执行单元对于除除法和平方根之外的指令是常见的,尽管从Bulldozer到Zen1之前的AMD支持只有128位执行单元的AVX/AVX2,因此vaddps ymm
解码为2个uops,每一半单独执行。英特尔Alder Lake E核心的工作方式也是如此。
一些古老的和/或低功耗CPU(如Pentium-M和K8,以及Bobcat)只有64位宽的执行单元,分两半运行SSE指令(对于所有指令,而不仅仅是像div/sqrt这样的"硬"指令)。
到目前为止,只有英特尔在任何CPU上支持AVX-512,而且(除了div/sqrt)它们都有全宽执行单元。不幸的是,他们还没有想出一种方法来展示强大的新功能,比如在没有完整AVX-512的情况下,在CPU上为128和256位矢量进行掩蔽和更好的混洗。AVX-512中有一些非常好的东西与更宽的矢量完全分离。
SIMDdiv/sqrt单元通常比其他单元窄
除法和平方根本身就很慢,不可能实现低延迟。管道成本也很高;没有当前的CPU能够在每个时钟周期启动新的操作。但最近的CPU一直在这样做,至少在部分操作中是这样:我认为它们通常以牛顿-拉斐森精化的几个步骤结束,并且该部分可以流水线化,因为它只涉及乘法/加法/FMA类型的操作。
英特尔从Sandybridge开始就支持AVX,但直到Skylake才将FPdiv/sqrt单元扩展到256位。
例如,Haswell将vsqrtpd ymm
作为3个uops运行,2个用于端口0(div/sqrt单元所在),1个用于任何端口,大概是为了重新组合结果。延迟大约是2倍,吞吐量是一半。(读取结果的uop需要等待两半都准备好。)
Agner Fog可能已经测试了vsqrtpd ymm
读取其自身结果的延迟;IDK如果英特尔可以让一半的操作在另一半准备好之前开始,或者合并的uop(或者不管是什么)最终会迫使它在启动另一半div或sqrt之前等待两半都准备好。div/sqrt以外的指令具有全宽执行单元,并且总是需要等待两半。
我还在一个关于浮点除法与浮点乘法的表中收集了各种CPU上YMM和XMM的divps/pd/sd/ss吞吐量和延迟
要完成@PeterOrderes的伟大答案,这确实是架构的依赖。。然而,人们可以期望在最新的主流处理器上并行计算两个平方根(或者可能在ALU级别高效地流水线计算)。以下是英特尔体系结构的延迟和吞吐量(您可以从英特尔获得):
体系结构 | 单延迟封装的XMM | 单吞吐量吞吐量封装的XMM | ||
---|---|---|---|---|
Skylake | 18 | 18 | 6 | |
骑士登陆 | 40 | 38 | >33 | <10>
是的,压缩操作数上的SIMD(矢量)指令对所有矢量元素执行相同的操作"并行";。这是由于sqrtsd
(一个double
上的标量平方根)和sqrtpd
(128位寄存器中两个double
上的压缩平方根)具有相同的延迟。
256位及更大矢量的vsqrtpd
在一些处理器上可能具有更高的延迟,因为操作是在矢量的128位部分上顺序执行的。vdivpd
可能也是如此,但其他指令则不然——大多数情况下,无论向量大小如何,延迟都是相同的。如果你想确定,请查阅说明表。