跳转到主要内容

AMD IBS

AMD IBS(Instruction-Based Sampling,基于指令采样)是 AMD 处理器中一项硬件级性能分析技术,用于监控和记录处理器执行的指令流,为开发者和系统管理员提供细粒度的性能洞察。

1. IBS?

IBS 是一种基于已执行指令的硬件采样技术。与传统基于事件计数的采样(如周期、缓存未命中等)不同,IBS 能够采集指令级别的丰富信息,比如:

  • 每条采样指令是否命中 L1/L2/L3 缓存

  • 是否发生 TLB miss

  • 分支预测是否成功

  • 指令类型(load、store、branch、ret 等)

  • 执行延迟、流水线 stalls 情况

  • 内存地址访问路径(可选)

2. IBS 的两种采样模式

IBS 提供两种模式:

2.1. IBS Fetch Sampling(IBS-Fetch)

  • 针对指令获取阶段

  • 可分析:

    • 指令是否来自 L1 I-cache

    • 指令 TLB miss

    • ITLB/TLB walk 等

2.2. IBS Operation Sampling(IBS-Op)

  • 针对指令执行阶段

  • 可分析:

    • 指令是否为 Load/Store

    • Load 是否命中 L1/L2/L3 或内存

    • Load 延迟、分支指令是否预测成功

    • Load 地址(可选开启)

3. 优缺点

下面是 IBS 的优点列举:

特性优势
精确性每条采样指令都已实际执行,避免“猜测”
低开销硬件实现,支持大规模部署
可获取微架构细节如分支预测失败、流水线停顿等
支持用户态/内核态分析便于深入系统级性能瓶颈分析

4. 用法解析

[!tip] 确保内核已经安装 IBS 驱动。

4.1. 使用 perf 采集

我们选取 AMD 的 Genoa 机型举例,使用如下命令采集 IBS 数据:

perf record -c 1000000 -C0-7 -a -e ibs_op/l3missonly=1/ --raw-samples sleep 30

0-7 core 表示 CCD 0, -c 1000000 表示每 100w 条指令采样一次,l3missonly 表示只监控 l3 miss 的指令,类似于一个 filter 的作用。

其输出是所有 load/store 指令的相关信息,我们使用下面命令对输出进行筛选并求平均值,就可以拿到访存指令的 Miss Latency:

perf report -D | grep -B4 "PERF_RECORD_SAMPLE" | grep -A5 "DRAM" | grep -o "DcMissLat......." | awk '{sum += $2; count++} END {if (count > 0) print sum / count}'

4.2. 技术原理简述

ibs_op/l3missonly=1/ 用于指定 只采样那些导致 L3 cache miss 的 load/store 指令。开启该选项时,只有穿透 L3 cache,访问 DRAM 或远程 CCD 的 memory 操作才会被采样。也就是说,只会记录那些因为 L3 cache miss 而最终访问 DRAM 或远程 CCD 的 load/store 指令。

导致 L3 Cache Miss 的指令,通常是 memory load/store 指令,具体包括:

类型示例说明
Loadmov rax, [rbx]从内存读取,未在 L3 命中(访问 DRAM 或远程)
Storemov [rcx], rdx少数 store 也可能触发读取(如 write-allocate),未命中 L3
Prefetchprefetcht0 [rsi]若触发实际 memory 访问且 L3 miss,也可能记录
特殊指令取决于是否访问 memory比如 cmp [rdi], eax 也涉及 load

不会采样的指令:

类型原因
L1 或 L2 命中不满足 L3 miss 条件
L3 命中被过滤掉(不设置 l3missonly=0 就不会记录)
非访存指令(ALU、branch、NOP等)不涉及 memory load/store,自然不会触发采样
Instruction fetch(指令本身)ibs_op 是采样 data 操作指令,不关注取指行为

IBS 在每个周期可捕获一条指令的详细微架构信息。设置 l3missonly=1 后:

  • IBS 会观察 micro-op 是否触发了 memory 访问;

  • 如果访问 L3 时没有命中(即发生 L3 miss);

  • 且满足采样周期条件(如 -c 1000000);

  • 则记录该指令样本,包括:

    • 虚拟/物理地址

    • DRAM 延迟(DcMissLat=xxx)

    • 访存类型(load/store)

    • 是否在 NUMA 本地 / 远程

5. 内容解析

5.1. 概览

我们列举其中的一个 sample:

