私には a があり、それぞれを FooList<byte[]>
に逆シリアル化するのが好きです。List は順序付けられており、元の Foo と同じ順序で結果にすべての Foo が含まbyte[]
れる並列ループを作成するのが好きです。リストは、並列操作を価値のあるものにするために非常に大きくなっています。これを達成する組み込みの方法はありますか?List<Foo>
byte[]
そうでない場合、これをすべて同期的に実行するよりもスピードアップを達成する方法はありますか?
ありがとう
私には a があり、それぞれを FooList<byte[]>
に逆シリアル化するのが好きです。List は順序付けられており、元の Foo と同じ順序で結果にすべての Foo が含まbyte[]
れる並列ループを作成するのが好きです。リストは、並列操作を価値のあるものにするために非常に大きくなっています。これを達成する組み込みの方法はありますか?List<Foo>
byte[]
そうでない場合、これをすべて同期的に実行するよりもスピードアップを達成する方法はありますか?
ありがとう
あなたが与えた情報から、バイトの入力配列と同じサイズの Foo の出力配列が必要だと理解していますか? これは正しいです?
もしそうなら、はい、操作は簡単です。ロックまたは同期された構造を気にしないでください。これらは、並列化によって得られるすべての速度を損ないます。
代わりに、この単純なルールに従えば、ロックや同期なしでアルゴリズムを並列化できます。
処理された入力要素 X[i] ごとに、任意の入力要素 X[j] から読み取ることができますが、出力要素 Y[i] にのみ書き込むことができます。
Scatter/Gather を参照してください。このタイプの操作は、出力要素が 1 つだけ書き込まれるため、Gather と呼ばれます。
上記の原則を使用できる場合は、出力配列 Foo[] を前もって作成し、入力配列で ForEach ではなく Parallel.For を使用します。
例えば
List<byte[]> inputArray = new List<byte[]>();
int[] outputArray = new int[inputArray.Count];
var waitHandle = new ManualResetEvent(false);
int counter = 0;
Parallel.For(0, inputArray.Count, index =>
{
// Pass index to for loop, do long running operation
// on input items
// writing to only a single output item
outputArray[index] = DoOperation(inputArray[index]);
if(Interlocked.Increment(ref counter) == inputArray.Count -1)
{
waitHandle.Set();
}
});
waitHandler.WaitOne();
// Optional conversion back to list if you wanted this
var outputList = outputArray.ToList();
インデックス int キーを持つスレッドセーフ ディクショナリを使用して foo からの結果を格納できるため、最後にすべてのデータ オーダラーがディクショナリに含まれます。