マルチスレッドの合計は誤った結果をもたらします

アレックスジューコフスキー

私は小さなライブラリを書いていて、配列を合計できるようにしたいと思っています。シングルスレッドバージョンは正常に機能しますが、マルチスレッドを追加すると、すべてが機能しなくなります。

私はパーティショナーを使用してブロック上のデータを分割し、すべての部分を1つの結果に合計しています。それから私はそれを返します。ただし、データは無効です。プログラムを再起動するたびに同じ結果が生じるため、競合状態は発生していないようです。

[Pure]
public static double Sum(this double[] source)
{
    source.IsNotNull("source");
    if (source.Length < Constants.SingleThreadExecutionThreshold)
        return Sum(source, 0, source.Length);
    double result = 0;
    object syncRoot = new object();     
    Parallel.ForEach(Partitioner.Create(0, source.Length),
        () => (double)0,
        (range, state, sum) => Sum(source, range.Item1, range.Item2),
        x =>
        {
            lock (syncRoot)
                result += x;
        });

    return result;
}

Sum(source, from, to)常に正しい結果を出します。実装は次のとおりです。

[Pure]
private static double Sum(this double[] source, int startIndex, int endIndex)
{
    double sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0;
    checked
    {
        int i;
        for (i = startIndex; i < endIndex - Constants.Step + 1; i += Constants.Step)
        {
            sum1 += source[i];
            sum2 += source[i + 1];
            sum3 += source[i + 2];
            sum4 += source[i + 3];
        }
        if (i == source.Length)
            return ((sum1 + sum2) + (sum3 + sum4));
        if (i == source.Length - 1)
            return ((sum1 + sum2) + (sum3 + sum4) + source[i]);
        if (i == source.Length - 2)
            return ((sum1 + sum2) + (sum3 + sum4) + (source[i] + source[i + 1]));
        return ((sum1 + sum2) + (sum3 + sum4) + (source[i] + source[i + 1] + source[i + 2]));
    }
}

internal static class Constants
{
    public const int Step = 4;
    public const int SingleThreadExecutionThreshold = 1024;
}

どうすれば修正できますか?


コード例:http//ideone.com/8sD0JL

アロン

さて、私はそれを修正したと思います。2つの大きなバグを見つけました。

  1. array.Lengthのもの
  2. あなたは「最終的に」代理人を悪用していました。そのコードが実行されるという保証はありません

これらの変更により、-0.000576496124267578の差が得られます。これは、二重和の丸め誤差の予想内です。

    [Pure]
public static double Sum(this double[] source, int startIndex, int endIndex)
{
    double sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0;
    checked
    {
        int i;
        int j = 0;
        for (i = startIndex; i < endIndex - Constants.Step + 1; i += Constants.Step)
        {
            sum1 += source[i];
            sum2 += source[i + 1];
            sum3 += source[i + 2];
            sum4 += source[i + 3];
            j += Constants.Step;
        }
        var segmentLength = endIndex - startIndex;

        if (j == segmentLength)
            return ((sum1 + sum2) + (sum3 + sum4));
        if (j == segmentLength - 1)
            return ((sum1 + sum2) + (sum3 + sum4) + source[i]);
        if (j == segmentLength - 2)
            return ((sum1 + sum2) + (sum3 + sum4) + (source[i] + source[i + 1]));
        return ((sum1 + sum2) + (sum3 + sum4) + (source[i] + source[i + 1] + source[i + 2]));
    }
}

internal static class Constants
{
    public const int Step = 4;
    public const int SingleThreadExecutionThreshold = 1024;
}

[Pure]
public static double Sum(this double[] source)
{
    if (source.Length < Constants.SingleThreadExecutionThreshold)
        return Sum(source, 0, source.Length);
    double result = 0;
    object syncRoot = new object();     
    Parallel.ForEach(Partitioner.Create(0, source.Length),
        (range) => {

            var x = Sum(source, range.Item1, range.Item2);
            lock (syncRoot)
                result += x;
        });
    return result;
}

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

join()を使用するJavaマルチスレッドプログラムは、隣接する数値の合計を計算するときに誤った結果を返します

分類Dev

uniq --countコマンドは誤った結果をもたらしますか?

分類Dev

uniq --countコマンドは誤った結果をもたらしますか?

分類Dev

GAMパッケージのテンソル積ti()は、誤った結果をもたらします

分類Dev

AVERAGETOTALYTDは誤った結果をもたらします。Power BIDAX

分類Dev

