关于 hardware-counters
面向性能分析的技能指南,介绍如何用 perf、PAPI 和 Intel PCM 采集及解读硬件性能计数器。适用于需要分析缓存、分支、IPC、内存带宽或定位源代码热点的开发者。
主要功能
- 01使用 perf stat 采集 PMU 事件
- 02计算 IPC、缓存未命中率和 MPKI
- 03查询 CPU 专属原始事件
- 04用 perf annotate 关联源代码行
- 05通过 PAPI 访问可移植计数器
- 06用 Intel PCM 测量内存带宽
适用场景
- 01测量程序的缓存未命中率和分支预测失败
- 02比较指令数与周期数以计算 IPC
- 03定位导致缓存未命中的源代码行
- 04分析系统内存带宽
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mohitmishra786/ low-level-dev-skills --skill hardware-counters安装后在 Claude Code 中输入/hardware-counters确认已加载。
详细介绍
硬件性能计数器
用途
指导 Agent 分析硬件性能计数器:使用 perf stat -e 收集 PMU 事件,使用 PAPI 库以可移植的方式访问计数器,解读缓存未命中率和分支预测错误率,计算 IPC,并使用 perf annotate 将事件与源代码行关联起来。
触发条件
- “如何用 perf 测量缓存未命中率?”
- “如何统计分支预测错误?”
- “如何用 perf 计算 IPC(每时钟周期指令数)?”
- “如何使用 PAPI 库访问硬件计数器?”
- “如何查看哪些源代码行导致了最多的缓存未命中?”
- “如何用性能计数器测量内存带宽?”
工作流
1. perf stat — 基本计数器采集
# Basic hardware event summary
perf stat ./prog
# Output:
# Performance counter stats for './prog':
#
# 1,234,567,890 instructions
# 456,789,012 cycles
# 12,345,678 cache-misses # 1.23 % of all cache refs
# 23,456,789 branch-misses # 2.34 % of all branches
#
# 0.456789012 seconds time elapsed
# Derived metrics (computed from the output)
# IPC = instructions / cycles = 1,234,567,890 / 456,789,012 ≈ 2.70
# CPI = cycles / instructions ≈ 0.37
2. 使用 -e 指定 PMU 事件
# Specific hardware events
perf stat -e instructions,cycles,cache-misses,branch-misses ./prog
# L1/L2/L3 cache events
perf stat -e \
L1-dcache-loads,L1-dcache-load-misses,\
L2-loads,L2-load-misses,\
LLC-loads,LLC-load-misses \
./prog
# Memory bandwidth (Intel)
perf stat -e \
uncore_imc/cas_count_read/,\
uncore_imc/cas_count_write/ \
./prog
# TLB misses
perf stat -e dTLB-loads,dTLB-load-misses,iTLB-loads,iTLB-load-misses ./prog
# Branch misprediction rate
perf stat -e branches,branch-misses ./prog
# Rate = branch-misses / branches × 100%
# Available events (varies by CPU)
perf list hardware # generic hardware events
perf list cache # cache events
perf list pmu # raw PMU events for your CPU
3. 关键指标和阈值
| 指标 | 公式 | 良好 | 需关注 |
|---|---|---|---|
| IPC | instructions / cycles | > 2.0(现代 x86) | < 1.0 |
| L1 未命中率 | L1-misses / L1-accesses | < 1% | > 5% |
| LLC 未命中率 | LLC-misses / LLC-accesses | < 1% | > 10% |
| 分支未命中率 | branch-misses / branches | < 1% | > 5% |
| MPKI | 每 1K 条指令的未命中次数 | — | L3 MPKI > 10 = 受内存限制 |
# Compute MPKI (Misses Per Kilo-Instructions)
perf stat -e instructions,LLC-load-misses ./prog
# MPKI = LLC-load-misses / (instructions / 1000)
4. 原始 PMU 事件(特定 CPU)
对于通用别名中没有的事件,请使用原始事件代码:
# Intel: use perf list or look up in Intel SDM
# Format: rXXYY where XX=umask, YY=event code
perf stat -e r0124 ./prog # example Intel raw event
# List Intel events with ocperf (OpenCL Perf Events)
pip install ocperf
ocperf.py list | grep "mem_load"
# Use libpfm4 for event names
pfm_ls | grep "MEM_LOAD"
perf stat -e $(pfm_ls | grep "MEM_LOAD_RETIRED.L3_MISS") ./prog
# AMD: similar approach
perf stat -e r04041 ./prog # AMD raw event
5. 使用 perf record/annotate 进行源代码级注释
# Record with hardware events
perf record -e LLC-load-misses -g ./prog
# Annotate: show source lines sorted by cache miss count
perf annotate --stdio
# Interactive (requires debug symbols)
perf report
# Press 'a' on a function to annotate it
# Combined: record hotspot + annotate
perf record -e cycles:u -g ./prog
perf annotate --symbol=my_function --stdio 2>/dev/null | head -40
# Example annotate output:
# Percent | Source code
# 45.23 | for (int i = 0; i < N; i++)
# 3.12 | sum += data[i]; ← cache miss here (strided access)
6. PAPI — 硬件计数器可移植 API
PAPI 提供可用于不同 CPU 架构的可移植 C API:
#include <papi.h>
#include <stdio.h>
int main(void) {
int Events[] = {PAPI_TOT_INS, PAPI_TOT_CYC,
PAPI_L2_TCM, PAPI_BR_MSP};
long long values[4];
if (PAPI_library_init(PAPI_VER_CURRENT) != PAPI_VER_CURRENT) {
fprintf(stderr, "PAPI init failed\n");
return 1;
}
PAPI_start_counters(Events, 4);
// --- Code to measure ---
do_work();
// -----------------------
PAPI_stop_counters(values, 4);
printf("Instructions: %lld\n", values[0]);
printf("Cycles: %lld\n", values[1]);
printf("IPC: %.2f\n", (double)values[0]/values[1]);
printf("L2 cache misses: %lld\n", values[2]);
printf("Branch mispred: %lld\n", values[3]);
return 0;
}
# Build with PAPI
gcc -O2 -g -o prog prog.c -lpapi
# Available PAPI events on your system
papi_avail -a | head -30
papi_native_avail | grep "L3" # native events with "L3"
常用的 PAPI 预设:
| 预设 | 事件 |
|---|---|
PAPI_TOT_INS | 指令总数 |
PAPI_TOT_CYC | 周期总数 |
PAPI_L1_DCM | L1 数据缓存未命中 |
PAPI_L2_TCM | L2 缓存总未命中数 |
PAPI_L3_TCM | L3 缓存总未命中数 |
PAPI_BR_MSP | 分支预测错误 |
PAPI_TLB_DM | 数据 TLB 未命中 |
PAPI_FP_INS | 浮点指令 |
PAPI_VEC_INS | 向量/SIMD 指令 |
7. Intel PCM(性能计数器监视器)
# Intel PCM — system-wide counters, no root required on modern kernels
git clone https://github.com/intel/pcm
cd pcm && cmake -S . -B build && cmake --build build
# Measure memory bandwidth
./build/bin/pcm-memory 1 # sample every 1 second
# Core utilization + IPC
./build/bin/pcm 1
# Cache miss breakdown per socket
./build/bin/pcm 1 -csv | head -20
相关技能
- 使用
skills/profilers/intel-vtune-amd-uprof进行引导式微架构分析 - 使用
skills/profilers/linux-perf执行 perf record/report 并生成火焰图 - 使用
skills/low-level-programming/cpu-cache-opt应用缓存优化模式 - 使用
skills/low-level-programming/simd-intrinsics提升 FLOPS/周期指标
评论
支持 Markdown