PLINQ のマージ オプション

クエリが並列として実行される場合、PLINQ はソース シーケンスをパーティション分割し、複数のスレッドが同時に異なる部分 (通常は別個のスレッド) で動作できるようにします。 結果を 1 つのスレッドで、たとえば、foreach (Visual Basic では For Each) ループで使用する場合、すべてのスレッドからの結果を 1 つのシーケンスに再マージする必要があります。 PLINQ で実行されるマージの種類は、クエリに存在する演算子によって異なります。 たとえば、結果に新しい順序を適用する演算子は、すべてのスレッドのすべての要素をバッファリングする必要があります。 消費スレッド (アプリケーション ユーザーのものでもある) 観点から、完全にバッファリングされたクエリは、最初の結果が生成される前に非常に長い期間実行される可能性があります。 既定では、その他の演算子は部分的にバッファリングされ、結果はバッチ単位で生成されます。 既定では、1 つの演算子 ForAll がバッファリングされることはありません。 すべてのスレッドのすべての要素はすぐに生成されます。

以下の例に示すように、WithMergeOptions メソッドを使用することで、PLINQ に、実行するマージの種類を示すヒントを提供できます。

var scanLines = from n in nums.AsParallel()
                    .WithMergeOptions(ParallelMergeOptions.NotBuffered)
                where n % 2 == 0
                select ExpensiveFunc(n);
Dim scanlines = From n In nums.AsParallel().WithMergeOptions(ParallelMergeOptions.NotBuffered)
                Where n Mod 2 = 0
                Select ExpensiveFunc(n)

コード例全体については、「方法:PLINQ のマージ オプションを指定する」を参照してください。

特定のクエリで要求されたオプションをサポートできない場合は、オプションが無視されるだけです。 ほとんどの場合、PLINQ クエリのマージ オプションを指定する必要はありません。 ただし、場合によっては、テストや測定を行うことで、クエリが既定以外のモードで最適に実行されることがわかることもあります。 このオプションは、より応答性の高いユーザー インターフェイスを提供するために、チャンク マージ演算子で結果を強制的にストリーミングする場合に一般的に使用されます。

ParallelMergeOptions

ParallelMergeOptions 列挙には、サポートされるクエリ形状について、結果が 1 つのスレッドで使用されるときにクエリの最終出力がどのように生成されるかを指定する以下のオプションが含まれます。

  • Not Buffered

    NotBuffered オプションを指定すると、処理された各要素は、生成されるとすぐに各スレッドから返されます。 この動作は、出力の "ストリーミング" に似ています。 AsOrdered 演算子がクエリに存在する場合、NotBuffered ではソース要素の順序が保持されます。 NotBuffered は使用可能になるとすぐに結果を生成し始めますが、それでも、すべての結果を生成するための合計時間は、他のマージ オプションのいずれかを使用する場合より長くなることがあります。

  • Auto Buffered

    AutoBuffered オプションを指定すると、クエリで要素がバッファーに収集され、定期的にバッファー コンテンツがすべて一度に消費スレッドに譲渡されます。 これは、NotBuffered の "ストリーミング" 動作を使用する代わりに、"チャンク" 単位でソース データを生成する動作に似ています。 消費スレッドで最初の要素が使用できるようになるまで、NotBuffered よりも AutoBuffered のほうが長くかかる場合があります。 バッファーのサイズと正確な生成動作を構成することはできず、これらはクエリに関するさまざまな要因によって異なる場合があります。

  • FullyBuffered

    FullyBuffered オプションを指定すると、要素が生成される前にクエリ全体の出力がバッファリングされます。 このオプションを使用すると、最初の要素が消費スレッドで使用可能になるまで時間がかかる場合がありますが、それでも他のオプションを使用する場合よりも速く完全な結果が生成される可能性があります。

マージ オプションをサポートするクエリ演算子

次の表に、指定された制約に従って、すべてのマージ オプション モードをサポートする演算子をリストします。

演算子 制約
AsEnumerable None
Cast None
Concat 配列またはリスト ソースのみがある順序付けされていないクエリ。
DefaultIfEmpty None
OfType None
Reverse 配列またはリスト ソースのみがある順序付けされていないクエリ。
Select None
SelectMany None
Skip None
Take None
Where None

他のすべての PLINQ クエリ演算子では、ユーザー指定のマージ オプションが無視される場合があります。 一部のクエリ演算子 (ReverseOrderBy など) では、すべて生成されて並べ替えられるまで要素を譲渡できません。 したがって、Reverse などの演算子も含むクエリで ParallelMergeOptions を使用すると、演算子でその結果が生成されるまでクエリではマージ動作が適用されません。

マージ オプションを処理するいくつかの演算子の機能は、ソース シーケンスの種類と、AsOrdered 演算子がクエリで既に使用されているかどうかによって異なります。 ForAll は常に NotBuffered であり、その要素をすぐに生成します。 OrderBy は常にFullyBuffered であり、生成の前にリスト全体を並べ替える必要があります。

関連項目