如何解决并行性:浮点结果有细微不同?
| 我正在尝试调试D编程语言的并行库。最近提交了一个错误报告,该错误报告指示使用任务执行的某些浮点运算的低阶位在运行期间不确定。 (如果您阅读了该报告,请注意,通过以确定性的方式创建任务,并行减少了工作量。) 这似乎不是舍入模式的问题,因为我尝试手动设置舍入模式。我也很确定这不是并发性错误。该库经过了充分的测试(包括通过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上运行此代码时,两个线程的答案相同。
答案:根本原因是D中Windows的主线程与其他线程的浮点状态初始化方式不同。请参阅我刚刚提交的错误报告。
解决方法
这是一篇论文,解释了同一C代码导致不同结果的多种原因。在您的情况下,最可能的原因是CPU内部指令的重新排序。
期望浮点计算具有确定性直到低位都是错误的。这不是浮点数设计要实现的。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。