跳转至

CPU cache 与 NUMA

是什么 / 解决什么问题

低延迟程序经常不是算力不足,而是 CPU 在等内存。cache miss、false sharing、NUMA 远端访问会把纳秒级逻辑放大成微秒级抖动。

核心模型

典型访问成本从低到高:

层级 大致量级 说明
L1 cache ~1ns 当前核心私有
L2 cache 数 ns 当前核心私有或局部共享
L3 cache 十几 ns socket 内共享
本地 DRAM 数十到百 ns 当前 NUMA node
远端 DRAM 更高且抖动更大 跨 socket 访问

具体数值依赖硬件,面试时不要背死数字,重点讲数量级和排查方法。

false sharing

多个线程更新不同变量,但变量落在同一 cache line,会导致 cache line 在核心之间反复失效。

struct counters_bad {
    uint64_t rx_count;
    uint64_t tx_count;
};

struct counters_good {
    alignas(64) uint64_t rx_count;
    alignas(64) uint64_t tx_count;
};

alignas(64) 不是万能解,真实项目还要确认结构体数组、allocator 对齐和字段布局。

NUMA 原则

  1. 线程固定到 CPU
  2. 内存由使用它的线程初始化
  3. NIC queue、中断、业务线程尽量在同一个 NUMA node
  4. 避免跨 socket 共享热数据

观测与调试

lscpu
numactl --hardware
numastat -p <pid>
perf stat -e cache-misses,cache-references ./app
perf mem record ./app
perf mem report

面试高频问题

怎么判断程序是 cache 问题

看 IPC、cache miss、内存访问热点和数据结构布局。perf stat 里 IPC 很低且 cache miss 高,说明 CPU 可能在等待内存;再用 perf recordperf mem 定位热点。

怎么降低 cache miss

让热数据更小、更连续、更少指针跳转;拆冷热字段;避免在热路径使用链表和树;预分配对象;减少跨线程共享。