6

我正在开发一个需要浮点确定性的 C 应用程序。我还希望浮点运算相当快。这包括 IEEE754 未指定的标准超越函数,如正弦和对数。与硬件浮点相比,我考虑过的软件浮点实现相对较慢,因此我正在考虑简单地从每个答案中舍入一两个最低有效位。精度损失对我的应用程序来说是一个足够的妥协,但这是否足以确保跨平台的确定性结果?所有浮点值都是双精度值。

我意识到运算顺序是浮点结果差异的另一个潜在来源。我已经有办法解决这个问题了。

如果今天使用的主要浮点硬件实现有软件实现,那就太好了,所以我可以直接测试这样的假设。

4

1 回答 1

3

据我了解,您有一个超越函数(如 sin(x))的软件实现,以 IEEE 标准操作(如浮点加法和乘法)表示,并且您希望确保在所有机器上得到相同的答案(或者,至少,你关心的所有机器)。

首先,了解:这不会适用于所有机器。例如IBM大型机十六进制浮点不是IEEE,并且不会给出相同的答案。为了得到准确的结果,您需要有一个 IEEEE 标准操作(如 FP 加法和乘法)的软件实现。

我猜你只关心实现 IEEE 标准浮点的机器。而且我还猜想你并不担心 NaN,因为 NaN 并未完全由 IEEE 754-1985 标准化,并且出现了两种相反的实现:HP 和 MIPS,几乎所有其他人都支持。1

有了这些限制,您如何才能在计算中获得可变性?

(1) 如果代码正在被并行化。确保没有发生这种情况。(这不太可能,但有些机器可能。)并行化是 FP 中结果变化的主要来源。至少我认识的一家公司,关心可复制性和并行性,拒绝使用 FP,只使用整数。

(2) 确保机器设置正确。

例如,大多数机器以 32 或 64 位精度计算(C 原始标准到处都是 64 位“双精度”。但 Intel x86/x87 可以在寄存器中以 80 位计算,并且在溢出时舍入到 64 或 32。1显示了如何更改x86/x87 精度控制从 80 位到 64 位,使用内联汇编。请注意,此代码是汇编级别的,不可移植 - 但大多数其他机器已经以 32 或 64 位精度进行计算,您无需担心x87 80 位。

(顺便说一句,在 x86 上,您只能通过使用 SSE FP 来避免所有问题;旧的传统 Intel x87 FP 永远无法给出完全相同的答案(尽管如果您将精度控制 (PC) 设置为 64 位而不是 80 位,你会得到相同的结果,除非有中间溢出,因为指数宽度不受影响,只是尾数))

例如,确保您在所有机器上使用相同的下溢模式。即确保 denorms 或启用,或者相反,所有机器都处于刷新到零模式。这是 Dobson 的选择:清零模式不是标准化的,但是一些机器,例如 GPU,根本就没有非规范化的数字。即许多机器有 IEEE 标准编号 FORMATS,但没有实际的 IEEE 标准算术(带 denorms)。我的想法是要求 IEEE denorms,但如果我绝对偏执,我会使用 flush 到零,并在软件中强制自己刷新。

(3) 确保您使用相同的语言选项。较旧的 C 程序以“双精度”(64 位)进行所有计算,但现在允许以单精度计算。无论如何,您希望在所有机器上都以相同的方式进行操作。

(4)一些较小的项目写你的代码:

避免编译器可能重新排列的大表达式(如果它没有正确实现严格的 FP 切换)

可能以简单的形式编写所有代码,例如

double a = ...;
double b = ...;
double c = a *b;
double d = ...;
double e = a*d;
double f = c + e;

而不是

f = (a*b) + (a*c);

这可能会优化为

f = a*(b+c);

我将在最后讨论编译器选项,因为它更长。

如果你做了所有这些事情,那么你的计算应该是绝对可重复的。IEEE 浮点数是精确的——它总是给出相同的答案。正是编译器在通向 IEEE FP 的过程中重新安排了计算,从而引入了可变性。

您应该不需要四舍五入低位。但这样做也不会受到伤害,并且可能会掩盖一些问题。请记住:您可能需要为每个添加屏蔽至少一个位......

(2) 编译器优化在不同机器上以不同方式重新排列代码。正如一位评论者所说,使用您的编译器开关来实现严格的 FP。

您可能必须禁用包含您的 sin 代码的文件的所有优化。

您可能必须使用挥发物。

希望有更具体的编译器开关。例如对于 gcc:

-ffp-contract=off --- 禁用融合乘法加法,因为并非所有目标机器都可能拥有它们。

-fexcess precision=standard --- 在内部寄存器中禁用 Intel x86/x87 超精度

-std=c99 --- 指定相当严格的 C 语言标准。不幸的是没有完全实现,因为我今天谷歌它

确保您没有启用优化,例如 -funsafe-math 和 -fassociativbe-math

于 2012-02-25T04:16:07.487 回答