缓存友好性关键在于结构体字段顺序、内存布局与访问模式:需紧凑排列热点字段、优先使用连续数组而非指针链表、显式对齐数据、避免固定步长扫描,并注意 TLB 与 cache 关联性影响。

避免跨缓存行访问:结构体对齐和字段顺序很关键
CPU 读取内存是以 cache line(通常是 64 字节)为单位的。如果一个 struct 的字段分散在两个 cache line 上,每次访问都要触发两次内存加载——哪怕你只用其中 1 字节。
常见错误现象:valgrind --tool=cachegrind 显示大量 LLm(last level cache miss),但逻辑上没做多少计算。
使用场景:高频访问的小对象,比如粒子系统里的 Particle、游戏实体组件、网络包解析结构体。
- 把经常一起读的字段放在一起,比如
x、y、z紧挨着,别中间插个id或timestamp - 用
alignas(64)强制对齐不是万能的;更有效的是控制字段顺序 + 避免“稀疏填充” - 编译器会自动填充(padding),但你得看懂
sizeof(T)和offsetof(T, field),确认关键字段没被拆开
struct BadVec3 {
float x;
int id; // ← 这里会把 y/z 推到下一个 cache line
float y, z;
};
struct GoodVec3 {
float x, y, z; // ← 连续 12 字节,紧凑
int id; // ← 放后面,不影响热点字段
};
用好局部性:数组优先于指针链表,尤其是遍历时
CPU 预取器(prefetcher)擅长连续地址模式。std::vector 按索引遍历是友好的;而 std::list 或一堆 new 出来的 Node*,地址完全随机,cache 命中率可能低于 10%。
立即学习“C++免费学习笔记(深入)”;
常见错误现象:循环处理 10 万个对象,std::list::iterator 耗时是 std::vector 的 3–5 倍,perf report 显示大量 cycles:u 和 mem_load_retired.l1_miss。
使用场景:批量处理、渲染循环、物理更新、日志聚合等需遍历全部元素的场合。
- 能用
std::vector<T>就别用std::vector<std::unique_ptr<T>>—— 后者指针跳转破坏空间局部性 - 如果必须动态增删,考虑
soa(structure of arrays)布局或arena allocator,保证数据块连续 - 避免在循环体内调用虚函数(间接跳转 + vtable 查找),尤其当基类指针数组实际指向不同派生类型时
注意编译器向量化与 cache 友好性的耦合
SIMD 指令(如 AVX)一次处理多个数据,但前提是数据在内存中对齐且连续。不对齐的 float 数组可能导致编译器放弃向量化,或退化成慢速的 unaligned load。
常见错误现象:开了 -O3 -march=native,但 <strong>attribute</strong>((aligned(32))) 没加在数组声明上,gcc 输出警告 loop vectorized but may not be beneficial。
使用场景:数学计算、图像处理、音频采样、矩阵运算。
- 数组声明时显式对齐:
alignas(32) float data[1024]; - 避免在结构体里嵌套
std::vector,它的内部指针指向堆内存,破坏连续性 - 用
std::array替代小尺寸动态容器,确保栈上连续分配
别迷信“大缓存 = 快”:TLB miss 和 cache associativity 一样致命
L1/L2 cache 容量再大,如果访问模式导致频繁 TLB miss(页表查找失败)或 conflict miss(多地址映射到同一 cache set),性能照样崩。典型例子是步长为 4096 字节倍数的数组扫描(arr[i * 4096])。
常见错误现象:处理大小为 2MB 的数组时,每 4KB 步进访问,perf stat -e dTLB-load-misses 高得异常,远超 cache-misses。
使用场景:大图处理、数据库页扫描、稀疏矩阵迭代器。
- 避免固定步长访问大数组,改用分块(blocking / tiling):先处理
32x32子块,让数据尽量留在 L1 - 对超大结构体,考虑手动分页对齐(
posix_memalign),减少 TLB 压力 - 在 NUMA 系统上,
numactl --membind=0启动程序,防止跨节点内存访问放大延迟
缓存友好不是靠加几个 prefetch 内置函数就能解决的;真正卡住性能的,往往是结构体字段顺序、内存分配方式、甚至数组步长这种一眼看不出毛病的细节。









