先问一个问题 同样是 O(n),为什么有的循环快很多?
答案常常不在算法复杂度,而在 CPU cache 命中率。现代 CPU 的瓶颈常常是内存访问,不是算术指令。
AoS 与 SoA 常见结构:
struct Particle { float x, y, z; float vx, vy, vz; int alive; }; std::vector<Particle> particles; 如果你只更新位置,实际上每次还会把速度和状态也加载进缓存。更好的方式是 SoA:
struct Particles { std::vector<float> x, y, z; std::vector<float> vx, vy, vz; std::vector<int> alive; }; 这样 CPU 读取的数据更“纯”,预取更有效。
减少伪共享 多线程里,两个线程写不同变量也可能互相拖慢,因为它们落在同一 cache line。
struct alignas(64) Counter { std::atomic<uint64_t> value; }; 用对齐把热点写入隔离开,通常能明显降低抖动。
少做指针追逐 链表、树这类结构在理论上优雅,但在缓存层面很吃亏。工程上更常见的折中是:
用连续数组表示节点池 索引代替裸指针 批量遍历而不是随机跳转 实践建议 先用 profiler 看 cache miss,再改代码 热路径优先考虑连续内存 把“数据怎么放”当成接口设计的一部分 小结 性能优化不是玄学。对于 C++,缓存友好的数据布局往往比微观语法技巧更值回票价。