スレッドが同じ CPU コア上にある限り、RDTSC 命令はラップアラウンドするまで増加する数値を返し続けます。2GHz CPU の場合、これは 292 年後に発生するため、実際の問題ではありません。あなたはおそらくそれが起こるのを見ないでしょう. それほど長く生きると予想される場合は、コンピューターを、たとえば 50 年ごとに再起動するようにしてください。
RDTSC の問題は、古いマルチコア CPU のすべてのコアで同じ時点で開始する保証がなく、古いマルチ CPU ボードのすべての CPU で同じ時点で開始するという保証がないことです。 .
最近のシステムでは通常、このような問題はありませんが、スレッドのアフィニティを 1 つの CPU でのみ実行するように設定することで、古いシステムでも問題を回避できます。これはアプリケーションのパフォーマンスには良くないため、通常は行うべきではありませんが、ティックを測定する場合は問題ありません。
(別の「問題」は、多くの人が時間を測定するために RDTSC を使用していることです。これはそれが行うことではありませんが、CPU サイクルが必要であると書いたので、それで問題ありません。時間を測定するために RDTSC を使用する場合、驚くべきことがあるかもしれません。省電力やハイパーブーストなど、さまざまな周波数変更テクニックが起動します。実際の時間では、clock_gettime
syscall は Linux で驚くほど優れています。)
rdtsc
ステートメントの中に書くasm
だけで、私にとってはうまく機能し、あいまいな16進コードよりも読みやすくなります。それが正しい 16 進コードであると仮定すると (また、クラッシュせず、増え続ける数値を返すこともないので、そのように見えます)、コードは適切です。
コードの一部にかかるティック数を測定したい場合、ティック差が必要な場合は、増加し続けるカウンターの 2 つの値を減算するだけです。uint64_t t0 = rdtsc(); ... uint64_t t1 = rdtsc() - t0;
周囲のコードから分離された非常に正確な測定が必要な場合は、呼び出す前にシリアル化、つまりパイプラインを停止する必要があることに注意してくださいrdtsc
(またはrdtscp
、新しいプロセッサでのみサポートされているものを使用します) 。すべての特権レベルで使用できるシリアル化命令はcpuid
.
コメントのさらなる質問に答えて:
コンピューターの電源を入れると、TSC はゼロから始まります (また、BIOS はすべての CPU のすべてのカウンターを同じ値にリセットしますが、数年前の一部の BIOS は確実にそうしませんでした)。
したがって、プログラムの観点からは、カウンターは「過去の未知の時間」を開始し、CPU が確認するすべてのクロックティックで常に増加します。そのため、そのカウンターを返す命令を今すぐ実行し、後で別のプロセスで実行すると、より大きな値が返されます (その間に CPU が中断またはオフにされていない限り)。カウンターが増え続けるため、同じプログラムの異なる実行はより大きな数値を取得します。いつも。
さて、clock_gettime(CLOCK_PROCESS_CPUTIME_ID)
それは別の問題です。これは、OS がプロセスに割り当てた CPU 時間です。プロセスが開始されると、ゼロから始まります。新しいプロセスもゼロから始まります。したがって、2 つのプロセスが相互に実行されると、非常に類似した、または同一の数値が得られますが、数値が増加することはありません。
clock_gettime(CLOCK_MONOTONIC_RAW)
RDTSC の動作に近い (一部の古いシステムでは RDTSC が実装されています)。増加し続ける値を返します。現在、これは通常、HPET です。ただし、これは実際にはtimeであり、 ticksではありません。コンピュータが低電力状態 (通常の 1/2 の周波数で実行中など) になっても、同じペースで進みます。