次のようなループがあります。
while (elapsedTime < refreshRate)
{
timer.stopTimer();
elapsedTime=timer.getElapsedTime();
}
私は他の場所でこれに似たものを読んだ(C 100%CPUなしのメインループ)が、このループは正確でなければならない高解像度タイマーを実行しています。では、高解像度を維持しながら100%CPUを使用しないようにするにはどうすればよいでしょうか。
次のようなループがあります。
while (elapsedTime < refreshRate)
{
timer.stopTimer();
elapsedTime=timer.getElapsedTime();
}
私は他の場所でこれに似たものを読んだ(C 100%CPUなしのメインループ)が、このループは正確でなければならない高解像度タイマーを実行しています。では、高解像度を維持しながら100%CPUを使用しないようにするにはどうすればよいでしょうか。
忙しくするべきではありません-待つのではなく、時間が経過したときにOSに通知してもらいます。
http://msdn.microsoft.com/en-us/library/ms712704(VS.85).aspx
高解像度タイマー(10ミリ秒以上)
タイマーは「正確」でなければならないと言うとき、実際にどれくらい正確である必要がありますか?最も近いミリ秒まで正確である必要がある場合は、ループ内に0.5ミリ秒のスリープを追加できます。残りの睡眠時間に基づいて動的に変化する睡眠ステートメントを追加することもできます。(擬似コード)のようなものを考えてください:
int time_left = refreshRate - elapsedTime;
while (time_left > 0) {
if (time_left > threshhold)
sleep_for_interval(time_left / 2);
update_timestamp(elapsedTime);
time_left = refreshRate - elapsedTime;
}
このアルゴリズムでは、待機時間がまだあることを検出すると、コードは短いバーストでスリープします。いくつかのテストを実行してthreshhold
、オーバーシュートのリスクとCPU使用率の節約のバランスをとる最適な値を見つける必要があります(アプリがスリープ時にCPUを失い、CPU時間が間に合わなくなることが原因です)。
高分解能タイミングのもう1つの方法は、定期的な割り込みをトリガーするハードウェアタイマーを使用することです。割り込みハンドラーは、ウェイクアップして何かを実行する必要があるというシグナルをスレッドに送信します。その後、スリープに戻り、次のシグナルが着信するのを待ちます。
リアルタイムオペレーティングシステムには、OSに組み込まれているこの種のことを行う方法があります。Windowsプログラミングを行っていて、非常に正確なタイミングが必要な場合は、Windowsのような汎用OSがうまく処理できるようなものではないことに注意してください。
POSIXのように、OSによって提供されるいくつかのタイマーを見てくださいusleep
。
一方、超高精度が必要な場合は、コードも機能しません。これは、OSが処理時間の量を使い果たし、カーネルスペースにジャンプしてシステムタスクを実行した後、OSがこのループを中断するためです。このためには、割り込み可能なカーネルとそれによって提供されるツールを備えた特別なOSが必要になります。RTOSキーワードを探します。
通常、何らかの方法でOSに譲ります。これにより、OSはプログラムを中断して、他のことを行うことができます。
明らかにこれはOSに依存しますが、次のようになります。
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
void yield(void)
{
#ifdef _WIN32
Sleep(0);
#else
usleep(1);
#endif
}
タイマーを停止する前に、yieldの呼び出しを挿入します。OSは、プログラムによるより少ない時間の使用を報告します。
もちろん、これによりタイマーが「精度が低く」なることに注意してください。これは、タイマーができるだけ頻繁に更新されない可能性があるためです。しかし、あなたは本当に極端な精度に頼るべきではありません、それはあまりにも難しいです。概算は大丈夫です。