Linux CPUInfo 中 L1 Cache 的解读
一、先搞清 L1 Cache 的含义
- **L1 Cache(一级缓存)**是离 CPU 核心最近、速度最快的缓存,通常分为两块:
- L1d(Data Cache):存放数据。
- L1i(Instruction Cache):存放指令。
- 在现代处理器中,每个核心通常拥有独立的 L1d/L1i;更大的 L2/L3 多为核间共享。L1 容量最小但命中率对性能影响极大,原因在于程序访问内存具有时间局部性与空间局部性。
二、在 Linux 下如何查看 L1 Cache
- 使用 lscpu(最直观,直接给出 L1d/L1i/L2/L3):
- 示例输出片段:
- L1d cache: 32K
- L1i cache: 32K
- L2 cache: 256K
- L3 cache: 15360K
- 查看 /proc/cpuinfo:
- 常见字段是 cache size(很多处理器只在这里显示“总缓存”或最高级别缓存,未必单独列出 L1d/L1i)。
- 注意:不同架构/微码可能只显示 L3 或不显示 L1 细分项,这是正常现象。
- 查看 /sys/devices/system/cpu/cpu0/cache/(最细粒度,能看到每个缓存层级与属性):
- 例如:coherency_line_size(缓存行大小)、number_of_sets、ways_of_associativity 等。
- 其他补充命令:
- getconf -a | grep CACHE(查看系统级缓存相关配置)
- dmidecode -t cache(从 DMI/SMBIOS 读取缓存描述,部分平台可见)。
三、读懂 L1 Cache 的关键指标
- 容量(Size):以 KB/MB 计。常见组合如 32K+32K(L1d+L1i)、64K+64K 等,表示数据与指令分别有独立的 L1。
- 缓存行大小(Cache Line):一次从下一级内存载入的最小单位,主流为 64 Bytes。这解释了“按行对齐/合并访问”的重要性。
- 相联度(Ways of associativity)与组数(Number of sets):反映命中策略与冲突率。例如看到 8-way、64 sets 等字段,可据此估算总容量与映射方式(容量 = 行大小 × 路数 × 组数)。
- 共享属性:L1 通常为每核私有;L3 多为多核/多插槽共享。这会影响并行线程对缓存的争用与命中率。
四、一个可操作的判读流程
- 步骤 1:用 lscpu 先看是否有 L1d/L1i 的明确数值(如 32K/32K)。
- 步骤 2:若 /proc/cpuinfo 的 cache size 很大(如 12MB),那通常是 L3 或“总缓存”的展示,不要误当作 L1。
- 步骤 3:进入 /sys/devices/system/cpu/cpu0/cache/,逐个 index 查看:
- 用 level 判断层级(0/1/2/3 等),用 type 判断是 Data/Instruction/Unified。
- 读取 coherency_line_size、number_of_sets、ways_of_associativity,理解其容量与映射。
- 步骤 4:结合核心/线程拓扑(lscpu 的 CPU(s)、Core(s) per socket、Thread(s) per core)判断 每核 L1 与 共享 L3 的关系,解释多线程/多进程下的缓存争用与性能差异。
五、常见误区与提示
- L1d 与 L1i 是分开的:性能优化时既要考虑数据访问的局部性,也要考虑指令解码的局部性;把它们合并相加去和其他架构比较没有意义。
- 不要将 L3 或“总缓存”当作 L1:很多系统的 /proc/cpuinfo 只显示较大的那一级缓存(常见为 L3),需用 lscpu 或 /sys 细看层级。
- Intel NetBurst 的特例:其 L1i 被“执行跟踪缓存(Execution Trace Cache)”替代,容量以 12K μOps 计,不能与字节单位的 L1d 直接相加比较。
- 缓存行与对齐:主流 64B 行大小意味着结构体/数组应尽量按 64B 边界对齐,减少伪共享(false sharing)与缓存颠簸(cache thrashing),提升命中率与并行性能。