简而言之,我试图在用户空间基准测试进程中实现以下目标(伪代码,假设为x86_64和UNIX系统):
results[] = ...
for (iteration = 0; iteration < num_iterations; iteration++) {
pctr_start = sample_pctr();
the_benchmark();
pctr_stop = sample_pctr();
results[iteration] = pctr_stop - pctr_start;
}
值得一提的是,我要使用的性能计数器是CPU_CLK_UNHALTED.THREAD_ALL
,用于读取独立于时钟频率变化的核心周期数(在以前的一个问题中,我原本打算使用TSC寄存器来实现这一点,但遗憾的是,该寄存器根本不测量这个)。
我的初始意图是使用内联汇编器首先使用WRMSR
配置计数器,然后在sample_pctr()
中使用RDPMC
读取计数器。
但我在第一个障碍上失败了,因为写入MSRs需要内核权限。似乎你确实可以从用户空间读取计数器(如果正确配置),但配置计数器(使用MSR)的操作需要由内核执行。
有人知道一种轻量级的方法来从用户空间请求内核配置性能计数器,以便我可以在我的基准测试套件中使用RDPMC
吗?
我考虑过以下事项:
- 针对Linux的Perf工具。似乎适用于在进程的整个生命周期中进行采样,而不是在特定时间点(在每次迭代之前和之后)内部进行。
- 直接使用Perf系统调用(即
perf_event_open
)。看起来计数器值只会定期更新(使用采样率)或在计数器超过阈值后更新。我需要在我要求的那一刻精确地获得计数器值。这就是为什么RDPMC
看起来很有吸引力的原因。我认为频繁采样本身会扭曲性能计数器读数。 - PAPI基于Perf构建,因此可能会继承上述问题。
- 编写一个内核模块——太费力了,也容易出错。
理想情况下,我希望找到适用于OpenBSD和Linux的解决方案,但我认为这是一个高难度的问题。也许现在只需要适用于Linux。
非常感谢任何帮助。谢谢。
编辑:我刚刚发现了Linux msr设备节点,这可能就足够了。如果有更好的答案出现,我会保留这个问题。
perf stat
使用perf
。 - Peter Cordes