PPC64长双机ε计

PPC64 long double's machine epsilon calculation

提问人:anymous.asker 提问时间:8/28/2021 最后编辑:phuclvanymous.asker 更新时间:2/2/2022 访问量:248

问:

我正在玩一个在 qemu 中模拟的 PPC64 虚拟机,试图模仿 POWER8 CPU。

在这里,该类型与 x86 中用于长双精度的 80 位浮点不同,并且从我所看到的情况来看,它也不符合 IEEE754 的 float128,因为它根据 C 宏有一个 106 位的尾数(而 112 位尾数由 IEEE754 为其 float128 指定)。long doubleLDBL_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_EPSILONstd::numeric_limits<long double>::epsilon()

这将使它比预期的精度高出大约10倍,从逻辑上讲,这应该是不可能的。鉴于螳螂正好是 2x53(IEEE754 的 float64),我认为它可能使用了双双结构,维基百科还说,在小数字方面的精度应该低于IEEE754 float128。

这是怎么回事?

浮点 IEEE-754 PowerPC epsilon 双双双算术

评论

4赞 njuffa 8/28/2021
我记得,幂的计算是基于双精度(有时也称为成对算术)的。操作数由有效性较高的头部和不太重要的尾部部分组成,两者都是数字。有一个归一化标准,即 |tail|< ulp(|head|)/2.然而,尾巴的大小可能比这小得多。特别是头部可以是,尾部可以小到最小的亚正常值,这就是你在这里遇到的。long doubledoubledouble1.0double
0赞 njuffa 8/28/2021
请注意,在成对算术中,精度方面,您将获得两倍的有效位数外加一个额外的位。这额外的一点从何而来?尾巴的标志位。
1赞 phuclv 8/28/2021
这是双倍算术。另请参阅标签 double-double-arithmetic

答:

3赞 Qiu Chaofan 12/22/2021 #1

首先,让我假设您的操作系统是 Linux。到目前为止,64 位 PowerPC 上的所有编译器都默认使用“double-double”类型,其格式不符合 IEEE。long double

格式实际上是两个 s 的组合,因此将其理解为 .高部与普通部分没有什么不同,而低部则提供延长的尾数。整数的指数与 相同,这意味着它的最大可表示数不比 的大几个数量级(因为 double-double 的尾数更长,所以它们仍然不同)。doublestruct { double high; double low; }doubledoubledouble

目前,双双浮点数的运算没有原生的 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+bxsaddqp__addkf3

如果您的工具链相对较新(例如,高级工具链 14 或更高版本),请尝试使用 C 代码启用。在 C++ 库支持完成后,GCC 和 Clang 计划将来在 64 位小端上将默认的长双精度类型切换为 binary128。-mabi=ieeelongdouble