用户 space 对 Intel x86-64 CPU 在 2020 年的 TSC(时间戳计数器)的稳定性如何?
How stable is TSC (TimeStamp Counter) from user space for Intel x86-64 CPUs in 2020?
有时我需要一种正确的方法来测量我的用户 space 应用程序在纳秒级的性能,以便在我的测量中包括系统调用延迟。我读了很多旧的(10 岁)文章说它不稳定,他们将从用户那里删除它 space。
- 2020年,英特尔第8/9代x86-64 CPU,稳定性如何?我们还能安全地使用 TSC 汇编代码吗?
- 如今在用户 space 中使用 TSC 的最佳实践是什么?
链接:
它与您主板上的时钟 crystal 一样稳定,但它被锁定到一个参考频率(取决于 CPU 型号),而不是当前的 CPU 核心时钟频率。该更改大约是 15 年前的(constant_tsc CPU 功能),使其可用于挂钟计时而不是循环计数。
例如,clock_gettime
的Linux VDSO user-space implementation使用rdtsc
和比例因子来计算与内核定时器中断更新的更新频率较低的时间戳的偏移量。 (VDSO = 内核拥有的代码和数据页,以只读方式映射到用户 space 进程。)
What the best practices to use TSC in the user space nowadays?
如果要计算核心时钟周期,请使用 rdpmc
(使用适当编程的 HW 性能计数器并设置为允许用户 space 读取它。)或用户 perf
或其他使用硬件性能计数器的方式。
但除此之外,您可以直接或通过包装库间接使用 rdtsc
。
根据您的开销要求,以及您愿意投入多少精力来找出 TSC 频率以便将 TSC 计数与秒相关联,您可以通过 std::chrono
或 libc clock_gettime
由于 VDSO,不需要实际进入内核。
How to get the CPU cycle count in x86_64 from C++? - 我的回答有更多关于 TSC 的细节,包括它如何在旧的 CPUs 上工作,以及乱序执行意味着你需要 lfence before/after rdtsc
如果您想等待较早的代码在读取内部 TSC 之前完成执行。
测量比几百条指令短的代码块会带来吞吐量和延迟是不同事物的复杂性,仅用一个数字来衡量性能没有意义。执行乱序意味着周围的代码很重要。
and they are gonna remove it from the user space.
x86 基本上从未删除过任何内容,而且绝对不会从 user-space 中删除任何内容。向后兼容现有的二进制文件是 x86 声名鹊起的主要理由,也是继续存在的原因。
rdtsc
记录在 Intel 和 AMD 的 x86 手册中,例如Intel's vol.2 entry for it。有一个 CPU 功能可以让内核为 user-space 禁用 RDTSC(TSD = TimeStamp Disable),但通常不会在 Linux 上使用。 (注意 #GP(0) 异常:如果寄存器 CR4 中的 TSD 标志已设置且 CPL 大于 0 - 当前特权级别 0 = 内核,更高 = 用户 -space.
IDK 是否有任何计划默认使用 TSD;我认为不会,因为它是一个有用且高效的时间源。即使是这样,在您想要进行分析/微基准测试的开发机器上,您也可以切换该功能。 (虽然通常我只是把东西放在静态可执行文件中的足够大的重复循环中,然后 运行 它在 perf stat
下以获得总时间和硬件性能计数器。)
有时我需要一种正确的方法来测量我的用户 space 应用程序在纳秒级的性能,以便在我的测量中包括系统调用延迟。我读了很多旧的(10 岁)文章说它不稳定,他们将从用户那里删除它 space。
- 2020年,英特尔第8/9代x86-64 CPU,稳定性如何?我们还能安全地使用 TSC 汇编代码吗?
- 如今在用户 space 中使用 TSC 的最佳实践是什么?
链接:
它与您主板上的时钟 crystal 一样稳定,但它被锁定到一个参考频率(取决于 CPU 型号),而不是当前的 CPU 核心时钟频率。该更改大约是 15 年前的(constant_tsc CPU 功能),使其可用于挂钟计时而不是循环计数。
例如,clock_gettime
的Linux VDSO user-space implementation使用rdtsc
和比例因子来计算与内核定时器中断更新的更新频率较低的时间戳的偏移量。 (VDSO = 内核拥有的代码和数据页,以只读方式映射到用户 space 进程。)
What the best practices to use TSC in the user space nowadays?
如果要计算核心时钟周期,请使用 rdpmc
(使用适当编程的 HW 性能计数器并设置为允许用户 space 读取它。)或用户 perf
或其他使用硬件性能计数器的方式。
但除此之外,您可以直接或通过包装库间接使用 rdtsc
。
根据您的开销要求,以及您愿意投入多少精力来找出 TSC 频率以便将 TSC 计数与秒相关联,您可以通过 std::chrono
或 libc clock_gettime
由于 VDSO,不需要实际进入内核。
How to get the CPU cycle count in x86_64 from C++? - 我的回答有更多关于 TSC 的细节,包括它如何在旧的 CPUs 上工作,以及乱序执行意味着你需要 lfence before/after rdtsc
如果您想等待较早的代码在读取内部 TSC 之前完成执行。
测量比几百条指令短的代码块会带来吞吐量和延迟是不同事物的复杂性,仅用一个数字来衡量性能没有意义。执行乱序意味着周围的代码很重要。
and they are gonna remove it from the user space.
x86 基本上从未删除过任何内容,而且绝对不会从 user-space 中删除任何内容。向后兼容现有的二进制文件是 x86 声名鹊起的主要理由,也是继续存在的原因。
rdtsc
记录在 Intel 和 AMD 的 x86 手册中,例如Intel's vol.2 entry for it。有一个 CPU 功能可以让内核为 user-space 禁用 RDTSC(TSD = TimeStamp Disable),但通常不会在 Linux 上使用。 (注意 #GP(0) 异常:如果寄存器 CR4 中的 TSD 标志已设置且 CPL 大于 0 - 当前特权级别 0 = 内核,更高 = 用户 -space.
IDK 是否有任何计划默认使用 TSD;我认为不会,因为它是一个有用且高效的时间源。即使是这样,在您想要进行分析/微基准测试的开发机器上,您也可以切换该功能。 (虽然通常我只是把东西放在静态可执行文件中的足够大的重复循环中,然后 运行 它在 perf stat
下以获得总时间和硬件性能计数器。)