CPU缓存优化核心是避免伪共享和提升数据局部性:用alignas与填充隔离热点变量;按访问模式选SoA/AoSoA布局;控制循环顺序适配预取;优先栈分配或对象池减少堆碎片。

CPU缓存优化的核心是让数据访问更“贴近”缓存行(cache line),减少跨核争用和缓存失效。关键就两点:避免伪共享(false sharing) 和 提升数据局部性(data locality),而不是盲目写汇编或调指令。
用内存对齐 + 填充字段隔离热点变量
伪共享发生在多个线程频繁修改同一缓存行(通常64字节)里的不同变量时——即使变量逻辑无关,硬件仍会反复同步整行,拖慢性能。最直接的解法是确保高竞争变量独占缓存行。
- 用
alignas(64)强制按64字节对齐,再配合填充字段(padding)把变量隔开 - 例如:两个原子计数器若共处一缓存行,可这样布局
注意:不要依赖结构体默认对齐;padding 大小要算准,推荐用 std::hardware_destructive_interference_size(C++17起)代替硬编码64。
结构体设计优先考虑访问模式(SoA vs AoS)
数据局部性差,常因结构体布局和访问方式不匹配。比如遍历数组时只读取某个字段(如所有对象的 x 坐标),用 AoS(Array of Structs)就会跳着读内存,缓存不友好。
立即学习“C++免费学习笔记(深入)”;
- 改用 SoA(Struct of Arrays):把同类字段连续存放,一次加载更多有效数据
- 或者用 AoSoA(Array of Struct of Arrays)平衡灵活性与局部性,适合SIMD向量化
- 对热路径中的小结构体(如 Vec3、Point),确保其大小是缓存行的约数(如24字节可塞2个进64字节行),减少浪费
控制循环与数据访问顺序,贴合硬件预取
CPU预取器擅长识别规则的、正向的、步长固定的内存访问。乱序、跳跃、反向遍历都会让它失效,导致大量缓存未命中。
- 嵌套循环中,外层遍历主键,内层尽量连续访存(如按行优先遍历二维数组)
- 避免在热循环里解引用远距离指针或随机索引容器(如
std::map、链表) - 对 vector 等连续容器,用下标而非迭代器+advance;必要时用
std::span明确访问范围,帮助编译器优化
慎用动态分配,优先栈/对象池/arena分配
堆上 new 出来的对象地址随机,极易破坏空间局部性;频繁分配释放还引入锁和元数据开销。
- 小而短生命周期对象尽量放栈上(如临时计算结构体)
- 高频创建销毁的对象(如游戏实体、网络包),用对象池预先分配大块内存,按需复用
- 批量处理场景(如渲染、物理模拟)可用 arena 分配器,保证一批对象内存连续
基本上就这些。缓存优化不是玄学,关键是理解你代码在跑的时候,数据在内存里怎么排、被谁读、怎么被预取——工具只是辅助,观察才是起点。









