我正在尝试为D编程语言调试我的并行库。一个bug report was recently filed表示使用任务执行的某些浮点运算的低位比特在运行期间是不确定的。 (如果您阅读报告,请注意并行缩减是通过以确定的方式创建任务来实现的。)
这似乎不是舍入模式问题,因为我尝试手动设置舍入模式。我也很确定这不是一个并发错误。该库经过了充分测试(包括通过Jinx压力测试),问题总是局限于低阶位,甚至在单核机器上也会发生,而低级内存模型问题则较少一个问题。浮点结果可能因调度操作的线程而有所不同的原因还有哪些?
编辑:我在这里做一些printf调试,看起来各个任务的结果有时会在运行中有所不同。
编辑#2:以下代码以更简单的方式再现了此问题。它总结了主线程中数组的术语,然后启动一个新线程来执行完全相同的函数。问题肯定不是我的库中的错误,因为这段代码甚至不使用我的库。
import std.algorithm, core.thread, std.stdio, core.stdc.fenv;
real sumRange(const(real)[] range) {
writeln("Rounding mode: ", fegetround); // 0 from both threads.
return reduce!"a + b"(range);
}
void main() {
immutable n = 1_000_000;
immutable delta = 1.0 / n;
auto terms = new real[1_000_000];
foreach(i, ref term; terms) {
immutable x = ( i - 0.5 ) * delta;
term = delta / ( 1.0 + x * x ) * 1;
}
immutable res1 = sumRange(terms);
writefln("%.19f", res1);
real res2;
auto t = new Thread( { res2 = sumRange(terms); } );
t.start();
t.join();
writefln("%.19f", res2);
}
输出:
舍入模式:0
0.7853986633972191094
舍入模式:0
0.7853986633972437348
另一个编辑
这是我用十六进制打印时的输出:
舍入模式:0
0x1.921fc60b39f1331cp-1
舍入模式:0
0x1.921fc60b39ff1p-1
此外,这似乎只发生在Windows上。当我在Linux VM上运行此代码时,我得到两个线程的相同答案。
ANSWER :事实证明,根本原因是主线程上的浮点状态初始化方式与D中Windows上的其他线程不同。请参阅the bug report I just filed.
答案 0 :(得分:2)
这是一个paper that explains,因为相同的C代码导致结果略有不同的原因很多。在您的情况下,最可能的原因是CPU内部指令重新排序。
将浮点计算确定为低阶位是完全错误的。这不是浮点数设计要实现的目标。