集中的な計算を行う特定のスレッドの最大CPU負荷を設定するための洗練された方法があるかどうか疑問に思っていました。
現在、スレッド内で最も時間のかかるループ(圧縮のみを実行)を見つけて、ハードコードされた値で使用GetTickCount()
しSleep()
ています。ループが特定の期間継続し、その後特定の最小時間スリープすることを確認します。それは多かれ少なかれ仕事をします、すなわちスレッドがCPUの50%以上を使用しないことを保証します。
ただし、動作はCPUコアの数(大きな欠点)と単純に醜い(小さな欠点:))に依存します。
何か案は?
5 に答える
OSのスケジューラにあなたが望むことをさせるためのAPIを知りません(スレッドがアイドル優先であっても、優先度の高い準備ができているスレッドがない場合でも、あなたのスレッドは実行されます)。ただし、すでに行っていることに基づいて、かなりエレガントなスロットリング関数を即興で作成できると思います。基本的に (Windows 開発マシンが手元にありません):
スレッドが反復ごとにスリープするデフォルトの時間を選択します。次に、反復ごとに (または、スロットリング関数自体が大きな CPU 負荷にならないように、反復ごとに)、
- スロットリング関数が最後に呼び出されてからスレッドが使用した CPU 時間を計算します (これを dCPU と呼びます)。GetThreadTimes() API を使用して、スレッドの実行時間を取得できます。
- スロットリング関数が最後に呼び出されてから経過したリアルタイムの量を計算します (これを dClock と呼びます)。
- dCPU / dClock は、(1 つの CPU の) CPU 使用率です。必要以上に高い場合は睡眠時間を増やし、低い場合は睡眠時間を減らします。
- 計算された時間だけスレッドをスリープさせます。
ウォッチドッグが CPU 使用率を計算する方法によっては、GetProcessAffinityMask()を使用して、システムに搭載されている CPU の数を調べることができます。dCPU / (dClock * CPU) は、使用可能な合計 CPU 時間の割合です。
初期スリープ時間とインクリメント/デクリメント量のいくつかのマジック ナンバーを選択する必要がありますが、このアルゴリズムを調整して、決定された CPU の割合にかなり近い状態でスレッドを実行し続けることができると思います。
Linux では、nice() を使用してスレッドのスケジューリング優先度を変更できます。
問題は、やるべき仕事があるときに CPU をアイドル状態にしたいというのは普通のことではないということです。通常、バックグラウンド タスクを IDLE 優先度に設定し、対話型タスクで使用されていないすべての CPU 時間を OS にスケジューリングさせます。
問題はウォッチドッグプロセスにあるように思えます。
バックグラウンド タスクが CPU バウンドの場合、未使用のすべての CPU 時間をそのタスクに使用する必要があります。
たぶん、ウォッチドッグプログラムの修正を検討する必要がありますか?
あなたが望むクロスプラットフォームの方法(または保証された方法の完全停止)は考えられませんが、GetTickCountを使用しているため、おそらくクロスプラットフォームには興味がありません:)
私はプロセス間通信を使用し、集中的なプロセスを適切なレベルに設定して、必要なものを取得しますが、それが状況に適しているかどうかはわかりません。
編集:私はバーナードに同意します。そのため、スレッドではなくプロセスの方が適切であると思いますが、目的に合わない可能性があります。
スレッドの優先度を変更できる場合もありますが、最大使用率を変更するには、ポーリングとハックを行って発生する回数を制限するか、プロセスの最大使用率を設定できる OS ツールを使用する必要があります。ただし、これを行いたい状況は見当たりません。