关于Cortex-A78中l3d_cache_refill与ll_cache_miss_rd的ARMv8 PMU事件疑问
ll_cache_miss_rd与l3_cache_refill计数差异问题分析 问题场景
我在Cortex-A78 Linux系统中使用perf测试进程内存带宽,得到以下输出:
18,312,265 ll_cache_miss_rd # 0.507 M/sec (28.64%) 36,006,163 l3_cache_refill # 0.996 M/sec (42.68%)
根据Cortex-A78的PMU文档说明:
LL_CACHE_MISS_RD Last level cache miss, read.
• 如果CPUECTLR.EXTLLC置位:该事件统计所有返回数据源为'DRAM'、'remote'或'inter-cluster peer'的可缓存读事务。
• 如果CPUECTLR.EXTLLC未置位:该事件对应已实现的末级缓存的L*D_CACHE_REFILL_RD事件——若同时实现了每核L2和集群L3,则为L3D_CACHE_REFILL_RD;若仅实现其中一个,则为L2D_CACHE_REFILL_RD;若均未实现,则为L1D_CACHE_REFILL_RD。
我的系统中L3为末级缓存,且CPUECTLR.EXTLLC=0,按文档理论上ll_cache_miss_rd应与L3D_CACHE_REFILL_RD完全一致,但实际l3_cache_refill的计数是ll_cache_miss_rd的两倍。另外,用perf -e r2a(L3D_CACHE_REFILL的事件ID为0x2A)捕获原始事件,其计数与ll_cache_miss_rd接近,和l3_cache_refill差异显著。
可能的原因分析
1. perf事件别名的统计范围差异
l3_cache_refill是perf提供的通用事件别名,而ll_cache_miss_rd是ARM架构特定事件:
l3_cache_refill在ARM平台的实现可能统计所有L3缓存填充事件,包含读、写两种操作触发的填充;而ll_cache_miss_rd(对应L3D_CACHE_REFILL_RD)仅统计读操作触发的L3缓存填充。如果测试负载中存在大量写操作导致的L3填充,就会出现l3_cache_refill计数接近前者两倍的情况。- 可通过同时测试
l3_cache_refill_wr(若系统支持该事件别名)验证,若写填充的计数与ll_cache_miss_rd接近,则可确认是读写事件合并统计导致的差异。
2. PMU事件的过滤规则差异
perf的事件别名可能附加了默认过滤条件(比如仅统计用户空间事件、排除特定事务类型),而不同别名的过滤规则可能不同:
- 执行以下命令对比原始事件的内核态、用户态拆分计数,同时与
ll_cache_miss_rd的计数做对比:
若perf stat -e r2a,r2a:u,r2a:k -p <你的进程PID>ll_cache_miss_rd的计数仅匹配r2a:u或r2a:k的其中一项,说明该别名存在默认的空间过滤,而l3_cache_refill没有此限制。
3. 硬件配置的特殊情况
即使CPUECTLR.EXTLLC=0,部分定制化Cortex-A78实现可能对末级缓存的定义有差异,或存在其他缓存层级影响:
- 执行以下命令确认L3是否为系统末级缓存:
同时检查系统是否存在额外的外部缓存配置,避免对末级缓存的判断偏差。cat /sys/devices/system/cpu/cpu0/cache/index3/level
4. perf工具的版本或解析bug
不同版本的perf对ARM事件别名的解析可能存在逻辑错误,建议:
- 升级perf到最新稳定版本后重新测试;
- 优先使用原始事件ID(如
r2a)进行测试,绕过别名解析环节,排除工具自身的问题。
验证建议
- 先拆分L3填充的读写事件,确认
l3_cache_refill是否包含写操作计数; - 对比原始事件与别名事件的空间过滤差异;
- 确认硬件缓存层级配置的准确性;
- 升级perf工具后重复测试。
内容的提问来源于stack exchange,提问作者wangt13

