1

タイマーを実装していますが、50 ミリ秒ごとに実行する必要があり、分解能を 1 ミリ秒以下にしたいと考えています。私は次の 2 つの記事を読むことから始めました。

http://www.codeproject.com/Articles/1236/Timers-Tutorial

http://www.virtualdub.org/blog/pivot/entry.php?id=272

奇妙なことに、それらは互いに矛盾しているように見えます。キュー タイマーは高解像度に適していると言う人もいれば、Windows 7 システムで約 15 ミリ秒の解像度を示す投稿もあります (私のアプリケーションには十分ではありません)。

そこで、自分のシステム (Win7 64bit i7-4770 CPU @3.4 Ghz) でテストを実行しました。私は50ミリ秒の期間で開始し、これが私が見ているものです(左が開始からの時間、右が実行間のギャップ、すべてミリ秒):

150   50.00
200   50.01
250   50.00
...
450   49.93
500   50.00
550   50.03
...
2250  50.10
2300  50.01

最大エラーは約 100 us であり、平均エラーはおそらく約 30 us 程度であることがわかります。これは私をかなり幸せにします。

そこで、どの時点で信頼性が低くなるかを確認するために、期間を落とし始めました。期間を 5 ミリ秒以下に短縮すると、悪い結果が見られるようになりました。

周期が 5 ミリ秒の場合、数秒ごとに 3 ミリ秒から 6 ミリ秒の間で周期がジャンプすることは珍しくありません。周期を 1 ミリ秒に減らすと、5 ~ 10 ~ 40 ミリ秒の周期が見られます。40ミリ秒までのジャンプは、画面に何かを印刷しているという事実が原因である可能性があると思いますが、わかりません。

これは私のタイマーコールバックコードです:

VOID CALLBACK timer_execute(PVOID p_parameter, 
   BOOLEAN p_timer_or_wait_fired)
{ 
   LARGE_INTEGER l_now_tick;

   QueryPerformanceCounter(&l_now_tick);

   double now = ((l_now_tick.QuadPart - d_start.QuadPart) * 1000000) / d_frequency.QuadPart;
   double us = ((l_now_tick.QuadPart - d_last_tick.QuadPart) * 1000000) / d_frequency.QuadPart;

   //printf("\n%.0f\t%.2f", now / 1000.0f, ms / 1000.0f);

   if (us > 2000 ||
       us < 100)
   {
      printf("\n%.2f", us / 1000.0f);
   }

   d_last_tick = l_now_tick;
}

とにかく、100hz 以下で実行している限り、キュー タイマーは非常に優れたツールのように思えます。私がリンクした 2 番目の記事に掲載された悪い結果 (15 ミリ秒程度の精度) は、CPU が遅いためか、構成が異なるためでしょうか?

複数のマシンでこの種のパフォーマンスを期待できるかどうか疑問に思っています (すべて 64 ビット Win7 を実行しているマシンと同じか、それよりも高速です)。また、期間が経過する前にコールバックが終了しない場合、OS がそこに別のスレッドを配置することに気付きました。これは明らかかもしれませんが、どのドキュメントでも目立たず、クライアント コードに重大な影響を及ぼします。

4

2 に答える 2

2

Windows のデフォルトのタイマー分解能は 15.625 ミリ秒です。それがあなたが観察する粒度です。ただし、システム タイマーの解像度は、MSDN の「タイマーの解像度の取得と設定」で説明されているように変更できます。これにより、ほとんどのプラットフォームで粒度を約 1 ミリ秒に減らすことができます。This SO answer は、現在のシステムタイマーの解像度を取得する方法を開示しています。

隠し機能NtSetTimerResolution(...)により、プラットフォームでサポートされている場合、タイマーの分解能を 0.5 ミリ秒に設定することもできます。「タイマーの分解能を 0.5 ミリ秒に設定するにはどうすればよいですか?」という質問に対するこのSO の回答を参照してください。

...別の設定ですか? 基盤となるハードウェアと OS のバージョンによって異なります。上記のツールを使用してタイマーの解像度を確認します。

...64 ビットの Win7 を実行しているマシンと同じか、それよりも高速ですか? はい、できます。ただし、他のアプリケーションでもタイマー分解能を設定できます。Google Chrome は既知の例です。このような他のアプリケーションも、タイマーの分解能を一時的に変更するだけの場合があります。したがって、タイマーの解像度がプラットフォーム/時間全体で一定であることに決して依存することはできません。タイマーの分解能がアプリケーションによって確実に制御されるようにする唯一の方法は、タイマーの粒度を自分で最小の 1 ミリ秒 (0.5 ミリ秒) に設定することです。

注: システム タイマーの粒度を小さくすると、システムの割り込み頻度が高くなります。スレッドのクォンタム (タイム スライス) が減少し、消費電力が増加します。

于 2014-11-25T07:38:05.873 に答える
0

違いは、システムで使用されるリソース管理によるものだと思います。これについては、オペレーティング システムのクラスで行わなければならなかったプレゼンテーションで知ったばかりです。多くのプロセスが実行されているため、時間が短すぎると、プロセスを十分に速くキューに入れることができない場合があります。一方、時間がある場合、プロセスは時間内にキューに入れられ、優先度も関係します。これが少しでも役に立てば幸いです。

于 2014-11-25T00:31:22.687 に答える