【笔记】AMD IBS 使用笔记
实验需求使用 perf_event_open 调用 AMD IBS 实现对于线程访存的监控,因此开始了解一下 IBS。
AMD IBS(Instruction-Based Sampling,基于指令采样)是 AMD 处理器中一项硬件级性能分析技术,用于监控和记录处理器执行的指令流,为开发者和系统管理员提供细粒度的性能洞察。
IBS 文档:https://www.amd.com/content/dam/amd/en/documents/archived-tech-docs/white-papers/AMD_IBS_paper_EN.pdf (没什么有用的内容)
IBS 采样结构体内容详见:https://www.weigao.cc/architecture/ibs.html#_1-ibs
调用方式
perf_event_open() + raw IBS
Linux 集成的 perf 子系统支持 IBS 事件,可以使用 perf_event_open()
syscall 直接采集 ibs_op 类型事件,然后 mmap 一个 ring buffer 直接读取采样样本。
注意 mmap 的 buffer 大小必须是 $ 1 + 2^n $ 个 page,否则会 failed。
以及一定要先检查内核编译时是否支持 ibs,如果不支持 ibs ,perf_event_open() 不会读取到任何内容也不会报错,需要更换一个支持 ibs 的内核。这导致我浪费了两天时间排查 raw data 的解码问题。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <linux/perf_event.h>
#include <asm/unistd.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
long page_size = sysconf(_SC_PAGESIZE);
int mmap_pages = 9; // ring buffer 大小必须是 1+2^n 页
size_t mmap_size = page_size * mmap_pages;
int fd;
struct perf_event_attr attr;
void init_ibs_perf() {
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;
}
void read_ibs_perf() {
fd = syscall(__NR_perf_event_open, &attr, 0, -1, -1, 0);
if (fd < 0) {
perror("perf_event_open failed");
return;
}
void* buf = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (buf == MAP_FAILED) {
perror("mmap failed");
close(fd);
fd = -1;
return;
}
printf("成功打开IBS性能监控,开始读取数据...\n");
printf_ibs_perf(fd, buf, mmap_size);
// 清理mmap
munmap(buf, mmap_size);
}
MSR 寄存器直接访问
可以直接访问 IBS 的寄存器来启用采样读取数据。
名称 | 编号 | 说明 |
---|---|---|
IBS_OP_CTL | 0xC0011033 | 控制器寄存器 |
IBS_OP_DATA3 | 0xC001103B | 包含 DcMissLat 等信息 |
IBS_OP_RIP | 0xC0011035 | 指令地址 |
IBS_OP_DATA | 0xC0011036 | 执行状态 |
可以通过 rdmsr_on_cpu() + 定时中断轮询方式采集,但这种方法依赖内核权限。
AMD IBS Toolkit
AMD 编写了针对应用场景的 IBS Toolkit,可以尝试直接使用,我没有深入研究。
https://github.com/jlgreathouse/AMD_IBS_Toolkit