在 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具有相同的最佳情况(舍入除数)但更好的最坏情况,这也是有意义的。divssx87 精度位大概控制硬件分频器的方式完全相同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 没有太大区别。
对于尼哈勒姆:
fdiv7-27 个周期延迟 = 吞吐量(根本没有流水线化),脚注说Round divisors 或低精度给出低值。
divsd/ divpd7-22 周期延迟=吞吐量。
divss/ divps7-14 个周期延迟=吞吐量。
因此,所有形式的最佳情况性能(分频器占用 7 个周期)都是相同的,最坏情况变得更糟,可能的尾数位越多。
我们知道除法器硬件是迭代的,并且必须持续更长时间才能计算更多位,因此将 x87 精度设置为 24 位或 53 位以与 using完全相同的方式帮助性能是 100% 合理的divss。无论如何,它们共享相同的硬件执行单元。
IvyBridge 终于流水线化了 FP 分频器。与 IvB 相比,Haswell 没有对 div 数字进行任何重大更改。这些是 HSW 编号:
fdiv10-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 指令,例如fsinand 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 天以来的常见优化。