缓存行是中央处理器缓存中数据交换与读写操作的最小单位,也称作缓存块。缓存与主存之间并不以单个字节为粒度搬运数据,而是整块地取出与写入,这一整块数据即一个缓存行。在个人电脑与服务器常用的处理器上,缓存行的容量通常为 64 字节。缓存行的大小决定了空间局部性利用的效率,也直接影响多核程序在共享数据时的竞争程度。
定义
缓存行指的是处理器缓存中可被独立读写与替换的最小内存块,处理器与主存之间的数据传递以它为基本粒度[1]。程序发起一次内存访问时,硬件不会只取回所需的那一两个字节,而是把包含该地址的整块数据一起装入缓存[2]。
不同微架构上缓存行的容量并不一致,历史与现有实现中可从 16 字节到 256 字节不等,但多数现代处理器采用 64 字节[3]。以 64 字节为例,一个缓存行可以容纳 16 个双精度浮点数,或 8 个 64 位长整型[4]。
内存地址被拆成若干字段来定位缓存行,其中低位偏移量用于指定行内某个具体字节,高位标签则用于判断这一行是否正是所需的内存区域[2]。
原理
缓存能够起作用的前提是程序访问具有时间局部性与空间局部性:近期被用过的数据很可能再次被用,相邻地址的数据也很可能被接连访问。正因为存在空间局部性,一次取回整行数据才不会浪费[2]。取回整行的代价按行计,因此后续访问若落在同一行内,就无需再次访问主存[5]。
设缓存行为 $L$ 字节,则行内偏移量占 $\log_2 L$ 位;若缓存共有 $N$ 个行,索引占 $\log_2 N$ 位,其余高位构成标签。以 64 字节行、1024 个行的缓存为例,偏移量为 6 位、索引为 10 位,标签长度等于地址宽度减去这两部分之和[2]。
根据行可以放置的位置,缓存分为直接映射、全相联与组相联三类:直接映射每个地址只有一个固定位置,全相联可放在任意位置但需比较全部标签,组相联则把缓存划分为若干组、每组容纳若干行[2]。
多核系统中,一致性协议同样以缓存行为单位维护状态。常见的 MSI 协议为每一行设置已修改、共享与无效三种状态,只有一份缓存可以处于已修改状态,多份缓存可以同时处于只读的共享状态[2]。
发展历程
缓存行的概念随缓存存储器一同出现。IBM System/360 Model 85 是较早配备缓存存储器的机型,1969 年 12 月开始交付[6]。该机把主存与缓存都划分为扇区,每个扇区 1024 字节,扇区再分为 16 个 64 字节的块,块是数据在缓存与主存之间搬运的单位[7]。
当时 64 字节块与 16 字节存储字宽度、四路交叉存取相结合,使一个块能够由四个存储单元一次重叠取回[7]。Model 85 标准配置的缓存为 16 KB,可扩展至 24 KB 或 32 KB;由于规模有限,该机型最终只建造了约 30 台[6]。
此后缓存行容量随工艺与访问模式演变。1990 年代的处理器多采用 32 字节缓存行,之后逐步过渡到 64 字节,并使 64 字节成为沿用至今的主流规格[8]。这一稳定性既是硬件设计的选择,也受到软件长期围绕 64 字节调优的反向影响[3]。
围绕缓存行的编程接口也逐步标准化。C++17 引入了描述干扰规模的常量,可用它作为对齐依据,把相互竞争的变量分开放置[9]。
应用
缓存行大小是分块算法设计中的关键参数。矩阵乘法等运算会把矩阵切成小方块,使参与计算的数据能够装进一级缓存并反复使用,从而避免频繁的行替换[10]。
在并行程序中,一种常见做法是让每个线程只写自己独占的缓存行。若多个线程的变量落在同一行,写入会引发该行在各级缓存之间反复迁移,这类并非逻辑共享造成的冲突称为伪共享,会明显拖慢程序。
为缓解这一问题,可以在数据结构中插入填充字节,或使用对齐声明把变量推到独立缓存行上。OpenMP 环境下的示例显示,把线程各自的种子数组按缓存行边界分配后,同一段随机数生成代码的运行时间由约 8.2 秒降至约 0.5 秒[11]。Java 平台则通过 @Contended 标注,让虚拟机把被标注字段隔离到不同缓存行。
矩阵运算、图遍历与并查集等数据结构常借助缓存行对齐来提升带宽利用率;操作系统内核也依据实际缓存行大小决定互斥量、自旋锁等热点的对齐方式[12]。
局限
增大缓存行能减少每字节的标签开销、便于预取并提高带宽,代价是随机访问时的内存流量成倍增加,冲突缺失与伪共享概率也随之上升[3]。当访问模式每次只需要行内少数几个字节,例如沿链表分散跳转时,整行搬运就会带来明显浪费[3]。
填充字节虽然能规避伪共享,但会增加内存占用,在数据量大时加剧存储压力,因此只宜用于确实存在竞争的热点处[13]。
不同处理器或同一系统内采用不一致的缓存行容量,还会让依赖缓存行语义的代码行为变得难以预测,这一点在业界讨论中曾被明确反对[8]。此外,编译器与运行时可能重排或消除未被使用的填充字段,使已经设计好的隔离失效,需要通过额外手段抑制这类优化。
参见
参考资料
- cache-associativity [引用日期2026-10-14]
- HimmelbauerFinal(PDF) [引用日期2026-10-14]
- stackoverflow.com 上的网页 [引用日期2026-10-14]
- usc.gal 上的文件 [引用日期2026-10-14]
- 从CPU缓存结构到原子操作-1 [引用日期2026-10-14]
- CS History: IBM System/360 Model 85 [引用日期2026-10-14]
- 11_360cache(PDF) [引用日期2026-10-14]
- RWT Forums - Real World Tech [引用日期2026-10-14]
- 深入理解 C++17 的缓存行接口 [引用日期2026-10-14]
- 2014ENSL0941(PDF) [引用日期2026-10-14]
- High Performance Computing: Tools and Applications [引用日期2026-10-14]
- LKML: Andi Kleen: Re: Update cacheline size on X86_GENERIC [引用日期2026-10-14]
- Communications of the ACM [引用日期2026-10-14]