You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

直接读取CPU PMC失败:指令退休计数器0x000000c0返回0,求排查

直接读取CPU性能监控计数器(PMC)结果为0的问题

我尝试不使用Perf等工具直接读取CPU性能监控计数器(PMC),但统计已退休指令数的计数器0x000000c0输出结果始终为0,请问测试或代码中是否存在错误?

测试代码

#include <stdint.h>
#include <stdio.h>
#include "pmc.h"
#include <fstream>
#include <iostream>
using namespace std;
counter programmables[] =
{
  { 0x000000c0ull, "INSTRUCTION_RETIRED"},
};
int core = 0;
static void pin_cpu(size_t core_ID)
{
  cpu_set_t set;
  CPU_ZERO(&set);
  CPU_SET(core_ID, &set);
  if (sched_setaffinity(0, sizeof(cpu_set_t), &set) < 0) {
    printf("Unable to Set Affinity\n");
    exit(EXIT_FAILURE);
  }
}
int main(){
    pin_cpu(core);
    int result = 0;
    int n = 10000;
    double cnt = 0;
    srand(10769);
    size_t n_programmables = sizeof(programmables) / sizeof(programmables[0]);
    setup_pmc(core, programmables, n_programmables);
    zero_pmc(n_programmables);
    start_pmc();
    double a = 0;
    for(int i = 1;i <= n;i++){
        a = (double)(rand() + 300 + i)/(rand() - i);
        cnt += a;
    }
    stop_pmc();
    result = get_stats_single();
    printf("%lf %d\n",cnt,result);
}

可能的错误点

  • 权限不足:读取PMC需要内核级权限,普通用户进程默认无法配置性能监控寄存器。必须以root权限运行程序,或者调整内核参数perf_event_paranoid为0或-1(执行echo 0 > /proc/sys/kernel/perf_event_paranoid)。
  • 计数器配置不完整:x86架构下,PMC需要完整的配置参数。仅指定事件选择码0xc0不够,还需要设置对应的UMASK(比如Intel架构下INSTRUCTION_RETIRED.ANY的UMASK为0x00),同时要在控制寄存器(IA32_PERFEVTSELx)中开启用户态计数位(USR位,位16),确保计数器统计用户态执行的指令。
  • pmc.h核心函数实现缺陷:
    • setup_pmc是否正确初始化了目标核心的性能监控控制寄存器,是否绑定到当前CPU核心?
    • zero_pmc是否真正重置了计数器的64位值?
    • get_stats_single是否读取了完整的64位PMC寄存器?如果仅读取32位部分,可能因计数器未溢出而得到0。
  • 指令执行顺序问题:启动计数器、测试代码、停止计数器的操作可能被CPU指令重排序干扰,导致计数器未正确统计测试代码的指令。需要在start_pmc后、测试循环前,以及stop_pmc前、读取计数器前添加内存屏障(如__asm__ volatile("mfence" ::: "memory");),确保指令执行顺序符合预期。

验证步骤

  1. 以root权限运行程序,同时调整perf_event_paranoid参数为宽松值。
  2. 检查pmc.h中的setup_pmc函数,确认是否正确设置了IA32_PERFEVTSELx寄存器的USR位,以及事件选择码和UMASK的组合是否匹配当前CPU微架构(可参考Intel/AMD官方手册)。
  3. 确认get_stats_single读取的是64位的IA32_PMCx寄存器(使用rdpmc指令读取完整64位值)。
  4. 添加内存屏障指令,确保计数器的启停与测试代码的执行顺序正确。

内容的提问来源于stack exchange,提问作者moep0

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 01:12:37