同样遍历1亿个int,按行遍历比按列遍历快了20倍——CPU缓存行的64字节法则
两层for循环,把i和j的位置换一下,执行时间差 20 倍。这不是面试八股文里的数字,是一个 10000×10000 的int矩阵在 Intel i7-12700 上实测出来的结果。GCC 13.2,Ubuntu 22.04,-O2优化。按行遍历 38ms,按列遍历 780ms。同样是 1 亿次加法,同样的汇编指令数量,快了 20 倍。你写的每一行 C++ 最终都要通过 CPU 拿数据、算数据、写数据。但 CPU 不按你的int粒度去内存拿东西——它每次搬的是 64 字节,一整条缓存行。你的遍历顺序要是和内存布局匹配,这 64 字节里的数据全用得上;不匹配的话,64 字节里只取了 4 字节,其余 60 字节全是废料。这篇把 20 倍差距的来源一层一层拆开。从 C++ 数组的内存布局讲起,到 CPU 缓存行的加载规则,到硬件预取器的模式识别,到 TLB 的翻译开销,最后到怎么用perf亲手验证。读完之后你下次写嵌套循环的时候会自然知道把哪个下标放内层。第一层:C++ 二维数组在内存里到底是怎么排的先把最基本的事实摆出来。C/C++ 里的二维数组int arr[M][N]在内存中是row-major order——按行优先存储。先把第 0 行的 N 个元素连续摆完,紧接着第 1 行的 N 个元素,再第 2 行,一直排到第 M-1 行。