循环分块 tiling/blocking
更新时间:2026-10-01。配合 缓存友好代码,这篇讲把工作集压进缓存的招牌技术。
本文要回答的问题
- 为什么普通 ijk 矩阵乘法缓存表现差?
- tile 大小怎么算才不超缓存?
一、复用与驱逐
普通三重循环里,一行 B 在被多次复用前就因数组过大被挤出。tiling 把计算切成小块,让 A/B/C 的子块在整个小块计算期间都驻留缓存,把跨循环复用变成缓存内复用。
二、块大小与多级
tile 占的三个子矩阵字节数要小于目标缓存(留余量);可分别为 L1/L2 做多级嵌套分块,最内层再做寄存器分块。块大小取元素数/行宽的整数倍并处理边界。
三、常见坑
- 块大小只凭经验不按容量算,导致 evict。
- 忽略三个子矩阵同时占用。
- 不做边界处理或忽视循环顺序。
小结
tiling 按缓存容量切块、把子矩阵驻留复用,多级分块对应各级缓存,块大小要用缺失数验证。下一篇 AoS 与 SoA 布局。
总结
普通三重循环矩阵乘法中,一行 B 在被多次复用之前就因数组过大被挤出缓存,跨循环复用全部退化成下层访问;tiling 按 tile 重排迭代,让 A/B/C 三个子块在整块计算期间驻留缓存,把远处复用变成缓存内复用,块大小必须按三个子矩阵总字节数小于目标缓存(留余量)来算,再为 L1/L2 做多级嵌套分块、最内层做寄存器分块。优化循环不是改算法,而是让数据在被反复使用的窗口里待在缓存中——块大小用缺失数实测,别凭直觉。