跨 CPU 核心的 rdtsc 准确度
- 2024-10-30 08:36:00
- admin 原创
- 48
问题描述:
我从一个线程发送网络数据包,并在运行于不同 CPU 核心上的第二个线程上接收回复。我的进程测量每个数据包发送和接收之间的时间(类似于 ping)。我使用 rdtsc 来获取高分辨率、低开销的计时,这是我的实现所需要的。
所有测量结果看起来都很可靠。不过,我还是担心 rdtsc 在不同核心之间的准确性,因为我读过一些文章,暗示 tsc 在核心之间不同步。
我在维基百科上找到了有关 TSC的以下信息
恒定的 TSC 行为可确保每个时钟滴答的持续时间是一致的,并且即使处理器核心改变频率,也支持将 TSC 用作挂钟定时器。这是所有英特尔处理器未来的架构行为。
我仍然担心跨核心的准确性,这是我的问题
更多信息
我在 Intel nehalem 机器上运行我的流程。
操作系统是Linux。
所有核心都设置了“ constant_tsc ” cpu 标志。
解决方案 1:
X86_FEATURE_CONSTANT_TSC
+ X86_FEATURE_NONSTOP_TSC
cpuid 中的位(edx=x80000007,位#8;检查Linux 内核的功能以进行更多检查)unsynchronized_tsc
英特尔设计师的 vol3b,第 16.11.1 节不变 TSC 说明了以下内容
“16.11.1 不变 TSC
较新处理器中的时间戳计数器可能支持增强功能,称为不变 TSC。处理器对不变 TSC 的支持由 CPUID.80000007H:EDX[8] 指示。
不变的 TSC 将在所有 ACPI P、C 和 T 状态下以恒定速率运行。这是未来的架构行为。在具有不变 TSC 支持的处理器上,操作系统可能会将 TSC 用于挂钟计时器服务(而不是 ACPI 或 HPET 计时器)。TSC 读取效率更高,并且不会产生与环转换或访问平台资源相关的开销。”
因此,如果 TSC 可以用作挂钟,则可以保证它们同步。
解决方案 2:
在最近的处理器上,您可以在同一个包的不同核心之间执行此操作(即只有一个核心 iX 处理器的系统),但您无法在不同的包(处理器)中执行此操作,因为它们不会共享 rtc。您可以通过 CPU 关联(将相关线程锁定到特定核心)来实现这一点,但这又取决于您的应用程序的行为方式。
在 Linux 上,您可以检查 /proc/cpuinfo 上的 constant_tsc,以查看处理器是否有一个对整个包有效的 tsc。原始寄存器位于 CPUID.80000007H:EDX[8]
我读过一些内容,但尚未通过编程确认,从修订版 11h 开始的 AMD CPU 对于此 cpuid 位具有相同的含义。
编辑:这是一个很好的后续阅读。
解决方案 3:
事实上,似乎核心不共享 TSC,请查看此线程:
http ://software.intel.com/en-us/forums/topic/388964
总而言之,不同的内核不共享 TSC,如果内核更改为特定能量状态,则 TSC 有时会失去同步,但这取决于 CPU 的类型,因此您需要查看 Intel 文档。似乎大多数操作系统在启动时都会同步 TSC。
我在一台配备 core 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:
在 Linux 上,您可以将 clock_gettime(3) 与 CLOCK_MONOTONIC_RAW 一起使用,它为您提供纳秒级的结果,并且不受 ntp 更新的影响(如果发生)。
解决方案 5:
我建议你不要使用 rdtsc。它不仅不可移植,而且不可靠,通常无法工作 - 在某些系统上,rdtsc 不会统一更新(例如,如果你使用 speedstep 等)。如果你想要准确的时间信息,你应该在套接字上设置 SO_TIMESTAMP 选项,并使用 recvmsg() 获取带有(微秒分辨率)时间戳的消息。
此外,使用 SO_TIMESTAMP 获得的时间戳实际上是内核获取数据包的时间,而不是您的任务偶然注意到的时间。
解决方案 6:
您可以使用sched_set_affinity()
API 设置线程亲和性,以便在一个 CPU 核心上运行线程。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件