0

現在、取り組んでいる C# プロジェクトを改善しようとしています。具体的には、私の目標は、いくつかの操作を並列化して処理時間を短縮することです。コツをつかむために、小さなスニペットから始めています。次のコード (並列ではない) は正しく動作します (期待どおり)

for (int i = 0; i < M; i++)
{
     double d;
     try
     {
          d = Double.Parse(lData[i]);
     }
     catch (Exception)
     {
         throw new Exception("Wrong formatting on data number " + (i + 1) + " on line " + (lCount + 1));
     }
     sg[lCount % N][i] = d;
}

次の (並列) コードを使用すると、まったく同じ結果が得られると期待できますが、そうではありません。

Parallel.For(0, M, i =>
{
    double d;
    try
    {
        d = Double.Parse(lData[i]);
    }
    catch (Exception)
    {
        throw new Exception("Wrong formatting on data number " + (i + 1) + " on line " + (lCount + 1));
    }
    sg[lCount % N][i] = d;
});

これらのスニペットの元となっているプログラムの部分は、一度に 1 行ずつファイルからデータを読み取ります。各行は、String.Split() を使用してベクター lData[] に挿入した、コンマで区切られた倍精度数値のシーケンスです。M 行ごとに、データ シーケンスは新しいデータ フレームで最初からやり直されます (したがって% M、値を割り当てるときに要素インデックスに含まれます)。

私の理解では (明らかに間違っています)、(シリアル) for ループからのコードを の 3 番目のパラメーターに入れることで、Parallel.Forその実行が並列化されます。これで結果が変わるはずはありません。スレッドがすべて lCount と M にアクセスしているという事実に問題がありますか? スレッド ローカル コピーを作成する必要がありますか?

ありがとう。

(私は初心者なので、Parallel.Forタグを作成することは許可されていません)

編集:さらにいくつかのテストを実行しました。基本的に、以前に行ったよりもコードの早い段階で出力を見ました。sg[][]私のコードの並列バージョンは、配列全体を埋めていないようです。むしろ、一部の値はデフォルト (私の場合は 0) のままです。

編集 2 (コメントの一部に答える): を使用しlData[]string[]取得されstring.Split()ます。分割している元の文字列は、データ ファイルから読み取られます。私はそれらを生成するコードを書いたので、それらは一般的に適切にフォーマットされています (私はまだtry-catch習慣から構造体を使用しています)。lData[]for ループ (wither 並列または直列) の直前に、正しい数の値 (M) があることを確認します。そうでない場合は、プログラムが問題の for ループに到達できないようにする例外をスローします。 sg[][]N x M 型の配列ですdouble(スニペットにタイプミスがありましたが、現在は修正されています。元のコードでは、このエラーは存在しませんでした)。ファイルから N 行を読み取った後、配列sg[][]データセット全体が含まれています。for ループ (並列または直列) の後には、次のような come の部分があります。//既に読んだ行を数えます if((lCount % N) == 0) { //sg[][] で処理 //sg[][] をリセット } sg[][]. for ループの全体的な目的は、 の値を更新することですsg[][]

4

2 に答える 2

2

私が見る限り、コードに本質的に間違っているものはありません。おそらく変数で、スニペットを含む関数に競合状態または閉鎖の問題があると思いますN

このスニペットを別の Parallel.For() 呼び出し内にネストした場合N、ラムダ式で閉じられているという事実が失われ、更新されている可能性があります。したがって、「N」の更新をオフにしている間、ラムダ内で一定のままであることが期待されます。それを解決するには、これを試してください:

// Create a local copy of N and M, so that if we update 
// it elsewhere it doesn't affect the closure
var n = N;
var m = M;
Parallel.For(0, m, i =>
{
    double d;
    try
    {
        d = Double.Parse(lData[i]);
    }
    catch (Exception)
    {
        throw new Exception("Wrong formatting on data number " + (i + 1) + " on line " + (lCount + 1));
    }
    sg[lCount % n][i] = d;
});
于 2013-08-11T02:33:06.467 に答える