性能事件组中只有 2 PERF_TYPE_HW_CACHE 个事件
only 2 PERF_TYPE_HW_CACHE events in perf event group
在 perf_event_open
之上进行自定义实施,我需要同时监控多个 PERF_TYPE_HW_CACHE
。
英特尔手册指出,对于我的 CPU 体系结构,每个线程有 4 个可编程计数器(如果禁用超线程,则为 8 个)。所以我将选择的 PERF_TYPE_HW_CACHE
事件分组为 1 个性能事件组,其中包含 PERF_TYPE_HW_CACHE
4 个事件 (LLC_GROUP
).
我 运行 进行了第一个实验,得到了以下结果:
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 并没有"fit" 所有的 4 个事件。我们还观察到 "strange" 多路复用,但没有实际结果..
因此,下一步,我将 4 事件组分成 2 组,每组 2 events/group(LLC_GROUP
、LLC2_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 没有同时 "fit" 4 PERF_TYPE_HW_CACHE
,但这次发生了(预期的)多路复用。
有没有人解释一下?
这种行为对我来说看起来很奇怪,因为我能够监视多个 PERF_TYPE_HARDWARE
事件(最多 6 个)而无需多路复用,我希望 PERF_TYPE_HW_CACHE
事件也会发生同样的情况还有。
请注意,perf
允许同时测量 2 个以上的 PERF_TYPE_HW_CACHE 事件,但测量 LLC-cache
个事件除外。
预期是,当有 4 个通用和 3 个固定用途时
硬件计数器,perf 中的 4 个 HW 缓存事件(默认为 RAW
事件)可以在没有多路复用的情况下测量, 超线程开启 。
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
CPU 属于 skylake/kaby lake
微体系结构家族和其他一些,允许您测量 OFFCORE RESPONSE
事件。监视 OFFCORE_RESPONSE
事件需要编程额外的 MSR,具体来说,MSR_OFFCORE_RSP0
(MSR 地址 1A6H)和 MSR_OFFCORE_RSP1
(MSR 地址 1A7H),此外还需要对 IA32_PERFEVTSELx
和 IA32_PMCx
注册。
每对 IA32_PERFEVTSELx
和 IA32_PMCx
寄存器将与上述 MSR 之一相关联,以测量 LLC 缓存事件。
可以看到OFFCORE_RESPONSE
个MSR的定义here。
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),
........
}
0x01b7
在 INTEL_UEVENT_EXTRA_REG
调用中指的是事件代码 b7
和 umask 01
。这个事件代码0x01b7
映射到LLC-cache事件,可以看出here-
[ 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
,如 here 所示。上面指定的函数循环遍历所有 "extra registers" 的数组,并将 event->config(包含原始事件 ID)与 offcore 响应 MSR 相关联。
因此,这意味着一次只能测量一个事件,因为只有一个 MSR - MSR_OFFCORE_RSP_0
可以映射到 LLC-cache
事件。但是,事实并非如此!
offcore 寄存器本质上是对称的,因此当第一个 MSR - MSR_OFFCORE_RSP_0
寄存器忙时,perf
使用第二个替代 MSR,MSR_OFFCORE_RSP_1
用于测量另一个 offcore LLC 事件.这个函数 here 有助于做到这一点。
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 缓存事件测量的能力。
在 perf_event_open
之上进行自定义实施,我需要同时监控多个 PERF_TYPE_HW_CACHE
。
英特尔手册指出,对于我的 CPU 体系结构,每个线程有 4 个可编程计数器(如果禁用超线程,则为 8 个)。所以我将选择的 PERF_TYPE_HW_CACHE
事件分组为 1 个性能事件组,其中包含 PERF_TYPE_HW_CACHE
4 个事件 (LLC_GROUP
).
我 运行 进行了第一个实验,得到了以下结果:
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 并没有"fit" 所有的 4 个事件。我们还观察到 "strange" 多路复用,但没有实际结果..
因此,下一步,我将 4 事件组分成 2 组,每组 2 events/group(LLC_GROUP
、LLC2_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 没有同时 "fit" 4 PERF_TYPE_HW_CACHE
,但这次发生了(预期的)多路复用。
有没有人解释一下?
这种行为对我来说看起来很奇怪,因为我能够监视多个 PERF_TYPE_HARDWARE
事件(最多 6 个)而无需多路复用,我希望 PERF_TYPE_HW_CACHE
事件也会发生同样的情况还有。
请注意,perf
允许同时测量 2 个以上的 PERF_TYPE_HW_CACHE 事件,但测量 LLC-cache
个事件除外。
预期是,当有 4 个通用和 3 个固定用途时
硬件计数器,perf 中的 4 个 HW 缓存事件(默认为 RAW
事件)可以在没有多路复用的情况下测量, 超线程开启 。
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
CPU 属于 skylake/kaby lake
微体系结构家族和其他一些,允许您测量 OFFCORE RESPONSE
事件。监视 OFFCORE_RESPONSE
事件需要编程额外的 MSR,具体来说,MSR_OFFCORE_RSP0
(MSR 地址 1A6H)和 MSR_OFFCORE_RSP1
(MSR 地址 1A7H),此外还需要对 IA32_PERFEVTSELx
和 IA32_PMCx
注册。
每对 IA32_PERFEVTSELx
和 IA32_PMCx
寄存器将与上述 MSR 之一相关联,以测量 LLC 缓存事件。
可以看到OFFCORE_RESPONSE
个MSR的定义here。
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),
........
}
0x01b7
在 INTEL_UEVENT_EXTRA_REG
调用中指的是事件代码 b7
和 umask 01
。这个事件代码0x01b7
映射到LLC-cache事件,可以看出here-
[ 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
,如 here 所示。上面指定的函数循环遍历所有 "extra registers" 的数组,并将 event->config(包含原始事件 ID)与 offcore 响应 MSR 相关联。
因此,这意味着一次只能测量一个事件,因为只有一个 MSR - MSR_OFFCORE_RSP_0
可以映射到 LLC-cache
事件。但是,事实并非如此!
offcore 寄存器本质上是对称的,因此当第一个 MSR - MSR_OFFCORE_RSP_0
寄存器忙时,perf
使用第二个替代 MSR,MSR_OFFCORE_RSP_1
用于测量另一个 offcore LLC 事件.这个函数 here 有助于做到这一点。
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 缓存事件测量的能力。