1つのスレッドからネットワークパケットを送信し、別のCPUコアで実行されている2番目のスレッドで応答を受信しています。私のプロセスは、各パケットの送信と受信の間の時間を測定します(pingと同様)。 rdtscを使用して、実装に必要な高解像度、低オーバーヘッドのタイミングを取得しています。
すべての測定値は信頼できるように見えます。それでも、tscがコア間で同期されていないことを示唆するいくつかのテキストを読んでいるので、コア間のrdtscの精度について心配しています。
ウィキペディアのTSC に関する次の情報を見つけました
一定のTSC動作により、各クロックティックの持続時間が均一になり、プロセッサコアが周波数を変更した場合でもウォールクロックタイマーとしてTSCの使用がサポートされます。これは、すべてのIntelプロセッサで前進しているアーキテクチャの動作です。
それでもコア間の発生が心配です。これが私の質問です
X86_FEATURE_CONSTANT_TSC
+ X86_FEATURE_NONSTOP_TSC
cpuidのビット(edx = x80000007、ビット#8;チェック unsynchronized_tsc
function 詳細なチェックのためのLinuxカーネルの)
IntelのDesignerのvol3b、セクション16.11.1 Invariant TSCには、次のように書かれています。
"16.11.1不変TSC
新しいプロセッサのタイムスタンプカウンタは、不変TSCと呼ばれる拡張機能をサポートしている場合があります。不変TSCに対するプロセッサのサポートは、CPUID.80000007H:EDX [8]で示されます。
不変TSCは、すべてのACPI P-、C-で一定の速度で実行されます。およびT状態。これは、前進するアーキテクチャの動作です。不変のTSCをサポートするプロセッサでは、OSは(ACPIまたはHPETタイマーの代わりに)ウォールクロックタイマーサービスにTSCを使用する場合があります。 TSCの読み取りははるかに効率的であり、リング遷移やプラットフォームリソースへのアクセスに関連するオーバーヘッドは発生しません。」
したがって、TSCをウォールクロックに使用できる場合、それらは同期していることが保証されます。
最近のプロセッサーでは、同じパッケージの別々のコア間でそれを行うことができます(つまり、1つのコアiXプロセッサーのみを備えたシステム)。rtcを共有しないため、別々のパッケージ(プロセッサー)でそれを行うことはできません。 CPUアフィニティ(関連するスレッドを特定のコアにロックする)を介してそれを回避することができますが、それでもアプリケーションの動作に依存します。
Linuxでは、/ proc/cpuinfoのconstant_tscをチェックして、プロセッサにパッケージ全体で有効な単一のtscがあるかどうかを確認できます。生のレジスタはCPUID.80000007H:EDX [8]にあります
私が読んだものの、プログラムでまだ確認されていないのは、リビジョン11h以降のAMDCPUがこのcpuidビットに対して同じ意味を持っているということです。
実際、コアはTSCを共有していないようです。次のスレッドを確認してください: http://software.intel.com/en-us/forums/topic/388964
要約すると、異なるコアはTSCを共有しません。コアが特定のエネルギー状態に変化すると、TSCが同期しなくなることがありますが、CPUの種類によって異なるため、Intelのドキュメントを確認する必要があります。ほとんどのオペレーティングシステムは、起動時にTSCを同期しているようです。
コアi5プロセッサを搭載したLinuxDebianマシンで、刺激的な反応アルゴリズムを使用して、異なるコアのTSC間の違いを確認しました。エキサイタープロセス(1つのコア)は共有変数にTSCを書き込み、反応するプロセスがその変数の変更を検出すると、その値を比較し、それを自身のTSCと比較します。これは私のテストプログラムの出力例です:
TSC ping-pong test result:
TSC cores (exciter-reactor): 0-1
100 records, avrg: 159, range: 105-269
Dispersion: 13
TSC ping-pong test result:
TSC cores (exciter-reactor): 1-0
100 records, avrg: 167, range: 125-410
Dispersion: 13
エキサイターCPUが0(平均159ティック)の場合の反応時間は、エキサイターCPUが1(167ティック)の場合とほぼ同じです。これは、それらがかなりよく同期していることを示しています(おそらくいくつかの違いがあります)。他のコアペアでは、結果は非常に似ていました。
一方、rdtscp Assembly命令は、TSCが読み取られたCPUを示す値を返します。これはあなたのケースではありませんが、単純なコードセグメントで時間を測定し、プロセスがコードの途中でCPUから移動されていないことを確認したい場合に役立ちます。
Linuxでは、clock_gettime(3)をCLOCK_MONOTONIC_RAWとともに使用できます。これにより、ナノ秒の解像度が得られ、ntpの更新(発生した場合)の影響を受けません。
Rdtscは使用しないことをお勧めします。移植性がないだけでなく、信頼性が低く、一般的に機能しません-一部のシステムでは、rdtscが均一に更新されません(speedstepなどを使用している場合など)。正確なタイミング情報が必要な場合は、ソケットでSO_TIMESTAMPオプションを設定し、recvmsg()を使用して(マイクロ秒の解像度)タイムスタンプでメッセージを取得する必要があります。
さらに、SO_TIMESTAMPで取得するタイムスタンプは、実際にはISカーネルがパケットを取得した時間であり、タスクが偶然に気付いたときではありません。
1つのCPUコアでスレッドを実行するために、sched_set_affinity()
APIを使用してスレッドアフィニティを設定できます。