3

この質問は、理想的には上級ユーザーの意見を求めます。

私はいくつかの数値計算コードを最適化しており、いくつかのプロセッサコアを解放しています。Task.StartNewそれらを効果的に利用するために、非常に短時間の操作(100〜500ミリ秒)のタスク()を使用したきめ細かい並行性を調べています。ここにはUIはまったく含まれていません。

ここで重要な要素の1つは、スレッド作成のオーバーヘッドなしで短期間のタスクのパフォーマンスを向上させるThreadPoolの使用です。ただし、タスクよりもループで考える方が自然なシナリオもあります(Parallel.Forなど)。

タスクがThreadPoolを使用することは理解していますが、Parallel.Forについてはよくわかりません。質問は:

  • どのコンストラクトがThreadPoolを利用しますか?
  • Parallel.ForはThreadPoolを使用するように構成できますか、それとも常にスレッド作成のオーバーヘッドが発生しますか?
  • 主な質問の一部ではありませんが、並列処理を最大化するためのリンクが役立ちます。

この質問は.NET4に固有のものであることに注意してください。現時点では、4.5へのアップグレードはオプションではありません。

更新
ダニエル・キンズマンのコメントに基づいて、次のことを考慮してください。

System.Threading.Tasks.Parallel.For(0, 100, i => { System.Console.WriteLine("Is ThreadPool @ low priority: " + System.Threading.Thread.CurrentThread.IsThreadPoolThread); });
System.Diagnostics.Process.GetCurrentProcess().PriorityBoostEnabled = true;
System.Diagnostics.Process.GetCurrentProcess().PriorityClass = System.Diagnostics.ProcessPriorityClass.RealTime;
System.Threading.Thread.CurrentThread.Priority = System.Threading.ThreadPriority.Highest;
System.Threading.Tasks.Parallel.For(0, 100, i => { System.Console.WriteLine("Is ThreadPool @ high priority: " + System.Threading.Thread.CurrentThread.IsThreadPoolThread); });

マルチコアマシンを使用している場合、IsThreadPoolThreadは、実行しているアプリケーションの数に応じて、非決定論的な結果を返します。

4

1 に答える 1

3

Parallel.Forデフォルトでは、「常に」はスレッドプールを使用してタスクを実行し、スレッド作成のオーバーヘッドは発生しません。

.Net 4.0 CLRの現在のリリースでは、Parallel.For内部でThreadPoolTaskSchedulerクラス(内部クラス)を使用してタスクを実行しています。もちろん、これは内部の詳細が変更される可能性Parallel.Forがありますが、おそらくThreadPoolを使用してタスクを実行し続けます。この「リスク」を取りたくない場合は、いつでも独自のTaskSchedulerを作成して、 ParallelOptionsクラスParallel.Forを使用するように提供できます。

マルチコアマシンを使用している場合、IsThreadPoolThreadは、実行しているアプリケーションの数に応じて、非決定論的な結果を返します。

説明:

ThreadPoolTask​​Schedulerクラスは、最適化されたタスクスケジューラであり、必要がない場合はスレッドでタスクを実行しないようにします。つまり、タスクをすぐに実行できる場合は、スレッドではない可能性のある現在のスレッドThreadPoolで実行します。表示される「false」出力は、この場合のものです。ただし、タスクをすぐに実行できない場合は、常にスレッドプールを使用して、後で実行するためにタスクをキューに入れます。

どちらの場合も、スレッド作成の「オーバーヘッド」がないことに注意してください(ThreadPool自体が、ヒューリスティックでプールに新しいスレッドを含めることを決定する可能性があるため、完全には当てはまりません)。

次のコードを使用して、これを確認できます。

Thread.CurrentThread.Name = "MyThread";
System.Threading.Tasks.Parallel.For(0, 100, i => Console.WriteLine(i + ". Is ThreadPool: " + Thread.CurrentThread.IsThreadPoolThread + " Name: " + Thread.CurrentThread.Name));

すべての「false」の場合、スレッド名は「MyThread」であることに気付くでしょう。

並列処理の最大化に関しては、CPUにバインドされた作業は、使用可能なCPUコアの数の範囲内でのみ並列化できます。TPLはこれを考慮に入れており、CPUバウンドタスクの並列計算に最適で最適化されています。TPLを使用することにより、あなたは正しい道を進んでおり、この道を続ける必要があります:)

于 2012-08-30T07:10:32.717 に答える