2016-10-14 46 views
0

これは私のコードで、タイマとしてQueryPeformanceCounterを使用しています。無限ループでCPU使用率を減らすための正確な方法

//timer.h 
class timer { 
private: 
    ... 
public: 
    ... 
    double get(); //returns elapsed time in seconds 
    void start(); 
}; 

//a.cpp 
void loop() { 
    timer t; 
    double tick; 
    double diff; //surplus seconds 
    t.start(); 
    while(running) { 
     tick = t.get(); 
     if(tick >= 1.0 - diff) { 
      t.start(); 
      //things that should be run exactly every second 
      ... 
     } 
     Sleep(880); 
    } 
} 

Sleepがなければ、このループは無限にt.get()高いCPU使用率の原因となるたびに呼び出すに行くだろう。そのため、約880ミリ秒間スリープ状態にして、必要ではないうちにt.get()を呼び出さないようにします。

私が上記のように、私は現在Sleepを使っていますが、私が心配するのはSleepの精度です。私はどこかで、プログラムが一時停止する実際のミリ秒数が20〜50ミリ秒に変わるかもしれないと読んだ。なぜなら、パラメータを880に設定した理由だ。私はできるだけCPU使用量を減らしたい。可能であれば、990ミリ秒以上を一時停止します。EDIT:そしてさらに1000ミリ秒未満すべてのループの間に。最善の方法は何でしょうか?

+0

行くための最善の方法は、Windowsでの正確なタイミングに頼る終了するだろう -

次に、より良いあなたのニーズに合わせて睡眠のメカニズムのいくつかの選択肢があります。そのことを実際には意識して設計されていませんでした。タイトなループと全くスリープしていなくても、1秒に達するのと同じように、Windowsが別のタスクに切り替えるのを妨げるものは何もありません。 –

+0

[SetTimer APIの使い方]の複写が可能です。(0120-998-301) – user3528438

+0

これは良い戦略ではありません。あなたのコードの実行を停止する*良い理由。あなたはそれを*始めるのに十分な理由を与えたいと思っています。 Sleep()を正確にすることでできることは、timeBeginPeriod()を呼び出します。 SetThreadPriority()を呼び出すことでより良い理由を与えてください。 timeSetEvent()は、待ち時間を調整できるかなり安定したタイマーを得るための良い方法ですが、非同期であることに注意してください。あなたはそれを1ミリ秒より正確にすることは決してありません。そして、あなたは決してそれが*常に* 1ミリ秒と仮定することはできません。カーネルとそのデバイスドライバは常に最初に来ます。 –

答えて

-1

990ミリ秒を超えて一時停止する場合は、991ミリ秒間スリープ状態を書き込みます。あなたのスレッドは、少なくともその時間は眠っていることが保証されています。これはそれほど大きくはありませんが、20-50msの倍数(OSのタイムスライスの解像度とコンテキスト切り替えのコストによります)の倍数になる可能性があります。

しかし、これは「まったく毎秒」実行するものではありません。時間を共有するオペレーティングシステムでこれを達成する方法はありません。メタルに近づくようにプログラムするか、PPSソースからの割り込みに頼らざるを得ず、あなたのOSでループ全体の繰り返しをワンショットで実行できるように祈ってください。または、私は、カーネルモード&hellipで実行する何かを書くと思います;

+0

OSのタイムスライスを解決する方法はありますか? 「スリープ」が解像度に基づいて特定のミリ秒を超えないことが保証されていれば、それは十分です。 – hjjg200

+1

@hʌn:あなたは何タイムスライスを取るか分からない。このようなオペレーティングシステムのユーザー空間では、正確なタイミングに頼ることはできません。 OSはコードをいつ実行するかを選択します。あなたのプロセスに2時間制御を戻さず、関連するすべての標準に準拠することができます!通常は毎秒正確にコードを実行するのではなく、毎秒近くのコード_asを実行して、実際に経過した時間に応じて変数を調整するようにします。ゲームの可変フレームレート –

+0

ドキュメントをお読みください。 「睡眠」は早期に戻ることができます。申し訳ありませんが、誤報のため-1。 – IInspectable

0

私はなぜt.start()を2回呼び出すのですか(クロックはリセットされますか?)、私はSleepの不正確さのための解決策を提案したいと思います。さんはwhile(running)ループの内容を見て、アルゴリズムに従ってみましょう:

double future, remaining, sleep_precision = 0.05; 
while (running) { 
    future = t.get() + 1.0; 

    things_that_should_be_run_exactly_every_second(); 

    // the loop in case of spurious wakeup 
    for (;;) { 
     remaining = future - t.get(); 
     if (remaining < sleep_precision) break; 
     Sleep(remaining); 
    } 

    // next, do the spin-lock for at most sleep_precision 
    while (t.get() < future); 
} 

sleep_precisionの値は経験的に設定する必要があります - 私が知っているのOSはあなたにそれを与えることはできません。 Is there an alternative for sleep() in C?

関連する問題