数据布局:AoS 与 SoA
更新时间:2026-10-01。数据在内存里的摆放方式决定每次缓存载入有多少是真正要用的。
本文要回答的问题
- 为什么遍历“一个字段”时 SoA 快得多?
- 什么时候 AoS 反而合适?
一、两种布局
- AoS(Array of Structs):
[ {x,y,z}, {x,y,z} ],取整个对象连续,面向对象直观。 - SoA(Struct of Arrays):
{ x:[], y:[], z:[] },同一字段连续排列。
二、按访问模式选
只遍历/处理某一字段(如对所有粒子的 x 计算)时,AoS 每行还带着用不到的 y、z,浪费带宽;SoA 全是 x,命中率和向量化都好。需要整体访问单个对象时 AoS 更优。还可拆冷热字段避免冷数据占行。
三、常见坑
- 默认 AoS,遍历单字段浪费带宽。
- SoA 后整体访问对象变跨数组。
- 忽略结构体内对齐填充造成的空洞。
小结
SoA 利于单字段遍历与 SIMD,AoS 利于整对象访问,再辅以冷热字段拆分和对齐。下一篇 结构体对齐与填充。
总结
数据在内存中的摆放决定了每条缓存行里有多少字节是真正要用的:AoS 把同一对象的字段连续存放、整对象访问直观友好,但遍历单个字段时会把用不到的同伴字段一起载入、浪费带宽;SoA 让同一字段跨对象连续排列,单字段遍历命中率高且天然利于 SIMD 向量化,代价是整对象访问要跨多个数组。选择布局的唯一依据是访问模式:整对象操作选 AoS、单字段遍历选 SoA,并配合冷热字段拆分与对齐填充榨干缓存行。