Win32 で CPU サイクル数を取得するにはどうすればよいですか?
-
02-07-2019 - |
質問
Win32 では、複数のプロセス/言語/システムなどで統一される、一意の CPU サイクル カウントまたは同様のものを取得する方法はありますか。
いくつかのログ ファイルを作成していますが、.NET ランタイムをホストしているため、複数のログ ファイルを作成する必要があり、ログを取得するために一方から他方への呼び出しを避けたいと考えています。そのため、私は 2 つのファイルを作成し、それらを結合し、並べ替えて、クロスワールド呼び出しを含む一貫したタイムラインを取得しようと考えていました。
ただし、GetTickCount は呼び出しごとに増加するわけではないため、信頼性がありません。ソート時に正しい順序で電話を受けるために、より良い番号はありますか?
編集:おかげで @グレッグ これで QueryPerformanceCounter の軌道に乗せられ、うまくいきました。
解決
使用できます RDTSC CPU 命令 (x86 を想定)。この命令は CPU サイクル カウンターを提供しますが、カウンターはすぐに最大値まで増加し、その後 0 にリセットされることに注意してください。Wikipedia の記事にもあるように、 QueryPerformanceCounter 関数。
他のヒント
興味深い記事があります! RDTSC を使用せず、代わりに使用するよう指示しています。 QueryPerformanceCounter.
結論:
通常の古いものを使用する
timeGetTime()
システムタイマーの粒度は10〜15ミリ秒ほどである可能性があるため、タイミングを行うことは多くのWindowsベースのオペレーティングシステムで信頼できません。timeGetTime()
10〜15ミリ秒のみです。Windows NT、2000、XPなどのNTベースの動作システムでは、高い粒度が発生することに注意してください。Windows 95と98は、約1〜5ミリ秒、はるかに優れた粒度を持つ傾向があります。ただし、電話すると
timeBeginPeriod(1)
プログラムの開始時(およびtimeEndPeriod(1)
最後に)、timeGetTime()
通常、1〜2ミリ秒まで正確になり、非常に正確なタイミング情報を提供します。
Sleep()
同様に動作します。その時間の長さSleep()
実際に眠りますtimeGetTime()
, 、だから電話した後timeBeginPeriod(1)
一度、Sleep(1)
実際に1〜2ミリ秒間眠ります、Sleep(2)
2-3などの場合(10〜15ミリ秒の高さで睡眠をとる代わりに)。より高い精度のタイミング(サブミリ秒の精度)の場合、キャリブレーションが困難であるため、アセンブリのニーモニックRDTSCの使用を避けたいと思うでしょう;代わりに、使用してください
QueryPerformanceFrequency
そしてQueryPerformanceCounter
, 、10マイクロ秒未満(0.00001秒)未満です。シンプルなタイミングの場合、TimeGetTimeとQueryPerformancecounterの両方がうまく機能し、QueryPerformanceCounterの方が明らかに正確です。ただし、ある種の「タイミングの一時停止」(フレームレート制限に必要なものなど)を実行する必要がある場合は、QueryPerformancecounterを呼び出すループに座って、特定の値に達するのを待っていることに注意する必要があります。これにより、プロセッサの100%が消費されます。代わりに、睡眠を呼び出すハイブリッドスキーム(1)を検討してください(最初にTimeBeginPeriod(1)を忘れないでください!)1ミリ秒以上を超える必要があるときはいつでも、QueryPerformanceCounter 100%-Busyループにのみ入力する必要があります。必要な遅延の1秒の最後の<1/1000を終了します。これにより、非常に最小限のCPU使用量で、超高度の遅延(10マイクロ秒までの正確さ)が得られます。上記のコードを参照してください。
System.Diagnostics.Stopwatch.GetTimestamp() は、時間の起点 (コンピューターの起動時かもしれませんが、確信はありません) 以降の CPU サイクル数を返しますが、2 回の呼び出しの間にそれが増加していないのを見たことがありません。
CPU サイクルは各コンピュータに固有であるため、2 台のコンピュータ間のログ ファイルをマージするためにそれを使用することはできません。
RDTSC 出力は現在のコアのクロック周波数に依存する場合がありますが、最新の CPU ではクロック周波数は一定ではなく、マルチコア マシンでは一貫性もありません。
システム時刻を使用し、複数のシステムからのフィードを処理する場合は NTP 時刻ソースを使用します。そうすることで、信頼性が高く一貫した時刻を読み取ることができます。オーバーヘッドが目的に対して大きすぎる場合は、 HPET 最後に既知の信頼できる時刻を読み取ってからの経過時間を計算するには、HPET を単独で使用するよりも優れています。
GetTickCount を使用して、ログ ファイルをマージするときに別のカウンターを追加します。異なるログ ファイル間で完全な順序が得られるわけではありませんが、少なくとも各ファイルのすべてのログが正しい順序で維持されます。