現在、取り組んでいる 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[][]
。