跨CPU核心的rdtsc精度

时间:2010-08-02 13:18:27

标签: linux multicore rdtsc

我从一个线程发送网络数据包,并在另一个CPU内核上运行的第二个线程上接收回复。我的过程测量发送和发送之间的时间。接收每个数据包(类似于ping)。我正在使用rdtsc来获得高分辨率,低开销的时序,这是我的实现所需要的。

所有测量结果都很可靠。尽管如此,我仍然担心核心的rdtsc准确性,因为我一直在阅读一些暗示tsc未在核心之间同步的文本。

我找到了有关TSC in wikipedia

的以下信息
  

常量TSC行为确保每个时钟周期的持续时间   制服并支持使用   即使TSC作为挂钟定时器   处理器核心改变频率。这个   建筑行为正在发生变化   适用于所有英特尔处理器。

我仍然担心核心的累积,这是我的问题

更多信息

  • 我在Intel nehalem机器上运行我的程序。
  • 操作系统是Linux。
  • 为所有核设置了“ constant_tsc ”cpu标志。

6 个答案:

答案 0 :(得分:26)

cpuid中的

X86_FEATURE_CONSTANT_TSC + X86_FEATURE_NONSTOP_TSC位(edx = x80000007,位#8;检查linux内核的 unsynchronized_tsc function以获取更多检查)

英特尔设计师的vol3b,第16.11.1节不变的TSC,它说以下

  

“16.11.1不变的TSC

     

较新处理器中的时间戳计数器可能支持增强,称为不变TSC。处理器对不变TSC的支持由CPUID.80000007H:EDX [8]指示。

     

不变的TSC将在所有ACPI P-,C-中以恒定速率运行。和T状态。这是向前发展的建筑行为。在具有不变TSC支持的处理器上,OS可以将TSC用于挂钟计时器服务(而不是ACPI或HPET计时器)。 TSC读取效率更高,不会产生与环转换或访问平台资源相关的开销。“

因此,如果TSC可用于挂钟,则可保证它们同步。

答案 1 :(得分:3)

在最近的处理器上,你可以在同一个软件包的不同内核之间(即只有一个核心iX处理器的系统),你不能在单独的软件包(处理器)中进行,因为它们不会共享RTC。您可以通过cpu affinity(将相关线程锁定到特定的核心)来逃避它,但是这又取决于应用程序的行为方式。

在linux上,您可以检查/ proc / cpuinfo上的constant_tsc,以查看处理器是否有一个对整个包有效的tsc。原始寄存器位于CPUID.80000007H:EDX [8]

我读到的内容,但尚未以编程方式确认,从版本11h开始的AMD cpus与此cpuid位具有相同的含义。

答案 2 :(得分:2)

在linux上你可以使用带有CLOCK_MONOTONIC_RAW的clock_gettime(3),它可以提供纳秒分辨率,并且不受ntp更新(如果有的话)。

答案 3 :(得分:2)

事实上,似乎核心不共享TSC,请检查此线程: http://software.intel.com/en-us/forums/topic/388964

总结一下,不同的内核不共享TSC,如果内核更改为特定的能源状态,TSC可能会失去同步,但这取决于CPU的类型,因此您需要检查Intel文档。似乎大多数操作系统在启动时同步TSC 我在具有核心i5处理器的Linux Debian机器上使用激动反应算法检查了不同内核上的TSC之间的差异。激励过程(在一个核心中)在共享变量中写入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汇编指令返回一个值,表示读取TSC的CPU。这不是你的情况,但是当你想要在一个简单的代码段中测量时间并且你想确保在代码中间没有移动CPU的过程时它会很有用。

答案 4 :(得分:0)

我建议您不要使用rdtsc。它不仅不便携,而且不可靠并且通常不起作用 - 在某些系统上rdtsc不能均匀更新(就像你使用的是speedtep等)。如果您需要准确的时序信息,您应该在套接字上设置SO_TIMESTAMP选项,并使用recvmsg()来获取具有(微秒分辨率)时间戳的消息。

此外,使用SO_TIMESTAMP获得的时间戳实际上是内核获取数据包的时间,而非您的任务正好注意到的时间。

答案 5 :(得分:0)

您可以使用sched_set_affinity() API设置线程关联,以便在一个CPU核心上运行您的线程。