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

perf中cpu_core与cpu_atom指标差异及异常问题咨询

关于perf stat中cpu_core与cpu_atom分支统计指标的疑问解答

1. cpu_core与cpu_atom统计指标的核心区别

  • cpu_core:统计的是ISA(指令集架构)层面的指令事件。比如cpu_core/branch-misses/代表CPU执行ISA分支指令(如jmp、je等汇编指令)时发生预测错误的次数,完全对应代码编译后的汇编指令数量。
  • cpu_atom:统计的是x86微架构层面的微操作(uop)事件。x86 CPU会将复杂的ISA指令拆分成多个简单微操作执行,部分指令还能通过**宏融合(Macro-fusion)**合并为单个微操作。这里的分支统计针对的是进入CPU分支预测单元处理的微操作数量。

2. 为何cpu_atom数值有时小于cpu_core?

这种情况主要由微架构的优化特性导致:

  • 宏融合优化:例如cmp指令+条件分支指令(如je)会被CPU融合成一个分支微操作,此时ISA层面是2条指令,但微操作层面仅统计1次分支事件,直接导致cpu_atom的分支计数少于cpu_core。
  • 分支消除:部分条件分支会被硬件动态优化(如循环展开后的冗余分支被合并,或可预测分支被硬件直接跳过),实际执行的分支微操作数量少于ISA分支指令数。
  • 统计范围差异:cpu_core统计所有提交执行的ISA分支指令,而cpu_atom仅统计进入分支预测单元的微操作,部分分支可能在解码阶段就被处理,未进入预测单元的统计范围。

3. 多次运行中比例波动、cpu_atom指标未被统计的原因

  • 硬件计数器采样误差:perf依赖硬件性能计数器实现统计,当程序运行时间较短、计数器溢出或受到系统调度干扰时,可能出现统计不全的情况。cpu_atom作为微架构特定计数器,对硬件状态变化更敏感,容易出现数值缺失。
  • CPU异构调度:如果程序被调度到异构CPU核心(如Intel大小核),不同核心的微架构差异会导致cpu_atom计数器无法在部分核心上正常工作,进而引发数值波动或缺失。
  • 编译优化的不确定性:你使用了-O3优化,编译器会根据上下文对分支进行动态优化(如循环展开、将条件分支转换为cmov条件移动指令),不同运行场景下的优化结果可能不同,导致分支的ISA指令与微操作数量比例波动。

4. 191.02%异常值的计算逻辑

这个数值并非bug,而是两种统计层面差异导致的正常结果:

  • 你推测的计算方式cpu_core/branch-misses ÷ cpu_atom/branches是正确的。该比例没有“不能超过100%”的限制,因为:
    • 分子是ISA层面的分支预测错误次数,对应原始的分支指令数量;
    • 分母是微架构层面的分支微操作数量,可能因宏融合等优化远小于ISA分支指令数。
  • 举例说明:若cpu_core统计到100次分支预测错误,而cpu_atom仅统计到52次分支微操作,计算得100/52≈192%,与你看到的191.02%高度吻合。这种超过100%的比例,本质是ISA分支与微操作分支的数量差异导致的。

测试代码

#include <benchmark/benchmark.h>

#include <algorithm>
#include <vector>

void test(benchmark::State& s) {
    const auto N = s.range(0);
    std::vector<unsigned long> v1(N), v2(N), c(N);
    
    srand(1);
    std::generate(v1.begin(), v1.end(), [] { return rand(); });
    std::generate(v2.begin(), v2.end(), [] { return rand(); });
#ifdef HIT
    std::generate(c.begin(), c.end(), [] { return rand() >= 0; });
#else
    std::generate(c.begin(), c.end(), [] { return rand() & 1; });
#endif

    for (auto _ : s) {
        unsigned long result = 0;
        for (int i = 0; i < N; i++) {
            if (c[i]) {
                result += v1[i];
            } else {
                result *= v2[i];
            }
        }
        benchmark::DoNotOptimize(result);
        benchmark::ClobberMemory();
    }
}

BENCHMARK(test)->Arg(1 << 22);
BENCHMARK_MAIN();

编译命令

g++ branch_prediction.cpp -o miss -g3 -O3 -mavx2 -lbenchmark

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 22:47:01