「a」から「b」の範囲の整数の合計は、大きな入力に対して誤った結果をもたらします

分類Dev

タイムスタンプは誤った結果をもたらします

分類Dev

区分的関数の積分は誤った結果をもたらします

分類Dev

Javascript正規表現の否定は誤った結果をもたらします

分類Dev

Pythonマトリックスは、最後のレコードと同じ結果をもたらします

分類Dev

Ruby-ステートメント内の誤った改行はまだ結果をもたらしますか?

分類Dev

T-SQLで誤った結果をもたらす集計

分類Dev

テキストフィールドを比較し、マッチングに応じて数値(値)の結果をもたらす必要があります

分類Dev

numpy配列のscipy.ndimage.interpolationシフトは誤った結果をもたらします-バグ?

分類Dev

ポリゴンのブーストポイントが誤った結果をもたらしますか?

分類Dev

自己結合は誤った/反対の結果を返しますか?

分類Dev

SIFTマッチングは非常に悪い結果をもたらします

分類Dev

Pythonのマルチプロセッシングは、与えられたタスクよりも多くの結果を返します

分類Dev

GoogleはAPIの誤った計算をマップします

分類Dev

/ optimizeを使用したRyuJITC#の誤った合計結果

分類Dev

SQL結合テーブルは間違った結果をもたらします

分類Dev

結合法則が破られたモナドは、理解のために誤った結果をもたらす可能性がありますか?

分類Dev

IOCPスレッドからWSAGetLastError()を呼び出すと、誤った結果が返されます

分類Dev

マングース検索は誤った結果を返します

分類Dev

Pythonマルチプロセッシングを使用したSLURMは、一貫性のない結果をもたらします

分類Dev

ブール関数は誤った結果を出します

分類Dev

GROUP BYMONTHは間違った結果をもたらします

分類Dev

Timedelta操作は間違った結果をもたらします

分類Dev

同じスレッドから継続的な結果が得られた場合、 `synchronized`は何をしますか?

Related 関連記事

  1. 1

    join()を使用するJavaマルチスレッドプログラムは、隣接する数値の合計を計算するときに誤った結果を返します

  2. 2

    uniq --countコマンドは誤った結果をもたらしますか?

  3. 3

    uniq --countコマンドは誤った結果をもたらしますか?

  4. 4

    GAMパッケージのテンソル積ti()は、誤った結果をもたらします

  5. 5

    AVERAGETOTALYTDは誤った結果をもたらします。Power BIDAX

  6. 6

    「a」から「b」の範囲の整数の合計は、大きな入力に対して誤った結果をもたらします

  7. 7

    タイムスタンプは誤った結果をもたらします

  8. 8

    区分的関数の積分は誤った結果をもたらします

  9. 9

    Javascript正規表現の否定は誤った結果をもたらします

  10. 10

    Pythonマトリックスは、最後のレコードと同じ結果をもたらします

  11. 11

    Ruby-ステートメント内の誤った改行はまだ結果をもたらしますか?

  12. 12

    T-SQLで誤った結果をもたらす集計

  13. 13

    テキストフィールドを比較し、マッチングに応じて数値(値)の結果をもたらす必要があります

  14. 14

    numpy配列のscipy.ndimage.interpolationシフトは誤った結果をもたらします-バグ?

  15. 15

    ポリゴンのブーストポイントが誤った結果をもたらしますか?

  16. 16

    自己結合は誤った/反対の結果を返しますか?

  17. 17

    SIFTマッチングは非常に悪い結果をもたらします

  18. 18

    Pythonのマルチプロセッシングは、与えられたタスクよりも多くの結果を返します

  19. 19

    GoogleはAPIの誤った計算をマップします

  20. 20

    / optimizeを使用したRyuJITC#の誤った合計結果

  21. 21

    SQL結合テーブルは間違った結果をもたらします

  22. 22

    結合法則が破られたモナドは、理解のために誤った結果をもたらす可能性がありますか?

  23. 23

    IOCPスレッドからWSAGetLastError()を呼び出すと、誤った結果が返されます

  24. 24

    マングース検索は誤った結果を返します

  25. 25

    Pythonマルチプロセッシングを使用したSLURMは、一貫性のない結果をもたらします

  26. 26

    ブール関数は誤った結果を出します

  27. 27

    GROUP BYMONTHは間違った結果をもたらします

  28. 28

    Timedelta操作は間違った結果をもたらします

  29. 29

    同じスレッドから継続的な結果が得られた場合、 `synchronized`は何をしますか?

ホットタグ

アーカイブ