提问人:anymous.asker 提问时间:8/28/2021 最后编辑:phuclvanymous.asker 更新时间:2/2/2022 访问量:248
PPC64长双机ε计
PPC64 long double's machine epsilon calculation
问:
我正在玩一个在 qemu 中模拟的 PPC64 虚拟机,试图模仿 POWER8 CPU。
在这里,该类型与 x86 中用于长双精度的 80 位浮点不同,并且从我所看到的情况来看,它也不符合 IEEE754 的 float128,因为它根据 C 宏有一个 106 位的尾数(而 112 位尾数由 IEEE754 为其 float128 指定)。long double
LDBL_MANT_DIG
维基百科说,IEEE754 float128 应该有一个大约 1.93e-34 的机器 epsilon,这比 80 位 x86 float (1.08e-19) 要好得多。
然而,当我尝试在这个虚拟机中获取机器 epsilon 时,我得到了一个相当令人惊讶的答案:
#include <iostream>
int main()
{
long double eps = 1.0l;
while (1.0l + 0.5l * eps != 1.0l)
eps = 0.5l * eps;
std::cout << eps << std::endl;
return 0;
}
它输出以下内容:
4.94066e-324
我从中得到相同的结果。LDBL_EPSILON
std::numeric_limits<long double>::epsilon()
这将使它比预期的精度高出大约10倍,从逻辑上讲,这应该是不可能的。鉴于螳螂正好是 2x53(IEEE754 的 float64),我认为它可能使用了双双结构,维基百科还说,在小数字方面的精度应该低于IEEE754 float128。
这是怎么回事?
答:
首先,让我假设您的操作系统是 Linux。到目前为止,64 位 PowerPC 上的所有编译器都默认使用“double-double”类型,其格式不符合 IEEE。long double
格式实际上是两个 s 的组合,因此将其理解为 .高部与普通部分没有什么不同,而低部则提供延长的尾数。整数的指数与 相同,这意味着它的最大可表示数不比 的大几个数量级(因为 double-double 的尾数更长,所以它们仍然不同)。double
struct { double high; double low; }
double
double
double
目前,双双浮点数的运算没有原生的 PowerPC 指令支持。long double 最终将被转换为对函数的调用。(LLVM 的 compiler-rt 和 GCC 的 libgcc 都有其实现,参见 add 函数的源代码a+b
__gcc_qadd
)
从 POWER ISA 3.0 (Power9) 开始,支持对“binary128”(符合 IEEE 标准的 128 位浮点类型)的本机指令支持。您可以使用来启用该功能并用于表示它,或者添加 -mabi=ieeelongdouble
以使编译器将 long double 视为 binary128 而不是 double-double(以及 C 库声明)。-mcpu=power9 -mfloat128
__float128
Binary128 不是两个双精度的组合,而是用向量寄存器存储/传递,并且比双精度高得多,具有 112 位尾数和 15 位指数。GCC/Clang 实际上通过使用 compiler-rt/libgcc 中的支持函数来支持 VSX(Power7 或更高版本)目标的 binary128。(例如,为 Power9 及更高版本、Power7 和 Power8 生成指令)a+b
xsaddqp
__addkf3
如果您的工具链相对较新(例如,高级工具链 14 或更高版本),请尝试使用 C 代码启用。在 C++ 库支持完成后,GCC 和 Clang 计划将来在 64 位小端上将默认的长双精度类型切换为 binary128。-mabi=ieeelongdouble
评论
long double
double
double
1.0
double