4

使用:

inline uint64_t rdtsc()
{
  uint32_t cycles_high;
  uint32_t cycles_low;

  asm volatile ("CPUID\n\t"
      "RDTSC\n\t"
      "mov %%edx, %0\n\t"
      "mov %%eax, %1\n\t": "=r" (cycles_high), "=r" (cycles_low)::
      "%rax", "%rbx", "%rcx", "%rdx");
  return ( ((uint64_t)cycles_high << 32) | cycles_low );
}

スレッド 1 実行中

while(globalIndex < COUNT)
{
  while(globalIndex %2 == 0 && globalIndex < COUNT)
    ;
  cycles[globalIndex][0] = rdtsc();
  cycles[globalIndex][1] = cpuToBindTo;
  __sync_add_and_fetch(&globalIndex,1);
}

スレッド 2 実行中

while(globalIndex < COUNT)
{
  while(globalIndex %2 == 1 && globalIndex < COUNT)
    ;
  cycles[globalIndex][0] = rdtsc();
  cycles[globalIndex][1] = cpuToBindTo;
  __sync_add_and_fetch(&globalIndex,1);
}

私は見ています

CPU     rdtsc()         t1-t0
11 = 5023231563212740   990
03 = 5023231563213730   310
11 = 5023231563214040   990
03 = 5023231563215030   310
11 = 5023231563215340   990
03 = 5023231563216330   310
11 = 5023231563216640   990
03 = 5023231563217630   310
11 = 5023231563217940   990
03 = 5023231563218930   310
11 = 5023231563219240   990
03 = 5023231563220230   310
11 = 5023231563220540   990
03 = 5023231563221530   310
11 = 5023231563221840   990
03 = 5023231563222830   310
11 = 5023231563223140   990
03 = 5023231563224130   310
11 = 5023231563224440   990
03 = 5023231563225430   310
11 = 5023231563225740   990
03 = 5023231561739842   310
11 = 5023231561740152   990
03 = 5023231561741142   310
11 = 5023231561741452   12458
03 = 5023231561753910   458
11 = 5023231561754368   1154
03 = 5023231561755522   318
11 = 5023231561755840   982
03 = 5023231561756822   310
11 = 5023231561757132   990
03 = 5023231561758122   310
11 = 5023231561758432   990
03 = 5023231561759422   310

どうやって 12458 の pong を受け取ったのかわかりませんが、なぜ 650-650-650 ではなく 310-990-310 と表示されているのか疑問に思っていました。tsc はコア間で同期されるはずだと思っていました。私のconstant_tsc CPUフラグはオンです。

4

2 に答える 2

1

このコードを実行しているのは何ですか? TSC 同期は、OS/カーネルで行われることになっており、ハードウェアに依存しています。たとえば、powernow-k8.tscsync=1ブートローダーを介してカーネル ブート パラメータにフラグのようなものを渡すことができます。

OS とハードウェアの組み合わせに適した TSC 同期方法を検索する必要があります。概して、このすべてが自動化されています。カスタム カーネルまたは i686 以外のハードウェアで実行していても驚かないでしょうか?

Google で正しい用語を検索すると、このトピックに関するメーリング リストのディスカッションなど、多くのリソースが見つかります。たとえば、議論されている 1 つのアルゴリズムを次に示します(ただし、これは明らかに適切なものではありません)。しかし、これはユーザーランドの開発者が心配すべきことではありません。これは、カーネル開発者だけが頭を悩ます必要がある難解な魔術です。

基本的に、ブート時に、SMP マシン上のすべての異なるプロセッサおよび/またはコア間で TSC カウンターを一定の誤差範囲内で同期するのは、OS の仕事です。大幅にずれている数値が表示されている場合は、TSC 同期に何か問題があり、独自の TSC 同期アルゴリズムを実装しようとするよりも、OS が TSC を正しく同期していない理由を見つけることに時間を費やしたほうがよいでしょう。

于 2012-05-08T03:18:29.767 に答える
0

NUMAメモリアーキテクチャはありますか?グローバルカウンターは、一方のCPUでは数ホップ離れたRAMに配置され、もう一方のCPUではローカルに配置される可能性があります。これをテストするには、同じNUMAノード上のコアにスレッドを固定します。

編集:パフォーマンスはCPU固有だったので、私はこれを推測していました。

編集:TSCの同期について。私は簡単な方法を知りません、それはそれがないということではありません!コア1を基準クロックとして使用し、それをコア2と比較するとどうなるでしょうか。その比較を何度も行い、最小値をとった場合は、適切な近似値が得られる可能性があります。これは、比較の途中で横取りされた場合に対処する必要があります。

于 2012-05-07T19:53:50.877 に答える