[ad_1]
非常に大きなファイル セットを処理しています。 これを行うために、作業を +/- 500k のタスクに分割し、これらのタスクを反復して収集するための小さなコードを書きました。
var threads = 16; for (int i = 0; i < task_amt; i++) { taskList.Add(new Task<double>(() => { // heavy computation code return result; })); } for (int j = 0; j < taskList.Count - threads; j += threads) { for (int k = 0; k < threads; k++) { Console.WriteLine($"Starting task {j + k}."); taskList[j + k].Start(); } for (int k = 0; k < threads; k++) { Console.WriteLine($"Waiting for task {j + k}."); taskList[j + k].Wait(); var taskResult = taskList[j + k].Result; } }
これは夢のように機能し、すべての論理コアを使用します。それらは 100% であり、これは CPU が重いため、他のリソースはごくわずかです。
しかし、約 15 分後に速度が低下しているように見え、30 分後には CPU の使用率が 50% しかなく、1.5 時間後には 30% しか使用されません (他のすべてのリソースは依然として無視できるほど低い状態です)。 これは合計計算時間に深刻な悪影響を及ぼします。なぜこれが起こるのか誰か教えてもらえますか?
私が試したこと:
考えられる唯一の理由はサーマル スロットリングです。CPU がサーマル スロットルを使用して冷却しているかどうかを調べてみましたが、残念ながら、使用したハードウェア監視アプリケーションでは CPU 温度が表示されませんでした。
解決策 1
「コールド」タスクを作成し、スレッドを自分で管理することは、悪い考えのように思えます。 「ホットな」タスクを作成して、スレッド プールにスケジュールを任せてみませんか? または使用 Parallel.For
また Parallel.ForEach
その代わり?
現在のコードでは、すべてのタスクの完了にまったく同じ時間がかからない限り、コアを「浪費」することになります。 考慮事項: 実行するタスクが 10 個あります。 5 つのタスクを開始します。 そのうちの 4 つは 1 分で完了します。 5 回目は 3 分かかります。 2 分間、実行中のタスクは 1 つだけです。 他の 5 つの保留中のタスクは開始されていません。
[ad_2]
コメント