缓存友好代码的核心是提升CPU对高速缓存的利用率,关键在于数据布局与访问模式匹配硬件特性:注重局部性、对齐、预取友好及避免伪共享;优先使用连续结构如vector而非链表,合理设计结构体大小与成员顺序,并确保顺序访问与缓存行对齐。
缓存友好代码的核心是让CPU更少地等待内存数据,更多地利用高速缓存(L1/L2/L3)。关键不是“写得快”,而是让数据布局和访问模式匹配硬件缓存行为:局部性(时间+空间)、对齐、预取友好、避免伪共享。
链表、树等动态结构常导致随机访问和缓存行失效。数组、vector、结构体数组(SoA)或结构体内的数组(AoS)更易被预取器识别,提升空间局部性。
std::vector 而非 std::list 存储同类型元素struct Point { float x,y,z; }; std::vector pts; ),
而非分离的坐标数组(x[], y[], z[]),除非有SIMD向量化需求struct Points { std::vector x, y, z; }; ),但注意访问跨度仍应尽量小过大的结构体容易跨缓存行(通常64字节),一次加载浪费带宽;未对齐或填充过多会降低密度,减少每行容纳的元素数。
alignas(64) 强制对齐到缓存行边界(适用于热点结构体或数组首元素)double, int, char),减少编译器填充;必要时用 [[no_unique_address]] 或位域压缩小字段static_assert(sizeof(MyStruct) 做编译期检查
CPU预取器擅长识别固定步长的顺序读写。跳跃式、逆序、散列索引访问会使其失效。
for (int i = 0; i ,而非 a[j][i])
arr[(i * prime) % size]),这破坏可预测性多个线程修改同一缓存行的不同变量,会导致该行在核间反复无效化,严重拖慢并发性能。
alignas(64) 将高频更新的变量隔离到独立缓存行(尤其在线程局部计数器、锁状态等场景)std::atomic 时注意其实现是否隐含缓存行对齐(如gcc/clang下 std::atomic 通常不自动对齐,需手动处理)