0x17e310 [0x78]: event: 9
.
. ... raw event: size 120 bytes
.  0000:  09 00 00 00 01 40 78 00 26 35 14 81 ff ff ff ff  .....@x.&5......
.  0010:  00 00 00 00 00 00 00 00 7b 16 49 89 e4 6b 00 00  ........{.I..k..
.  0020:  aa 83 01 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
.  0030:  44 00 00 00 ff 0b 00 00 24 f4 07 00 41 05 00 00  D.......$...A...
.  0040:  26 35 14 81 ff ff ff ff 00 02 f7 04 00 00 00 00  &5..............
.  0050:  23 00 00 00 00 00 00 00 a1 00 d7 14 dc 01 00 00  #...............
.  0060:  84 57 3b 7c 9f 89 ff ff 84 57 3b 7c 1f 01 00 00  .W;|.....W;|....
.  0070:  34 35 14 81 ff ff ff ff                          45......        

ibs_op_ctl: 000005410007f424 MaxCnt   1000000 L3MissOnly 1 En 1 Val 1 CntCtl 0=cycles CurCnt      1345
IbsOpRip: ffffffff81143526
ibs_op_data: 0000000004f70200 CompToRetCtr   512 TagToRetCtr  1271 BrnRet 0  RipInvalid 0 BrnFuse 0 Microcode 0
ibs_op_data2: 0000000000000023 RmtNode 0 DataSrc 3=DRAM
ibs_op_data3: 000001dc14d700a1 LdOp 1 StOp 0 DcL1TlbMiss 0 DcL2TlbMiss 0 DcL1TlbHit2M 0 DcL1TlbHit1G 1 DcL2TlbHit2M 0 DcMiss 1 DcMisAcc 0 DcWcMemAcc 0 DcUcMemAcc 0 DcLockedOp 0 DcMissNoMabAlloc 1 DcLinAddrValid 1 DcPhyAddrValid 1 DcL2TlbHit1G 0 L2Miss 1 SwPf 0 OpMemWidth  4 bytes OpDcMissOpenMemReqs  5 DcMissLat   476 TlbRefillLat     0
IbsDCLinAd: ffff899f7c3b5784
IbsDCPhysAd: 0000011f7c3b5784
0 118629299983995 0x17e310 [0x78]: PERF_RECORD_SAMPLE(IP, 0x4001): 0/0: 0xffffffff81143526 period: 1000000 addr: 0
 ... thread: swapper:0
 ...... dso: /proc/kcore

样本结构简要概览:

字段含义
event: 9表示 PERF_RECORD_SAMPLE 类型事件
raw event: size 120 bytes原始样本数据大小
ibs_op_ctlIBS 控制字段:采样周期、是否只采样 L3 miss、当前计数等
IbsOpRip被采样指令的虚拟地址(RIP)
ibs_op_data包含分支、指令完成到 retire 的延迟等
ibs_op_data2数据来源(如 DRAM、本地/远程 node)
ibs_op_data3包括访存类型、是否 miss、是否 locked、延迟等详细信息
IbsDCLinAd访存指令的 virtual address
IbsDCPhysAd访存指令的 physical address
PERF_RECORD_SAMPLE样本事件总结,包括指令地址、触发周期、线程等

接下来进行逐行解析:

5.2. ibs_op_ctl

ibs_op_ctl: 000005410007f424 MaxCnt 1000000 L3MissOnly 1 En 1 Val 1 CntCtl 0=cycles CurCnt 1345

属于控制字段,拆解如下:

位字段含义
MaxCnt = 1000000设置每采样一次需执行的指令数(周期)
L3MissOnly = 1只采样 L3 miss 的访存指令
En = 1采样启用
Val = 1当前样本有效
CurCnt = 1345当前样本指令周期倒数计数(用于调节分布)
CntCtl 0 = cycles使用周期控制采样(而非 retired 指令数)

5.3. IbsOpRip

IbsOpRip: ffffffff81143526

采样到的 指令虚拟地址(RIP)

  • 该例子对应内核空间:ffffffff81xxxxxx,可能是某个内核函数中发生的访存

  • 可用 addr2line -e /boot/vmlinux ffffffff81143526 映射函数名

5.4. ibs_op_data

ibs_op_data: 0000000004f70200 CompToRetCtr 512 TagToRetCtr 1271 BrnRet 0 RipInvalid 0 BrnFuse 0 Microcode 0

字段含义
CompToRetCtr = 512指令完成到 retire 的延迟
TagToRetCtr = 1271分派到 retire 之间的延迟(可能表示 pipeline stall)
BrnRet = 0非分支指令
Microcode = 0非 microcode 执行
RipInvalid = 0RIP 有效

5.5. ibs_op_data2

ibs_op_data2: 0000000000000023 RmtNode 0 DataSrc 3=DRAM

字段含义
RmtNode = 0本地 NUMA node
DataSrc = 3数据来源是 DRAM(常见编码:3=DRAM,4=远程,6=IO 等)

5.6. ibs_op_data3

ibs_op_data3: 000001dc14d700a1 LdOp 1 StOp 0 DcL1TlbMiss 0 DcL2TlbMiss 0 DcL1TlbHit2M 0 DcL1TlbHit1G 1 DcL2TlbHit2M 0 DcMiss 1 DcMisAcc 0 DcWcMemAcc 0 DcUcMemAcc 0 DcLockedOp 0 DcMissNoMabAlloc 1 DcLinAddrValid 1 DcPhyAddrValid 1 DcL2TlbHit1G 0 L2Miss 1 SwPf 0 OpMemWidth 4 bytes OpDcMissOpenMemReqs 5 DcMissLat 476 TlbRefillLat 0

这是最关键的字段之一,包含了 memory 延迟与 miss 类型,逐项如下:

字段含义
LdOp = 1是 load 指令
StOp = 0非 store 指令
DcMiss = 1数据 cache miss
L2Miss = 1L2 miss
==DcMissLat = 476==内存访问延迟为 476 cycles(重点)
OpMemWidth = 4操作内存宽度为 4 字节
OpDcMissOpenMemReqs = 5此时 memory pipeline 有 5 个 outstanding 请求
DcLockedOp = 0非锁操作
DcLinAddrValid = 1 / DcPhyAddrValid = 1地址有效
TlbRefillLat = 0没有 TLB refill latency
DcL1TlbMiss = 0 / DcL2TlbMiss = 0没有 TLB miss

5.7. IbsDCLinAd / IbsDCPhysAd

IbsDCLinAd: ffff899f7c3b5784 IbsDCPhysAd: 0000011f7c3b5784

字段含义
IbsDCLinAd = ffff899f7c3b5784访存虚拟地址
IbsDCPhysAd = 0000011f7c3b5784映射物理地址(可结合页表分析内存 node)

5.8. PERF_RECORD_SAMPLE(IP…)

0 118629299983995 0x17e310 [0x78]: PERF_RECORD_SAMPLE(IP, 0x4001): 0/0: 0xffffffff81143526 period: 1000000 addr: 0 … thread: swapper

… dso: /proc/kcore

这是 perf 报告格式,概括该采样点:

  • PERF_RECORD_SAMPLE(IP, 0x4001):采样事件,包含指令地址

  • thread: swapper

    :发生于 idle thread

  • dso: /proc/kcore:说明是在内核执行过程中被采样(非用户态)

6. 监控使能

对于在日常监控中使能 IBS 并且监控 DcMissLat 指标,有两种方式,分别是使用 perf_event_open + raw IBS 事件和 MSR 直接访问。

6.1. 使用 perf_event_open + raw IBS 事件

Linux 的 perf 子系统支持 IBS 的硬件事件,通过 perf_event_open() 系统调用直接启用 ibs_op 类型事件,然后从 ring buffer 中读取采样样本,包括 DcMissLat。

目前正在咨询 ARM Light Spe 是如何实现监控的,将来可以作为参考。

下面是我列举的一个 demo,用于调用接口:

打开 perf_event_open 配置 ibs_op:

#include <linux/perf_event.h>
#include <asm/unistd.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

int fd;
struct perf_event_attr attr;

memset(&attr, 0, sizeof(struct perf_event_attr));
attr.type = PERF_TYPE_RAW;   // 对于 IBS,用 RAW 类型
attr.size = sizeof(struct perf_event_attr);
attr.config = 0x1;           // 0x1 = IBS_OP(ibs_op 控制器)
attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_RAW;
attr.sample_period = 1000000;
attr.exclude_kernel = 0;
attr.exclude_user = 0;
attr.disabled = 0;
attr.read_format = 0;

fd = syscall(__NR_perf_event_open, &attr, 0, -1, -1, 0);

读取 ring buffer 中的采样样本,需要 mmap 一个 ring buffer,然后循环从中读取:

void* buf = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
// 解析 perf_event_header,并从中获取 raw sample 中的 DcMissLat

raw sample 是个结构体,DcMissLat 在 ibs_op_data3 字段里,需要解析其中的 bit field:DcMissLat = (ibs_op_data3 >> 32) & 0xFFFF

6.2. MSR 直接访问

可以访问 IBS 的硬件 MSR(model specific registers)来启用采样:

名称编号说明
IBS_OP_CTL0xC0011033控制器寄存器
IBS_OP_DATA30xC001103B包含 DcMissLat 等信息
IBS_OP_RIP0xC0011035指令地址
IBS_OP_DATA0xC0011036执行状态

可以通过 rdmsr_on_cpu() + 定时中断轮询方式采集,但这种方法依赖内核权限。

修改历史7 次提交