如何测量现代x86处理器实际经过的时钟周期数?

4

在最近的x86上,RDTSC返回一些伪计数器,它测量时间而不是时钟周期

鉴于此,我如何测量当前线程/程序的实际时钟周期

就平台而言,我更喜欢Windows,但Linux的答案也可以。

1个回答

4
这并不简单。在Intel® 64和IA-32体系结构开发人员手册:第3B卷中描述了这样一件事:
以下是其行为:
对于Pentium M处理器,对于Pentium 4处理器、英特尔Xeon处理器和P6系列处理器:时间戳计数器会随着每个内部处理器时钟周期递增。内部处理器时钟周期由当前的核心时钟与总线时钟比率确定。Intel® SpeedStep®技术的转换也可能影响处理器时钟。
对于Pentium 4处理器,英特尔Xeon处理器;对于英特尔Core Solo和英特尔Core Duo处理器;对于英特尔Xeon处理器5100系列和英特尔Core 2 Duo处理器;对于英特尔Core 2和英特尔Xeon处理器;对于英特尔Atom处理器:时间戳计数器以恒定速率递增。该速率可以由处理器的最大核心时钟与总线时钟比率设置,也可以由处理器启动时设置的最大解析频率设置。最大已解析频率可能与处理器基础频率不同。在某些处理器上,TSC频率可能与品牌字符串中的频率不同。
这是您用例的建议:
为了确定平均处理器时钟频率,英特尔建议使用性能监视逻辑来计算所需平均值的一段时间内处理器核心时钟的计数。有关更多信息,请参见第18.17节“在基于Intel NetBurst®微架构的处理器上具有Intel Hyper-Threading Technology的系统中计数时钟”和第19章“性能监视事件”。
坏消息是,据我所知,性能计数器通常无法在AMD和英特尔处理器之间移植。因此,您必须确保检查使用AMD文档中的哪些性能计数器。还存在一些复杂性:您不能轻松地测量任意代码所需的周期数。例如,处理器可能会暂停或进入睡眠模式(请参见C状态)或操作系统可以执行一些无法在没有高权限的情况下进行配置文件记录的受保护代码(出于安全考虑)。只要您需要测量相对较长时间(至少几十个周期)的数值密集型代码的周期数,此方法就很好。最重要的是,MSR的文档和使用非常复杂,并且有一些限制。
CPU_CLK_UNHALTED.THREADCPU_CLK_UNHALTED.REF_TSC这样的性能计数器似乎是衡量您想要衡量的内容的好起点。使用库来读取这些性能计数器通常是一个非常好的想法(除非您喜欢头痛至少几天)。PAPI可能足以完成此工作。
以下是一些有趣的相关帖子:

谢谢指引,我会去看看!+1 - user541686
1
要在Linux下测量程序的用户空间核心时钟周期,perf stat --all-user ./my_program会默认计算cycles硬件PMU事件以及instructions和其他一些事件。 --all-user使它将PMU编程为仅在CPU处于非内核特权级别时进行计数。这很容易,除非您想要进入微小的测量间隔,在此情况下,使用rdpmc在程序中计时(在调用系统调用以对PMU进行编程后),此时测量开销和乱序执行成为一个巨大的问题。 - Peter Cordes
1
@PeterCordes: 谢谢。是的,我希望避免使用外部分析器程序,因为我想要测量的循环计数发生在我的程序中特定的时间间隔内。它们对我来说远非微不足道,我也不担心乱序执行等问题,但整个程序运行时间更长,有更多的逻辑和干扰源使得我无法测量我想要的内容。(当然,在最坏情况下,我会花些时间挑选出热点路径并在隔离环境中进行测量,但这有时候非常麻烦。) - user541686
1
@user541686:有几个技巧可以做到这一点:在程序的某个点上生成一个 perf stat -p <PID>,它会附加到您的程序上(示例)。或者使用更现代的 perf通过编写管道来启用/禁用 perf 事件收集,让被分析的程序控制 perf stat - Peter Cordes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接