Ori*_*kis 5 multiplexing perf intel-pmu
我正在perf_event_opensyscall之上进行自定义实现。
实施旨在支持各种的PERF_TYPE_HARDWARE,PERF_TYPE_SOFTWARE和PERF_TYPE_HW_CACHE事件上的任何核心特定的线程。
在英特尔® 64 位和 IA-32 架构软件开发人员手册第 3B 卷中,我看到以下用于测试 CPU (Kaby Lake) 的内容:
到目前为止,我的理解是,可以同时监视(理论上)无限的PERF_TYPE_SOFTWARE事件,但同时监视有限的(没有多路复用)PERF_TYPE_HARDWARE和PERF_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),
Run Code Online (Sandbox Code Playgroud)
所有这些都使用提供的公式实现:
(perf_hw_cache_id) | (perf_hw_cache_op_id << 8) |
(perf_hw_cache_op_result_id << 16)
Run Code Online (Sandbox Code Playgroud)
并且作为一个群体被操纵(第一个是组长等)。
所以,我的问题如下:
PERF_TYPE_HARDWARE哪些PERF_TYPE_HW_CACHE事件以及在哪里可以找到这些信息?PERF_TYPE_HARDWARE预定义事件(例如PERF_COUNT_HW_CACHE_MISSES)和PERF_TYPE_HW_CACHE事件之间有什么区别?PERF_TYPE_HW_CACHE事件的情况下进行监控的任何建议?PERF_TYPE_HARDWARE或/和PERF_TYPE_HW_CACHE事件的情况下进行监控的任何建议?提前致谢!
PERF_TYPE_HARDWARE映射PERF_TYPE_HW_CACHE到涉及性能监控的两组寄存器。调用第一组 MSR,IA32_PERFEVTSELx其中 x 可以从 0 到 N-1 变化,N 是可用通用计数器的总数。这PERFEVTSEL是“性能事件选择”的缩写,它们指定了发生事件计数的各种条件。第二组 MSR 称为IA32_PMCx,其中 x 的变化与 类似PERFEVTSEL。这些 PMC 寄存器存储性能监控事件的计数。每个PERFEVTSEL寄存器都与相应的寄存器配对PMC。映射发生如下 -
在内核的体系结构特定部分初始化时,用于测量硬件特定事件的 pmu在此注册为类型PERF_TYPE_RAW。所有PERF_TYPE_HARDWARE和PERF_TYPE_HW_CACHE事件都映射到PERF_TYPE_RAW事件以识别 pmu,如此处所示。
if (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE)
type = PERF_TYPE_RAW;
Run Code Online (Sandbox Code Playgroud)
相同架构特定的初始化负责设置上述每组性能监控事件寄存器的首/基寄存器的地址,这里
.eventsel = MSR_ARCH_PERFMON_EVENTSEL0,
.perfctr = MSR_ARCH_PERFMON_PERFCTR0,
Run Code Online (Sandbox Code Playgroud)
所识别的 PMU 特定功能event_init负责设置和“保留”两组性能监控寄存器,以及检查事件约束等。预订在这里进行。
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;
}
Run Code Online (Sandbox Code Playgroud)
该值num_counters= 由指令标识的通用计数器的数量CPUID。
除此之外,还有一些额外的寄存器用于监视非核心事件(例如 LLC 缓存特定事件)。
在架构性能监控的更高版本中,一些硬件事件是在固定用途寄存器的帮助下测量的,如此处所示。这些是固定用途寄存器-
#define MSR_ARCH_PERFMON_FIXED_CTR0 0x309
#define MSR_ARCH_PERFMON_FIXED_CTR1 0x30a
#define MSR_ARCH_PERFMON_FIXED_CTR2 0x30b
Run Code Online (Sandbox Code Playgroud)
PERF_TYPE_HARDWARE预先定义的事件都是架构性能监控事件。这些事件是架构性的,因为每个架构性能事件的行为预计在支持该事件的所有处理器上保持一致。所有PERF_TYPE_HW_CACHE事件都是非体系结构的,这意味着它们是特定于模型的,并且可能因处理器系列而异。
对于我拥有的 Intel Kaby Lake 机器,总共PERF_TYPE_HW_CACHE预定义了 20 个事件。涉及的事件约束,确保 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。它可以通过名为 的 sysfs 条目进行配置/sys/devices/cpu/perf_event_mux_interval_ms。该值不能降低到某个点以上,如此处所示。
CPUID指令检索的,并且此类计数器的数量是通过该函数在内核启动的体系结构初始化部分设置的early_initcall。这可以在这里看到。初始化完成后,内核知道只有 4 个计数器可用,以后超线程功能的任何更改都不会产生任何影响。| 归档时间: |
|
| 查看次数: |
306 次 |
| 最近记录: |