IMC (In-Memory Collection Counters)

Anju T Sudhakar,2019年5月10日

基本概述

IMC(In-Memory Collection Counters,内存收集计数器)是一种硬件监控设施,可在 Nest 级别(芯片内但核心外)、Core(核心)级别和 Thread(线程)级别收集大量的硬件性能事件。

Nest PMU 计数器由运行在 OCC(On-Chip Controller,芯片内控制器)复合体中的 Nest IMC 微代码处理。该微代码收集计数器数据,并将 Nest IMC 计数器数据移动到内存中。

Core 和 Thread IMC PMU 计数器在核心中处理。Core 级别的 PMU 计数器提供每个核心的 IMC 计数器数据,而 Thread 级别的 PMU 计数器提供每个 CPU 线程的 IMC 计数器数据。

OPAL 从 IMC 目录(IMC Catalog)获取 IMC PMU 及支持的事件信息,并通过设备树(device tree)传递给内核。事件信息包含:

  • 事件名称

  • 事件偏移量

  • 事件描述

以及可能包含的

  • 事件缩放因子

  • 事件单位

某些 PMU 的所有支持事件可能具有共同的缩放和单位值。对于这些情况,这些事件的缩放和单位属性必须从 PMU 继承。

内存中的事件偏移量是累积计数器数据的地方。

IMC 目录可在以下网址找到:

https://github.com/open-power/ima-catalog

内核在设备树的 imc-counters 设备节点中发现 IMC 计数器信息,该节点具有兼容字段 ibm,opal-in-memory-counters。内核从设备树中解析 PMU 及其事件信息,并在内核中注册 PMU 及其属性。

IMC 示例用法

# perf list
[...]
nest_mcs01/PM_MCS01_64B_RD_DISP_PORT01/            [Kernel PMU event]
nest_mcs01/PM_MCS01_64B_RD_DISP_PORT23/            [Kernel PMU event]
[...]
core_imc/CPM_0THRD_NON_IDLE_PCYC/                  [Kernel PMU event]
core_imc/CPM_1THRD_NON_IDLE_INST/                  [Kernel PMU event]
[...]
thread_imc/CPM_0THRD_NON_IDLE_PCYC/                [Kernel PMU event]
thread_imc/CPM_1THRD_NON_IDLE_INST/                [Kernel PMU event]

要查看 nest_mcs0/PM_MCS_DOWN_128B_DATA_XFER_MC0/ 的每个芯片数据:

# ./perf stat -e "nest_mcs01/PM_MCS01_64B_WR_DISP_PORT01/" -a --per-socket

要查看核心 0 的非空闲指令:

# ./perf stat -e "core_imc/CPM_NON_IDLE_INST/" -C 0 -I 1000

要查看执行 “make” 时的非空闲指令:

# ./perf stat -e "thread_imc/CPM_NON_IDLE_PCYC/" make

IMC 追踪模式

POWER9 支持 IMC 的两种模式:累积模式(Accumulation mode)和追踪模式(Trace mode)。在累积模式下,事件计数在系统内存中累积。然后,Hypervisor(虚拟机监控程序)会定期或在请求时读取发布的计数。在 IMC 追踪模式下,64 位追踪 SCOM 值使用事件信息进行初始化。追踪 SCOM 中的 CPMCxSEL 和 CPMC_LOAD 指定了要监控的事件和采样持续时间。在 CPMCxSEL 发生每次溢出时,硬件会对程序计数器连同事件计数一起进行快照,并写入由 LDBAR 指向的内存中。

LDBAR 是一个 64 位的专用每个线程寄存器,它具有指示硬件配置为累积模式还是追踪模式的位。

LDBAR 寄存器布局

0

启用/禁用

1

0:累积模式

1:追踪模式

2:3

保留

4-6

PB 范围

7

保留

8:50

计数器地址

51:63

保留

TRACE_IMC_SCOM 位表示

0:1

SAMPSEL

2:33

CPMC_LOAD

34:40

CPMC1SEL

41:47

CPMC2SEL

48:50

BUFFERSIZE

51:63

RESERVED

CPMC_LOAD 包含采样持续时间。SAMPSEL 和 CPMCxSEL 决定要计数的事件。BUFFERSIZE 指示内存范围。在每次溢出时,硬件会对程序计数器及事件计数进行快照,更新内存并为下一个采样持续时间重新加载 CMPC_LOAD 值。IMC 硬件不支持异常,因此如果内存缓冲区到达末尾,它会静默回绕。

目前,为追踪模式监控的事件固定为 cycle(周期)。

追踪 IMC 示例用法

# perf list
[....]
trace_imc/trace_cycles/                            [Kernel PMU event]

使用 trace-imc 事件记录应用程序/进程

# perf record -e trace_imc/trace_cycles/ yes > /dev/null
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.012 MB perf.data (21 samples) ]

生成的 perf.data 可以使用 perf report 读取。

使用 IMC 追踪模式的好处

避免了 PMI(Performance Monitoring Interrupts,性能监视中断)中断处理,因为 IMC 追踪模式会对程序计数器进行快照并更新到内存中。这也为操作系统提供了一种在没有 PMI 处理开销的情况下实时进行指令采样的方法。

使用和不使用 trace-imc 事件时的 perf top 性能数据。

未执行 trace-imc 事件而执行 perf top 命令时的 PMI 中断计数。

# grep PMI /proc/interrupts
PMI:          0          0          0          0   Performance monitoring interrupts
# ./perf top
...
# grep PMI /proc/interrupts
PMI:      39735       8710      17338      17801   Performance monitoring interrupts
# ./perf top -e trace_imc/trace_cycles/
...
# grep PMI /proc/interrupts
PMI:      39735       8710      17338      17801   Performance monitoring interrupts

也就是说,在使用 trace_imc 事件时,PMI 中断计数不会增加。