这实际上是一个问题,其中一些甚至太宽泛了
有人可以解释为什么 C 决定使用 64 位双精度而不是硬件本机 80 位双精度吗?
它与 C 无关,因为 C 标准只规定了内置类型的最低要求,完全取决于编译器实现来选择他们想要用于类型的任何格式。没有什么能阻止 C 编译器使用一些定制的 77 位浮点类型
为什么硬件设置为 80 位双精度,因为它没有对齐?每个的性能影响是什么?
它与 2 个字节的倍数对齐。请记住,x87 可以追溯到 8086 + 8087。
对于现代硬件实现者和软件编写者来说,这是一个很好的权衡,他们需要更高的精度来进行精确的四舍五入double
操作。太大的类型,您将需要更多的晶体管。将有效数中的位数加倍,乘数需要是原来的 4 倍
x87 算术和初始 IEEE 754 标准提案的主要设计者 William Kahan 关于 x87 浮点开发的说明:“我们敢于扩展的格式(80 位)被包括在内,以提供与 13 - 十进制内部格式用于惠普的 10 位十进制计算器。”此外,Kahan 指出 64 位是在不增加 8087 循环时间的情况下进行进位传播的最宽有效位,并且 x87 扩展精度旨在在未来的处理器中扩展到更高的精度:“目前,10 -byte 扩展格式是超精确算术的价值和实现它以快速运行的代价之间的一个可容忍的折衷;很快,两个字节的精度将变得可以容忍,最终是 16 字节格式……那种当 IEEE Standard 754 for Floating-Point Arithmetic 制定时,就已经考虑到逐渐向更广泛的精度发展。
https://en.wikipedia.org/wiki/Extended_precision#IEEE_754_extended_precision_formats
如您所见,使用 64 位有效位,您可以与整数 ALU 共享组件(加法器、乘法器...)。
我想为我的默认数字类型使用 80 位双精度。但是编译器开发人员的选择让我担心这不是最佳选择。x86 上的 double 仅短 2 个字节,为什么编译器默认不使用 10 字节长的 double?
它实际上旨在用作临时变量(如tmp = (b*c + d)/e
)以避免内部溢出或下溢问题,而无需像Kahan summation这样的特殊技术。这不是您的默认浮点类型。long double
事实上,很多人在使用or时错误地使用了浮点字面量float
。他们忘记添加正确的后缀,导致精度不足,然后他们问为什么long double
与double
. 总之,double
应该用于几乎所有情况,除非您受到带宽或精度的限制并且您真的知道自己在做什么
我可以举一个 80 位长双精度与双精度的例子吗?
您可以打印完整的值并自己查看。还有很多值得一读的问题
为什么微软默认禁用 long double?
默认情况下, Microsoft不会禁用 long double。他们只是选择映射long double
到 IEEE-754 双精度,顺便说一下与double
. 该类型long double
仍然可以正常使用。他们这样做是因为 SSE 上的数学运算更快、更一致。这样你就可以避免像下面这样的“错误”
除了 64 位 long double 没有奇数大小,这需要编译器多填充 6 个零字节(或处理非 2 的幂类型宽度),这是一种资源浪费。
也就是说,甚至不是说 80 位long double
在 x86 上不可用。目前只有 MSVC 放弃了扩展精度类型,其他 x86 编译器(如 GCC、Clang、ICC...)仍然支持它,并将80 位 IEEE-754 设为long double 的默认格式。例如GCC 具有-mlong-double-64/80/128
并-m96/128bit-long-double
控制的确切格式long double
或者在不通过更改可能破坏 ABI 兼容性的情况下long double
,您可以使用GNU C 浮点类型名称,例如__float80
在支持它的目标上。 Godbolt 上的这个示例无论是针对 Windows 还是 Linux 都编译为 80 位 FP 数学。
就数量级而言,在典型的 x86/x64 PC 硬件上,long double 会差多少/慢多少?
这是无法回答的,因为延迟和吞吐量取决于每个特定的微架构。但是,如果您执行大量浮点运算,则double
速度会明显加快,因为它的有效位数较少,并且可以与 SIMD 并行化。例如,您可以使用AVX-512一次处理 8 个双精度数的向量。扩展精度类型无法做到这一点
此外,80 位 x87 fp 加载和存储指令比转换为/从 32 位或 64 位转换的“正常”版本慢得多,并且仅fstp
可用,而不是fst
. 请参阅Peter Cordes关于在现代 CPU 上进行 x87 性能逆向计算的回答。(事实上,这是一个跨站点副本,询问为什么 MSVC 不将 80 位 x87 类型公开为long double
.)