在 fpu 切换到单精度模式前几年,我在旧 fpu 上读到过,除法和 sqr 的速度是正常模式下的两倍。
(检查它的来源http://stereopsis.com/FPU.html)
还是这样,这样的切换可以加快一些循环,在里面产生很多浮点代码?
第二个问题相关,例如,在执行系统(winapi)调用时,我可以在代码中自由地玩弄 FPU 精度吗,与 fpu 舍入模式和系统端相同,api 是否也会破坏我的设置?
在 fpu 切换到单精度模式前几年,我在旧 fpu 上读到过,除法和 sqr 的速度是正常模式下的两倍。
(检查它的来源http://stereopsis.com/FPU.html)
还是这样,这样的切换可以加快一些循环,在里面产生很多浮点代码?
第二个问题相关,例如,在执行系统(winapi)调用时,我可以在代码中自由地玩弄 FPU 精度吗,与 fpu 舍入模式和系统端相同,api 是否也会破坏我的设置?
是的,Agner Fog 的吞吐量/延迟数字与降低 x87 精度以加快最坏情况的速度完全一致。
考虑到现代 div/sqrt 硬件的工作方式,使用 Radix-16 或 Radix-1024 分频器迭代计算结果的更多位,这也是有意义的,因此需要更少的正确位意味着您可以更快地停止。(GCC 的 sqrt() 编译后是如何工作的?用的是哪一种 root 方法?Newton-Raphson?和Intel x86 处理器的整数除法算法)
fdiv
考虑到 x87和 SSE1divss
在相同的硬件上运行,divss
具有相同的最佳情况(舍入除数)但更好的最坏情况,这也是有意义的。divss
x87 精度位大概控制硬件分频器的方式完全相同divsd
。
详情如下
是的,x87 可以限制为 64 位或 32 位总宽度(double
或float
),低于标准的 80 位。 是的,这确实稍微加快了fsqrt
最坏fdiv
情况的速度,使其速度与相同精度的标量 SSE/SSE2 大致相同(sqrtss
= 标量单 / sqrtsd
= 标量双)。没有其他东西运行得更快或更慢。
它不会使x87 比 SSE 更快,所以在这一点上,它主要是 CPU 历史的好奇。
显然 DirectX 确实(曾经?)实际上将 x87 精度设置为 24 位尾数(float
),并且 MSVC 的 CRT 启动用于将其设置为 53 位尾数(double
)。请参阅 Bruce Dawson 的https://randomascii.wordpress.com/2012/03/21/intermediate-floating-point-precision/。但微软的历史怪异是个例外;其他工具链/操作系统不会乱用 x87。
Agner Fog 的指令表没有提到 Sandybridge 或更高版本 CPU 的 x87 精度。这可能意味着它不再有帮助,或者(我认为)Agner 认为它不值得一提。他的 SnB 和更新的表格没有任何脚注,所以我认为这就是解释。据我所知,SnB 的分频器与 NHM 没有太大区别。
对于尼哈勒姆:
fdiv
7-27 个周期延迟 = 吞吐量(根本没有流水线化),脚注说Round divisors 或低精度给出低值。
divsd
/ divpd
7-22 周期延迟=吞吐量。
divss
/ divps
7-14 个周期延迟=吞吐量。
因此,所有形式的最佳情况性能(分频器占用 7 个周期)都是相同的,最坏情况变得更糟,可能的尾数位越多。
我们知道除法器硬件是迭代的,并且必须持续更长时间才能计算更多位,因此将 x87 精度设置为 24 位或 53 位以与 using完全相同的方式帮助性能是 100% 合理的divss
。无论如何,它们共享相同的硬件执行单元。
IvyBridge 终于流水线化了 FP 分频器。与 IvB 相比,Haswell 没有对 div 数字进行任何重大更改。这些是 HSW 编号:
fdiv
10-24c 延迟,8-18c 吞吐量divsd
/ divpd xmm
: 10-20c 延迟,8-14c 吞吐量divss
/ divps xmm
: 10-13c 延迟,7c 吞吐量(固定延迟对调度程序来说很好)另请参阅浮点除法与浮点乘法,其中我收集了 Agner Fog 的最新 Intel CPU 数据,包括 256 位 YMM 向量。我在那里省略了 x87,因为它基本上与高性能无关。
通常您只使用 SSE1,因为它通常更快(由于平坦的寄存器集和 2 操作数指令而不是堆栈,因此无需在fxch
和寄存器副本上花费前端带宽)。fld
并且在某些情况下使用 SIMD 的机会(通常 4x float sqrt 结果与 1 相同)使其与将 x87 FPU 设置为 32 位相比是一个巨大的胜利。
大多数 SSE 数学指令的吞吐量和延迟与 x87 对应的指令相似,但 x87 的开销更大。
如果您需要制作与古代CPU兼容的 32 位二进制文件,甚至没有 SSE1fdiv
,是的,如果fsqrt
性能对您的代码很重要,您可以将 x87 精度降低到 24 位。(可能还可以加速一些微编码的 x87 指令,例如fsin
and fyl2x
,IDK。)
或者,如果将精度降低到float
过于激烈,那么您将double
在 XMM regs 中查看 SSE2 的数学。它是 x86-64 的基线,因此如果您出于某种原因必须制作 32 位二进制文件,则再次值得考虑。没有它的最新 CPU 是 Athlon XP。(如果您不计算当前 Geode 之类的东西。)
与fpu舍入模式和系统端相同,api也会破坏我的设置吗?
AFAIK,什么都不会改变舍入模式。那将是一个很大的差异,并且对性能没有帮助。
如果有人能够证明这样做是合理的,那么有人会这样做是为了在(int)float
没有 SSE convert-with-truncation 指令(或 SSE3fisttp
用于 x87 版本)的情况下使用 C 的性能,以避免必须将 x87 舍入模式设置为截断(接近 0),然后在每次 FP 值转换为整数时恢复它。
大多数编译器在优化时假定舍入到最近。
我的理解是,精度对传统 x86 FPU 速度的影响几乎以 i486 结束。不过,这是 8087 天以来的常见优化。