34

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

所有的测量看起来都很可靠。尽管如此,我还是担心跨内核的 rdtsc 准确性,因为我一直在阅读一些暗示 tsc 在内核之间不同步的文本。

我在维基百科中找到了以下关于TSC 的信息

恒定的 TSC 行为确保每个时钟滴答的持续时间是一致的,并支持将 TSC 用作挂钟计时器,即使处理器内核改变频率。这是面向所有英特尔处理器的架构行为。

我仍然担心跨核心的准确性,这是我的问题

更多信息

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

6 回答 6

31

X86_FEATURE_CONSTANT_TSC+ X86_FEATURE_NONSTOP_TSCcpuid 中的位(edx=x80000007,位 #8;检查linux 内核的功能以进行更多检查) unsynchronized_tsc

Intel 的 Designer 的 vol3b,第 16.11.1 节 Invariant TSC 它说如下

"16.11.1 不变 TSC

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

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

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

于 2010-11-10T13:52:37.817 回答
3

在最近的处理器上,您可以在同一个包的不同内核之间执行此操作(即只有一个核心 iX 处理器的系统),您不能在单独的包(处理器)中执行此操作,因为它们不会共享 rtc。您可以通过 cpu 亲和性(将相关线程锁定到特定内核)来摆脱它,但这又取决于您的应用程序的行为方式。

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

我读到的,但尚未以编程方式确认的是,从 11h 版开始的 AMD cpus 对这个 cpuid 位具有相同的含义。

于 2014-01-17T12:52:57.897 回答
3

事实上,似乎内核不共享 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 时它会很有用。

于 2014-02-19T22:03:19.940 回答
2

在 linux 上,您可以将 clock_gettime(3) 与 CLOCK_MONOTONIC_RAW 一起使用,它可以为您提供纳秒级的结果,并且不受 ntp 更新(如果发生的话)的影响。

于 2010-08-29T08:40:02.280 回答
1

我建议你不要使用 rdtsc。它不仅不可移植,而且不可靠并且通常无法工作 - 在某些系统上,rdtsc 不会统一更新(例如,如果您使用的是 speedstep 等)。如果您想要准确的时间信息,您应该在套接字上设置 SO_TIMESTAMP 选项并使用 recvmsg() 来获取带有(微秒分辨率)时间戳的消息。

此外,您使用 SO_TIMESTAMP 获得的时间戳实际上是内核收到数据包的时间,而不是您的任务碰巧注意到的时间。

于 2010-08-02T21:50:46.547 回答
1

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

于 2010-10-16T23:27:48.133 回答