1

PLINQ クエリのスレッド "インデックス" を Select などの演算子の 1 つに渡す方法はありますか?

バックグラウンドは、逆シリアル化を行う PLINQ クエリがあることです。逆シリアル化メソッドは、構造体 (おそらく配列) を使用してデータを別のメソッドに渡します。

      ParallelEnumerable.Range(0, nrObjects)
        .WithDegreeOfParallelism(8)
        .Select(i => this.Deserialize(serializer, i, arrays[threadIndex]))
        .ToList();

(threadIndex は私が望む新しい変数です)

スレッド インデックスがわかっている場合は、事前にこれらの配列を 8 つ作成し (すべてが使用されない場合でも)、それらを再利用できます。Deserialization メソッドは何百万回も呼び出される可能性があるため、あらゆる小さな最適化が重要になります。

4

3 に答える 3

1

スレッドインデックスを再作成します。並列度は(IIRC)使用するスレッドの最大数のみであることに注意してください。その番号を使用する必要はありませんあなたが説明する方法に依存することは、あなたが実際にアクセスするだけthreadIndexかもしれないことを意味するように思われるでしょう。要するに、いいえ:私はそうは思いません。arrays[0]

ただし、アイテムインデックスを取得することはできます。つまり、それがあなたの言いたいことなら、単純に:

.Select((value, itemIndex) => this.Deserialize(
     serializer, i, arrays[itemIndex])).ToList();

意図は作業バッファーを取得することであるように聞こえます(コメント)。その場合、私は(同期アクセスなどを使用して)いくつかの便利なバッファーをコンテナーに保持します(実際にそうします)。

  • コンテナから既存のバッファを取得しようとします(同期済み)
  • 見つからない場合は、新しいバッファを作成します
  • (仕事する)
  • コンテナへのバッファの返却/追加(同期)

これは一般的に非常に高速です(反復ごとのバッファ割り当てよりもはるかに高速です)

于 2010-11-02T12:27:38.920 に答える
0

一度にループの 1 つの並列インスタンスに渡されるローカルを割り当てる (およびクリーンアップする) ことができるオーバーロードを提供する Parallel.ForEach を使用することをお勧めします。私はこのアプローチを、プロセスのさまざまなステップでバッファーが必要な大量の画像データの処理に使用しました。

于 2010-11-07T16:07:39.490 に答える
0

整数を作成しConcurrentBag、逆シリアル化の前にそれを取得してインデックスとして使用し、後で返すことができます。すべてのスレッドは、一度に 1 つの配列要素を占有します。

Parallel クラスの使用を検討してください。配列に関しては、より適切です。Select使用する場合のインデックス付きバージョンには制限がありますParallelEnumerable(あなたの場合ではありませんが、注意してください)

于 2010-11-02T12:38:27.973 に答える