PERF_TYPE_HARDWARE 和 PERF_TYPE_HW_CACHE 并发监控

Posted

技术标签:

【中文标题】PERF_TYPE_HARDWARE 和 PERF_TYPE_HW_CACHE 并发监控【英文标题】:PERF_TYPE_HARDWARE and PERF_TYPE_HW_CACHE concurrent monitoring 【发布时间】:2020-09-04 19:41:06 【问题描述】:

我正在perf_event_open syscall 之上进行自定义实现。

该实现旨在为任何内核上的特定线程支持各种PERF_TYPE_HARDWAREPERF_TYPE_SOFTWAREPERF_TYPE_HW_CACHE 事件。

英特尔® 64 和 IA-32 架构软件开发人员手册第 3B 卷中,我看到以下测试 CPU(Kaby Lake):

到目前为止,据我了解,可以同时监控(理论上)无限的 PERF_TYPE_SOFTWARE 事件,但同时监控有限的(没有多路复用)PERF_TYPE_HARDWAREPERF_TYPE_HW_CACHE 事件,因为每个事件都是由有限的(如可以在上面的手册)CPU的PMU的计数器数量。

因此,对于启用了超线程的四核 Kaby Lake CPU,我假设最多可以同时监视 4 个 PERF_TYPE_HARDWARE/PERF_TYPE_HW_CACHE 事件(如果只使用 4 个线程,则最多可以监视 8 个)。

用上述假设进行实验后,我发现虽然我可以成功监控多达 4 个 PERF_TYPE_HARDWARE 事件(对于 8 个线程),但 PERF_TYPE_HW_CACHE 事件并非如此,因为它最多只能同时监控 2 个事件!

我也尝试只使用 4 个线程,但同时监控的“PERF_TYPE_HARDWARE”事件的上限仍然是 4。超线程禁用也是如此!

有人可能会问:为什么需要避免多路复用。首先,实现需要尽可能准确,避免多路复用的潜在盲点,其次,当超过“上限”时,所有事件值都为 0...

我要定位的PERF_TYPE_HW_CACHE 事件是:

CACHE_LLC_READ(PERF_HW_CACHE_TYPE_ID.PERF_COUNT_HW_CACHE_LL.value  | PERF_HW_CACHE_OP_ID.PERF_COUNT_HW_CACHE_OP_READ.value << 8 | PERF_HW_CACHE_OP_RESULT_ID.PERF_COUNT_HW_CACHE_RESULT_ACCESS.value << 16),
CACHE_LLC_WRITE(PERF_HW_CACHE_TYPE_ID.PERF_COUNT_HW_CACHE_LL.value  | PERF_HW_CACHE_OP_ID.PERF_COUNT_HW_CACHE_OP_WRITE.value << 8 | PERF_HW_CACHE_OP_RESULT_ID.PERF_COUNT_HW_CACHE_RESULT_ACCESS.value << 16),
CACHE_LLC_READ_MISS(PERF_HW_CACHE_TYPE_ID.PERF_COUNT_HW_CACHE_LL.value  | PERF_HW_CACHE_OP_ID.PERF_COUNT_HW_CACHE_OP_READ.value << 8 | PERF_HW_CACHE_OP_RESULT_ID.PERF_COUNT_HW_CACHE_RESULT_MISS.value << 16),
CACHE_LLC_WRITE_MISS(PERF_HW_CACHE_TYPE_ID.PERF_COUNT_HW_CACHE_LL.value  | PERF_HW_CACHE_OP_ID.PERF_COUNT_HW_CACHE_OP_WRITE.value << 8 | PERF_HW_CACHE_OP_RESULT_ID.PERF_COUNT_HW_CACHE_RESULT_MISS.value << 16),

所有都使用提供的公式实现:

(perf_hw_cache_id) | (perf_hw_cache_op_id << 8) |
(perf_hw_cache_op_result_id << 16)

并作为一个群体被操纵(第一个是组长等)。

所以,我的问题如下:

    PMU 的哪些计数器用于PERF_TYPE_HARDWARE,哪些用于PERF_TYPE_HW_CACHE 事件,我在哪里可以找到这些信息? PERF_TYPE_HARDWARE 预定义事件(如PERF_COUNT_HW_CACHE_MISSES)和PERF_TYPE_HW_CACHE 事件有什么区别? 关于如何在不复用所有列出的PERF_TYPE_HW_CACHE 事件的情况下进行监控有什么建议吗? 关于如何在不复用多达 8 个PERF_TYPE_HARDWARE 或/和PERF_TYPE_HW_CACHE 事件的情况下进行监控有什么建议吗?

提前致谢!

【问题讨论】:

