スレッド ローカル変数で Parallel.For を使用するように記述されたコードがいくつかあります。これは基本的には大きな配列の合計ですが、配列の要素は合計と同時に for ループで明示的に計算されます。
私が抱えている問題は、スレッドローカル変数が非常に重いオブジェクトであることです。200 MB のメモリを占有することは珍しくありません。プログラムのメモリ使用量が 2 GB に急上昇し、その後 GC がそれを 200 MB に戻し、上下に移動することに気付きました。これは、多くの一時メモリが割り当てられていることを示しています。いくつかのスレッド ローカル変数が必要なので、それらを構造体オブジェクトにラップしました。これにより、Console.WriteLine をコンストラクターに追加できるようになり、多くのオブジェクトが作成されていることがわかりましたが、マシンのコアごとに 1 つの構成しか期待していませんでした。正確に (numberOfCores) スレッドを作成し、それらだけを最後まで保持するにはどうすればよいですか?
追加した
ParallelOptions options = new ParallelOptions();
options.MaxDegreeOfParallelism = 2;
これはほんのわずかしか役に立ちませんでした。まだ構造体の構造が多すぎます。options.TaskScheduler でできることはありそうですが、その威力がどこまでなのかがよくわかりません。自分で巻けそうで、ちょっと怖いくらいです。できればやりたくない。
これが私のプログラムのコードの関連セクションです。
ParallelOptions options = new ParallelOptions();
options.MaxDegreeOfParallelism = 2;
Parallel.For<ThreadLocalData>(0, m, options,
// Thread local variable initialization
() => new ThreadLocalData(new DenseMatrix(r * r, r * r, 0),
new DenseMatrix(r * r, r * r, 0),
new DenseMatrix(r, r, 0)),
// Per-thread routine
(row, loop, threadLocalData) =>
{
threadLocalData.kronProductRight.Clear();
for (int column = 0; column < n; ++column)
{
if ((int)E[row, column] == 1)
threadLocalData.kronProductRight.Add(Yblocks[column], threadLocalData.kronProductRight);
}
MathNetAdditions.KroneckerProduct(Xblocks[row], threadLocalData.kronProductRight, threadLocalData.kronProduct);
threadLocalData.subtotal.Add(threadLocalData.kronProduct, threadLocalData.subtotal);
return threadLocalData;
},
(threadLocalData) =>
{
lock (mutex)
A.Add(threadLocalData.subtotal, A);
}
);