Linux 如何在进程中配置和采样英特尔性能计数器

Linux 如何在进程中配置和采样英特尔性能计数器,linux,x86,benchmarking,perf,intel-pmu,Linux,X86,Benchmarking,Perf,Intel Pmu,简言之,我试图在userland基准过程中实现以下目标(伪代码,假设x86_64和UNIX系统): results[]=。。。 对于(迭代=0;迭代

简言之,我试图在userland基准过程中实现以下目标(伪代码,假设x86_64和UNIX系统):

results[]=。。。
对于(迭代=0;迭代
FWIW,我正在考虑使用的性能计数器是
CPU\u CLK\u UNHALTED.THREAD\u ALL
,用于读取与时钟频率变化无关的内核周期数(在一个示例中,我一直计划使用TSC寄存器进行此操作,但唉,这根本不是此寄存器测量的)

我最初的意图是使用内联汇编程序首先使用
WRMSR
配置计数器,然后使用
RDPMC
sample_pctr()中读取计数器

我遇到了第一个障碍,因为编写MSR需要内核特权。看起来您实际上可以从用户空间读取计数器(如果配置正确),但是配置计数器(使用MSR)的操作需要由内核执行

有没有人知道一种轻量级的方法,可以让内核从用户空间配置a性能计数器,这样我就可以在基准测试工具中使用
RDPMC

我研究/思考过的东西:

  • Linux的性能工具。似乎准备在整个流程生命周期内进行采样,而不是在流程中作为特定点(每次迭代前后)进行采样
  • 直接使用性能系统调用(即
    perf\u event\u open
    )。看起来计数器值仅会定期更新(使用采样率)或在计数器超过阈值后更新。我需要的计数器值正好在我问的时候。这就是为什么
    RDPMC
    看起来如此吸引人的原因。我认为频繁采样本身会使性能计数器读数出现偏差
  • 基于perf构建,因此可能继承了上述问题
  • 编写内核模块——工作量太大,容易出错
理想情况下,我想要一个在OpenBSD和Linux上工作的解决方案,但不知何故,我认为这是一个很高的要求。也许现在只针对Linux

非常感谢您的帮助。谢谢

编辑:我刚刚找到了,这可能就足够了。如果有更好的答案出现,我会把这个问题留待考虑。

看来最好的方法——至少对于Linux来说——是使用

您只需打开一个设备节点,查找所需的MSR地址,然后读取或写入8个字节


OpenBSD更难,因为(在撰写本文时)MSR没有用户空间代理。因此,您需要手工编写内核模块或实现sysctl。

您可以从用户空间对计数器进行编程,但您可能希望将线程固定到内核,因为PMC不会在上下文开关上保存/还原。请参阅已编写的Linux内核模块,该模块为您提供PMC访问权限,以及有关使用它们的一些讨论。谢谢!您能评论一下perf的采样模型会带来多少开销吗?我所读的任何读物中都会包括这些性能例程吗?不知道;我只是使用
perf
,将我想要微基准的循环放入它自己的独立程序中,并使用
perf stat
。而不是
lseek
/
write
,只需使用
pwrite
以指定的偏移量写入,如中所述
results[] = ...
for (iteration = 0; iteration < num_iterations; iteration++) {
    pctr_start = sample_pctr();
    the_benchmark();
    pctr_stop = sample_pctr();
    results[iteration] = pctr_stop - pctr_start;
}