【参考方案1】:
    PERF_TYPE_HARDWAREPERF_TYPE_HW_CACHE 事件映射到与性能监控相关的两组寄存器。第一组 MSR 称为IA32_PERFEVTSELx,其中 x 可以在 0 到 N-1 之间变化,N 是可用的通用计数器的总数。 PERFEVTSEL 是“性能事件选择”的缩写,它们指定了执行事件计数的各种条件。第二组 MSR 称为 IA32_PMCx,其中 x 的变化与 PERFEVTSEL 类似。这些 PMC 寄存器存储性能监控事件的计数。每个PERFEVTSEL 寄存器都与对应的PMC 寄存器配对。

映射发生如下-

在内核的体系结构特定部分初始化时,一个用于测量硬件特定事件的 pmu 被注册为here,类型为PERF_TYPE_RAW。所有PERF_TYPE_HARDWAREPERF_TYPE_HW_CACHE 事件都映射到PERF_TYPE_RAW 事件以识别pmu,如here 所示。

if (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE)
        type = PERF_TYPE_RAW;

相同的架构特定初始化负责设置上述每组性能监控事件寄存器here的第一个/基址寄存器的地址

    .eventsel       = MSR_ARCH_PERFMON_EVENTSEL0,
    .perfctr        = MSR_ARCH_PERFMON_PERFCTR0,

event_init 函数特定于 PMU 识别,负责设置和“保留”两组性能监控寄存器,以及检查事件约束等,here。预订发生在here。

for (i = 0; i < x86_pmu.num_counters; i++) 
        if (!reserve_perfctr_nmi(x86_pmu_event_addr(i)))
            goto perfctr_fail;
    

    for (i = 0; i < x86_pmu.num_counters; i++) 
        if (!reserve_evntsel_nmi(x86_pmu_config_addr(i)))
            goto eventsel_fail;
    

num_counters = 由CPUID 指令标识的通用计数器的数量。

除此之外,还有几个额外的registers 用于监控核心外事件(例如,LLC 缓存特定事件)。

在更高版本的架构性能监控中,一些硬件事件是在固定用途寄存器的帮助下测量的,如 here 所示。这些是固定用途的registers -

#define MSR_ARCH_PERFMON_FIXED_CTR0 0x309
#define MSR_ARCH_PERFMON_FIXED_CTR1 0x30a
#define MSR_ARCH_PERFMON_FIXED_CTR2 0x30b

    PERF_TYPE_HARDWARE 预定义的events 都是架构 性能监控事件。这些事件是体系结构的,因为每个体系结构性能事件的行为预计在支持该事件的所有处理器上都是一致的。所有PERF_TYPE_HW_CACHE 事件都是非架构性的,这意味着它们是特定于模型的,并且可能因处理器系列而异。

    对于我拥有的 Intel Kaby Lake 机器,总共预定义了 20 个PERF_TYPE_HW_CACHE 事件。事件约束involved,确保3 个可用的固定功能计数器映射到3 个PERF_TYPE_HARDWARE 架构事件。每个固定功能计数器只能测量一个事件,因此我们可以丢弃它们进行分析。另一个限制是只能同时测量两个针对 LLC 缓存的事件,因为只有两个 OFFCORE RESPONSE 寄存器。此外,nmi-watchdog 可以将事件固定到通用计数器系列中的另一个计数器。如果 nmi-watchdog 被禁用,我们将剩下 4 个通用计数器。

鉴于所涉及的约束以及可用计数器的数量有限,如果同时测量所有 20 个硬件缓存事件,则无法避免多路复用。测量所有事件的一些解决方法,不会导致多路复用及其错误,是 -

3.1。将所有PERF_TYPE_HW_CACHE 事件分成 4 个一组,这样所有 4 个事件都可以同时安排在 4 个通用计数器中的每一个上。确保组中的 LLC 缓存事件不超过 2 个。运行相同的配置文件并分别获取每个组的计数。

3.2。如果要同时监视所有PERF_TYPE_HW_CACHE 事件,则可以通过减小perf_event_mux_interval_ms 的值来减少多路复用的一些错误。它可以通过名为/sys/devices/cpu/perf_event_mux_interval_ms 的sysfs 条目进行配置。这个值不能降低超过一个点,可以看到here。

    监控多达 8 个硬件或硬件缓存事件需要禁用超线程。请注意,有关可用通用计数器数量的信息是使用CPUID 指令检索的,并且此类计数器的数量是在内核启动的体系结构初始化部分通过early_initcall 函数设置的。这可以看到here。一旦初始化完成,内核就知道只有 4 个计数器可用,以后对超线程能力的任何更改都不会产生任何影响。

【讨论】:

惊人的答案@Arnabjyoti Kalita!您阐明了完全没有记录的性能方面。谢谢!

以上是关于PERF_TYPE_HARDWARE 和 PERF_TYPE_HW_CACHE 并发监控的主要内容,如果未能解决你的问题,请参考以下文章

开发工具perf性能分析工具perf的编译和使用说明

开发工具perf性能分析工具perf的编译和使用说明

开发工具perf性能分析工具perf的编译和使用说明

读取和解析 perf.data

如何分析 perf sched 脚本和 perf sched 延迟?

perf 报告函数名称和额外字符