缓存行

关注
义项:CPU缓存的最小存取单位
缓存行

缓存行是中央处理器缓存中数据交换与读写操作的最小单位,也称作缓存块。缓存与主存之间并不以单个字节为粒度搬运数据,而是整块地取出与写入,这一整块数据即一个缓存行。在个人电脑与服务器常用的处理器上,缓存行的容量通常为 64 字节。缓存行的大小决定了空间局部性利用的效率,也直接影响多核程序在共享数据时的竞争程度。

百科 图文
目录
  1. 定义
  2. 原理
  3. 发展历程
  4. 应用
  5. 局限
  6. 参见

定义

缓存行指的是处理器缓存中可被独立读写与替换的最小内存块,处理器与主存之间的数据传递以它为基本粒度[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]。此外,编译器与运行时可能重排或消除未被使用的填充字段,使已经设计好的隔离失效,需要通过额外手段抑制这类优化。

参见

  • CPU缓存 —— 缓存行是其中的最小存取与替换单位。

  • 伪共享 —— 多个核心访问同一缓存行中不同变量所引发的性能问题。

  • 缓存一致性 —— 多核之间以缓存行为粒度维护数据一致性的机制。

  • 内存层次结构 —— 寄存器、各级缓存与主存构成的存储层级。

  • 缓存替换算法 —— 缓存行需要让位时决定淘汰对象的策略。

  • 内存对齐 —— 通过地址对齐把数据安排在期望的缓存行内。

参考资料

  1. cache-associativity [引用日期2026-10-14]
  2. HimmelbauerFinal(PDF) [引用日期2026-10-14]
  3. stackoverflow.com 上的网页 [引用日期2026-10-14]
  4. usc.gal 上的文件 [引用日期2026-10-14]
  5. 从CPU缓存结构到原子操作-1 [引用日期2026-10-14]
  6. CS History: IBM System/360 Model 85 [引用日期2026-10-14]
  7. 11_360cache(PDF) [引用日期2026-10-14]
  8. RWT Forums - Real World Tech [引用日期2026-10-14]
  9. 深入理解 C++17 的缓存行接口 [引用日期2026-10-14]
  10. 2014ENSL0941(PDF) [引用日期2026-10-14]
  11. High Performance Computing: Tools and Applications [引用日期2026-10-14]
  12. LKML: Andi Kleen: Re: Update cacheline size on X86_GENERIC [引用日期2026-10-14]
  13. Communications of the ACM [引用日期2026-10-14]
词条评价
词条统计

浏览次数:3 次

阅读量:0 次 · 阅读完成量:0 次

最近更新:2026-10-13T21:21:03Z

历史版本

本条目引用的词条
CPU缓存 伪共享 缓存一致性 内存层次结构 缓存替换算法 内存对齐