我最近将我的操作系统从 Debian 9 升级到 Debian 11。我有一堆服务器运行模拟,一个子集产生特定结果,另一个子集产生不同结果。这在 Debian 9 中不会发生。我制作了一个最小的失败示例:
#include <stdio.h>
#include <math.h>
int main()
{
double lp = 11.525775909423828;
double ap = exp(lp);
printf("%.14f %.14f\n", lp, ap);
return 0;
}
lp 值在每台机器上打印相同的答案,但我对 ap 有两个不同的答案:101293.33662281210127 和 101293.33662281208672
代码是用“gcc fptest.c -lm -O0”编译的。刚刚添加了“-O0”以确保优化不是问题。如果没有此选项,它的行为相同。
Debian 11 版本中链接的库是 libm-2.31.so 和 libc-2.31.so。
在(工作的)Debian 9 版本中链接的库是 libm-2.24.so 和 libc-2.24.so。
这些服务器都使用不同的 CPU 运行,因此很难说太多。但是例如,我在至强 E5-2695 v2 和至强 E5-2695 v3 之间得到了不同的结果。
在我拥有的所有处理器中,我在 Debian 11 上只看到这两个结果之一,而在 Debian 9 上运行时,我始终只得到一个结果。
对我来说,这感觉就像 libm-2.31 和/或 libc-2.31 中的错误。我对这种事情的经验为零。有人可以解释一下我所看到的是否是预期的吗?它看起来像一个错误吗?我能做些什么吗?等等
还尝试用clang编译,并得到完全相同的问题。
另请注意,在 Debian 9 上编译的二进制文件在 Debian 11 上运行,并产生与 Debian 11 二进制文件相同的结果/问题,这进一步加重了我对库相关的怀疑(我无法在 Debian 9 上运行 Debian 11 二进制文件)。
更新
只需阅读这篇很有帮助的帖子。所以我很高兴不同的架构可能会为 exp() 函数提供不同的结果。但是我所有的处理器都是 x86_64 和某种 intel xeon-xxxx。我不明白为什么具有完全相同库的完全相同的二进制文件在不同的处理器上给出不同的结果。
正如那篇文章中所建议的,我使用 %a 打印了这些值。这两个答案仅在 LSB 上有所不同。如果我使用 expl() 我在所有机器上都会得到相同的答案。
解释为什么我会看到差异,如果这是预期的,那就太好了。任何确保一致性的编译器标志也很好。