まず、.Netは、どのコアがどのスレッドを実行するかを選択しませんが、OSは選択します。システムで実行されているCPUを集中的に使用するアプリケーションが他にない場合は、各スレッドが別々のコアで実行されることが期待できます。ただし、他のアプリケーションがある場合、OSは、たとえば、すべてのスレッドを単一のコアで実行し、それらを切り替えることを決定する場合があります。
そして、それはそれよりもさらに複雑です。スレッドは通常、単一のコアでは実行されません。OSは常にスレッドをコアからコアに切り替えます。たとえば、タスクマネージャからの次のスクリーンショットを見てください。これは、シングルスレッドのCPUを集中的に使用するアプリケーションの実行を示しています。
シングルスレッドが私の4つのコアすべてで実行され、実行された数秒間で各コアの約25%を使用したことに気付くでしょう。
.Netは、コンピューターのCPU使用率を認識していないため、CPUを集中的に使用する作業を実行するスレッドの最適な数は、コアの数と同じであると想定しています。
PLINQがどのように正確に機能するかはわかりませんが、あなたの例では、各コアが正確に1000/4の素数を生成するとは思いません。1つのスレッドがすでに素数のシェアを生成していて、別のスレッドがまだ実行されていない場合、最初のスレッドをアイドル状態のままにしておくのは効率的ではありません。
もちろん、IO操作では、最適なスレッド数はコア数に依存しないため、並列度を手動で設定する必要があります。(スレッドの最適な数は1である可能性があることを忘れないでください。ハードディスクは、多くのファイル間を行き来するのではなく、シーケンシャル読み取りで最速です。)
設定WithDegreeOfParallelism(7)
すると、間違いなく7つのスレッドが使用されます(ここでも、コアの数は保証されません)。OSは、4つのコアでこれらの7つのスレッドを実行する方法を決定します。これらのスレッドがすべてCPUを集中的に使用する場合、各スレッドにコアの4 /7≈57%のようなものが与えられる可能性があります。それらがIOバウンドである場合、使用可能なコアでウェイクアップした(ブロックされていない)スレッドのコードを実行します。
そして、WithDegreeOfParallelism()
実際には、最大数ではなく、正確なスレッド数を設定します。StephenToubParallelOptions.MaxDegreeOfParallelism
とPLINQWithDegreeOfParallelism
を参照してください。