2

MSDN の記事Game Timing and Multicore Processorsによると、QueryPerformanceFrequency() および QueryPerformanceCounter() 関数が最適であると言われています。しかし、それがサポートされていない場合は、timeGetTime() または単に GetTickCount() を使用できます。

  1. QueryPerformanceFrequency() は CPU クロックと同じですか、それとも独自のクロックまたは時間の経過とともに変化しない独自の周波数を持つものを使用していますか?
  2. 時間の経過とともに周波数がランダムに変化する場合 (特にラップトップで)
  3. SetThreadAffinityMask 関数を使用するにはどうすればよいですか? (私が見たいくつかのコードは、関数を使用してそれを「1」に変更し、次にカウンターを使用してマスクを古い値に再度変更します。それはなぜですか?それは正しいですか?)
  4. QueryPerformanceFrequency() 関数を 1 回だけ使用し、ケース/質問 1 の頻度で除算してデルタ時間値を計算するのは正しいですか? それともケース2で直りますか?
4

3 に答える 3

2
  1. 実装の基礎となる QPC は大きく異なります。場合によってはそうですが、通常はそうではありません。
  2. これは RDTSC に影響しますが、QPC には影響しません。
  3. これは、スレッドが 1 つの CPU コアから別の CPU コアに移動するのを防ぐためです。負の時間経過を報告する高解像度タイミング メソッドを回避するのに役立つ場合があります (それは起こります...)。一般的にはお勧めしませんが。
  4. QPC の周波数は一定です。少なくとも特定のシステムでは、少なくとも再起動するまで。

しかし、必ずしも正しい質問をしているわけではありません...

Windows で一般的に使用される 4 つのタイミング関数は、GetTickCount、timeGetTime、QueryPerformanceCounter (QPC)、および RDTSC です。

それらの中で私の推奨事項:

ゲーム ロジックのタイミングは、timeGetTime で行う必要があります。シンプルで信頼性が高く、その目的に十分な解像度を備えています。(編集:デフォルトの解像度は異なります-timeBeginPeriodを呼び出して、1ミリ秒の解像度に強制できます)

GetTickCount は使用しないでください。ゲーム ロジックやパフォーマンス モニタリングには解像度が低すぎます (64 ヘルツ - 通常のモニターのリフレッシュ レートでビート周波数が発生するため、厄介な周波数です)。これは IIRC を呼び出す最速のタイミング関数ですが、解像度の低さを補うシナリオが見つかりません。(編集: timeBeginPeriod は GetTickCount の解像度を改善できるという噂があります - その噂は FALSE です)

RDTSC と QPC はどちらも、単純なゲーム ロジックのタイミングには信頼性が低く、風変わりすぎますが、パフォーマンス測定には適しています。RDTSC には、CPU 周波数の変更に依存しないユニットが必要な場合に使用するのが苦痛になる問題があり、通常は asm を使用する必要があります。QPC は通常は機能しますが、うまくいかない場合は非常にうまくいかず、非常にさまざまな方法でうまくいかないことがあります (非常に遅い場合もあれば、小さな負のデルタが頻繁に発生する場合もあれば、大きな負のデルタがまれに発生する場合もあります)。 (ラップアラウンドではありません)、時には完全に精神病などです)。RDTSC はほとんど常に高速であり、通常は解像度が大幅に向上します。全体的に、RDTSC の方が高速で、測定時の歪みが少ないという理由だけで、社内での使用には RDTSC を好みます。お客様のマシンでは、

于 2014-04-15T13:19:49.777 に答える
0

QPF / QPCは、高精度のタイマーが必要な場合に最適です(戻り値はナノ秒単位ですが、精度が1ナノ秒であることを意味するわけではありません)。それ以外の場合は、GetTickCount()(ミリ秒単位で)を使用します。どちらのバージョンも、可変CPU周波数を適切に処理する必要があります(たとえば、省電力オプションを備えたラップトップの場合)。

アフィニティマスクがシステム時刻の取得にどのように役立つかわかりません。

高精度の時間を取得する適切な方法は、QPFとQPCの両方を呼び出し、次のように時間を計算することです。

double seconds = QPC / QPF;

編集:

GetTickCount()の精度は低く、5ミリ秒程度ですが、それでもほとんどのアプリケーションに適しています。非常に短い期間を測定するための単一のオプションがあります:QPC/QPF。

于 2013-01-16T16:55:56.137 に答える
0

個人的には、内部クロック サイクルごとにインクリメントする x86 アーキテクチャの 64 ビット カウンターであるタイム スタンプ カウンターを好みます。これは rdtsc 命令を使用して読み取られ、edx:eax レジスター (x86-32) および rdx:rax (x86-64) にカウンター値を返します。

指導には問題がありましたが、それは何年も前のことです。現在、負荷に応じて実行頻度が変化する「グリーン機能」により、経過時間の計算がより困難になっていますが、経過クロック サイクルは問題ではありません。

unsigned long long startCycle, endCycle, elapsedCycles, overhead;

// @ start of program

overhead=instruction_rdtsc ();
overhead=instruction_rdtsc ()-overhead;

// preparing to measure

startCycle=instruction_rdtsc ();

// (sequence to measure)

endCycle=instruction_rdtsc ();

elapsedCycles=endCycle-startCycle-overhead;

命令自体のオーバーヘッドを決定する必要があります。Intel プロセッサのオーバーヘッドは、AMD プロセッサよりも小さいことがわかりました。可能な限り低い値を見つけるために、オーバーヘッドを数回 (たとえばループで) 測定する必要があります。測定されるシーケンスが長いほど、オーバーヘッドの問題は少なくなります。この命令により、アプリケーションに永続的なパフォーマンス メータリングを挿入して、通常の (パフォーマンス テスト以外の) 実行で実際のパフォーマンスを測定できるようになります。

パイプライン処理とアウトオブオーダー実行の問題のため、非常に短いシーケンスは測定しないでください。rdtsc の前に cpuid 命令を挿入することを提案する人もいますが、それは実際のクロック数が実際よりも大きくなることを意味するだけです。目安として 30 前後のサイクル カウントが見られますが、100 前後またはそれ以上のサイクル カウントは一般的に信頼できます。その中間にグレーゾーンがあります。

于 2014-01-21T10:39:33.123 に答える