9

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

別の編集

代わりに16進数で印刷したときの出力は次のとおりです。

丸めモード: 0

0x1.921fc60b39f1331cp-1

丸めモード: 0

0x1.921fc60b39ff1p-1

また、これは Windows でのみ発生するようです。このコードを Linux VM で実行すると、両方のスレッドで同じ結果が得られます。

ANSWER : 根本的な原因は、浮動小数点の状態が D の Windows の他のスレッドとは異なる方法でメイン スレッドで初期化されることであることが判明しました。私が提出したばかりのバグ レポートを参照してください。

4

1 に答える 1

2

これは、同じ C コードがわずかに異なる結果につながる可能性がある多くの理由を説明する論文です。あなたの場合、最も可能性の高い理由は、CPU 内部の命令の並べ替えです。

浮動小数点計算が下位ビットに至るまで決定論的であると期待するのは、単純に間違っています。それは、浮動小数点数が実現するように設計されたものではありません。

于 2011-04-16T15:14:42.943 に答える