性能事件组中只有 2 个PERF_TYPE_HW_CACHE事件



在自定义实现之上工作perf_event_open我需要同时监视多个PERF_TYPE_HW_CACHE

英特尔手册指出,对于我的 CPU 架构,每个线程有 4 个可编程计数器(如果禁用超线程,则为 8 个(。因此,我将选择的PERF_TYPE_HW_CACHE事件分组为包含 4 个事件 (LLC_GROUPPERF_TYPE_HW_CACHE的 1 个性能事件组

。我运行了第一个实验,得到了以下结果:

LLC_GROUP of thread 2 | time Enabled: 3190370379, time Running: 3017
HW_CACHE_LLC_READ_MISSES = 0
HW_CACHE_LLC_WRITE_MISSES = 0
HW_CACHE_LLC_READS = 0
HW_CACHE_LLC_WRITES = 0

从上述结果可以看出,PMU 并没有"适合"所有 4 个事件。我们还观察到一种"奇怪"的多路复用,没有实际结果。

因此,作为下一步,我将 4 个事件组分成 2 组,每组 2 个事件/组(LLC_GROUPLLC2_GROUP(,我得到的结果如下:

LLC_GROUP of thread 2 | time Enabled: 2772569406, time Running: 1396022331
HW_CACHE_LLC_READ_MISSES = 102117
HW_CACHE_LLC_WRITE_MISSES = 9624295
LLC2_GROUP of thread 2 | time Enabled: 2772571024, time Running: 1376575096
HW_CACHE_LLC_READS = 22020658
HW_CACHE_LLC_WRITES = 18156060

通过这种配置,我们再次观察到PMU不能同时"适合"4PERF_TYPE_HW_CACHE,但这次(预期的(多路复用正在发生。

有人有任何解释吗?

这种行为对我来说看起来很奇怪,因为我能够在不多路复用的情况下监控多个PERF_TYPE_HARDWARE事件(最多 6 个(,我希望PERF_TYPE_HW_CACHE事件也会发生同样的情况。

请注意,perf允许同时测量 2 个以上的PERF_TYPE_HW_CACHE事件,但测量LLC-cache事件除外。

期望是,当有 4 个通用和 3 个固定用途时 硬件计数器,4 个硬件缓存事件(默认为RAW个事件(在 perf 中可以在不多路复用的情况下测量,超线程打开

sudo perf stat -e L1-icache-load-misses,L1-dcache-stores,L1-dcache-load-misses,dTLB-load-misses sleep 2
Performance counter stats for 'sleep 2':
26,893      L1-icache-load-misses                                       
98,999      L1-dcache-stores                                            
14,037      L1-dcache-load-misses                                       
723      dTLB-load-misses                                            
2.001732771 seconds time elapsed
0.001217000 seconds user
0.000000000 seconds sys

当您尝试测量针对LLC-cache的事件时,会出现此问题。它似乎只同时测量 2 个LLC-cache特定事件,没有多路复用。

sudo perf stat -e LLC-load-misses,LLC-stores,LLC-store-misses,LLC-loads sleep 2
Performance counter stats for 'sleep 2':
2,419      LLC-load-misses           #    0.00% of all LL-cache hits   
2,963      LLC-stores                                                  
<not counted>      LLC-store-misses                                              (0.00%)
<not counted>      LLC-loads                                                     (0.00%)
2.001486710 seconds time elapsed
0.001137000 seconds user
0.000000000 seconds sys

属于skylake/kaby lake系列微体系结构和其他一些 CPU 允许您测量OFFCORE RESPONSE事件。监控OFFCORE_RESPONSE事件需要对额外的 MSR 进行编程,特别是MSR_OFFCORE_RSP0(MSR 地址 1A6H(和MSR_OFFCORE_RSP1(MSR 地址 1A7H(,此外还需要对IA32_PERFEVTSELxIA32_PMCx寄存器进行编程。

每对IA32_PERFEVTSELxIA32_PMCx寄存器将与上述MSR之一相关联,以测量LLC缓存事件。

可以在此处查看OFFCORE_RESPONSEMSR 的定义。

static struct extra_reg intel_skl_extra_regs[] __read_mostly = {
INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0x3fffff8fffull, RSP_0),
INTEL_UEVENT_EXTRA_REG(0x01bb, MSR_OFFCORE_RSP_1, 0x3fffff8fffull, RSP_1),
........
}

INTEL_UEVENT_EXTRA_REG调用中的0x01b7是指事件代码b7和掩码01。此事件代码0x01b7映射到 LLC 缓存事件,如下所示 -

[ C(LL  ) ] = {
[ C(OP_READ) ] = {
[ C(RESULT_ACCESS) ] = 0x1b7,   /* OFFCORE_RESPONSE */
[ C(RESULT_MISS)   ] = 0x1b7,   /* OFFCORE_RESPONSE */
},
[ C(OP_WRITE) ] = {
[ C(RESULT_ACCESS) ] = 0x1b7,   /* OFFCORE_RESPONSE */
[ C(RESULT_MISS)   ] = 0x1b7,   /* OFFCORE_RESPONSE */
},
[ C(OP_PREFETCH) ] = {
[ C(RESULT_ACCESS) ] = 0x0,
[ C(RESULT_MISS)   ] = 0x0,
},
},

事件0x01b7将始终映射到MSR_OFFCORE_RSP_0,如此处所示。上面指定的函数遍历所有"额外寄存器"的数组,并将事件>配置(包含原始事件 ID(与非核响应 MSR 相关联。

因此,这意味着一次只能测量一个事件,因为只能将一个 MSR -MSR_OFFCORE_RSP_0映射到LLC-cache事件。但是,事实并非如此!

离核寄存器本质上是对称的,因此当第一个 MSR -MSR_OFFCORE_RSP_0寄存器繁忙时,perf使用第二个替代 MSR,MSR_OFFCORE_RSP_1测量另一个离核 LLC 事件。这里的这个函数有助于做到这一点。

static int intel_alt_er(int idx, u64 config)
{
int alt_idx = idx;
if (!(x86_pmu.flags & PMU_FL_HAS_RSP_1))
return idx;
if (idx == EXTRA_REG_RSP_0)
alt_idx = EXTRA_REG_RSP_1;
if (idx == EXTRA_REG_RSP_1)
alt_idx = EXTRA_REG_RSP_0;
if (config & ~x86_pmu.extra_regs[alt_idx].valid_mask)
return idx;
return alt_idx;
}

对于Kaby-Lake系列微架构来说,只有 2 个离核寄存器,阻碍了同时针对 2 个以上 LLC 缓存事件测量的能力,而无需任何多路复用。

相关内容

  • 没有找到相关文章

最新更新