如何利用Linux perf性能计数器计算L3缓存带宽
Linux下测量Python脚本L3缓存带宽的实现方法
基于已有perf计数器的手动计算方法
你当前用的perf命令拿到的LLC(Last Level Cache,绝大多数消费级/服务器平台上LLC即为L3缓存)事件,确实可以用来估算L3带宽,计算前先确认两个基础参数:
- 程序实际运行时长:perf stat运行结束后默认输出的
seconds time elapsed字段就是有效时长 - 本地CPU的缓存行大小:现代x86、ARM平台的缓存行普遍为64字节,可执行
getconf LEVEL3_CACHE_LINESIZE确认,若命令返回空直接按64字节计算即可。
注意perf的LLC-*是内核抽象的通用事件,不同CPU架构映射的硬件计数器略有差异,计算前建议用已知带宽的内存密集型负载做简单校准。
两种常见带宽口径的计算逻辑
- L3缓存侧总访问带宽:即CPU核心与L3缓存之间的总数据传输带宽。缓存是按行调度的,不管单次访问读写字节数多少,只要触发一次L3访问就会传输一整个缓存行的数据。
计算公式:L3总带宽 = (LLC-loads + LLC-stores + LLC-prefetches) * 缓存行大小 / 程序运行时长
注意部分CPU平台的LLC-loads事件已经包含了硬件预取发起的请求,这种情况下不需要重复加LLC-prefetches数值,否则结果会偏高。 - L3未命中触发的内存侧带宽:即L3缓存和主存之间的传输带宽,也是性能分析中最常用的带宽指标——只有L3未命中的请求才会走到内存控制器,占用内存总线带宽。
你当前的perf命令缺少两个必要事件,需要先调整命令补全计数项:
计算公式:perf stat -e LLC-loads,LLC-load-misses,LLC-stores,LLC-store-misses,LLC-prefetches,LLC-prefetch-misses python hello.py- L3到内存读带宽 =
(LLC-load-misses + LLC-prefetch-misses) * 缓存行大小 / 程序运行时长 - L3到内存写带宽 =
LLC-store-misses * 缓存行大小 / 程序运行时长 - 总内存带宽 = 读带宽 + 写带宽
注意Intel等平台的缓存采用写回机制,脏缓存行会合并写回主存,手动计算的写带宽和实际值会有10%~20%的固有误差,属于正常现象。
- L3到内存读带宽 =
可直接测量L3带宽的成熟工具
如果不想手动计算,可以直接用专门的性能工具直接输出带宽结果,常用的有这几个:
perf mem:perf工具自带的内存剖析子命令,直接执行perf mem stat python hello.py即可输出内存访问带宽、L3命中率等统计值,不需要额外安装,缺点是默认采样模式下有一定运行开销。- Intel PCM工具集的
pcm-memory:直接读取CPU内存控制器的专用硬件计数器,输出精度远高于通用LLC事件计算值,可以按内存通道分别统计读、写带宽,适合做精确带宽测量,仅支持Intel平台CPU。 likwid-perfctr:跨平台性能计数工具,内置了Intel、AMD、ARM多代CPU的预定义事件组,只要指定L3或内存相关的性能组,就能直接输出L3访问带宽、内存带宽、各级缓存命中率等全套指标,不需要手动查事件映射。toplev:基于Intel Top-down微架构分析方法的工具,除了输出带宽数值,还能直接判定L3带宽、内存带宽是否成为程序的性能瓶颈,适合做深度性能调优。
内容的提问来源于stack exchange,提问作者Kailash gogineni
相关产品推荐
相关产品推荐

