2. 缓存基础回顾:缓存层次结构、缓存行、写策略与替换策略

在深入对比 x86 与 ARM 的缓存一致性协议之前,必须牢固掌握缓存系统的核心基础。缓存是解决处理器与主存之间“存储墙”问题的关键硬件结构,其设计直接决定了系统的性能与一致性协议的复杂度。本节将系统回顾缓存的层次结构、缓存行、写策略以及替换策略,为后续协议差异分析奠定基础。

2.1 缓存层次结构

现代处理器普遍采用多级缓存(Multi-level Cache)架构,以在速度、容量和成本之间取得平衡。典型的层次结构包含 L1、L2 和 L3 缓存,其核心特征如下:

缓存级别 典型容量 访问延迟(CPU周期) 位置 主要特征
L1 缓存 32KB - 128KB 2 - 4 周期 每个核心私有 分为指令缓存(L1-I)和数据缓存(L1-D);极低延迟
L2 缓存 256KB - 1MB 10 - 20 周期 每个核心私有或共享 统一缓存(指令+数据);容量与延迟的折中
L3 缓存 2MB - 64MB 30 - 60 周期 所有核心共享 最后一级缓存(LLC);用于跨核心数据共享与一致性过滤
关键概念: 在缓存一致性协议中,L1 和 L2 通常是“私有缓存”,而 L3 作为“一致性域”的汇聚点。x86 和 ARM 在 L3 的管理方式上存在显著差异,这直接影响监听(Snooping)与目录(Directory)协议的选择。

下图展示了典型的多核处理器缓存层次结构,清晰呈现了私有缓存与共享缓存之间的关系:

典型多核处理器缓存层次结构 Core 0 L1-I L1-D L2 Cache (私有) Core 1 L1-I L1-D L2 Cache (私有) Core 2 L1-I L1-D L2 Cache (私有) 片上互连(Ring Bus / Mesh) L3 Cache(共享 / LLC) 内存控制器 → 主存(DRAM)

2.2 缓存行(Cache Line)

缓存行是缓存与主存之间数据交换的最小单位。理解缓存行的结构对于分析一致性协议中的“伪共享(False Sharing)”问题至关重要。

  • 定义: 缓存行是缓存中存储数据的基本单元,通常大小为 64 字节(x86 和 ARM 均采用此标准)。
  • 结构: 每个缓存行包含 标签(Tag)、索引(Index)、偏移量(Offset) 以及 数据块(Data Block)。此外,还包含 状态位(如 MESI 状态) 和 一致性标签。
  • 对齐: 缓存行在内存中是对齐的,即起始地址是 64 的倍数。这意味着一个 64 字节的缓存行对应内存中一段连续的 64 字节区域。
移植适配警示: 虽然 x86 和 ARM 都使用 64 字节缓存行,但 ARM 架构允许实现定义缓存行大小(如 32 字节或 128 字节)。在移植涉及缓存行刷新的代码时,必须使用架构提供的缓存行大小查询指令(如 x86 的 CPUID 或 ARM 的 CTR_EL0),而非硬编码 64 字节。

下图展示了缓存行的内部结构及其与内存地址的映射关系:

缓存行结构(64字节)与地址映射 缓存行(Cache Line) Tag(标签) Index(索引) 状态位 Data Block(64字节数据) 内存地址分解 | Tag (高地址位) | Index (中间地址位) | Offset (低6位) | Tag:区分不同内存块 Index:选择缓存组 Offset:定位字节(0-63)

2.3 写策略:写直达与写回

写策略决定了当处理器执行写操作时,数据如何同步到下一级存储。两种基本策略是 写直达(Write-Through) 和 写回(Write-Back)。现代高性能系统几乎全部采用写回策略,但理解两者的差异对于分析一致性协议至关重要。

特性 写直达(Write-Through) 写回(Write-Back)
写入流程 数据同时写入缓存和下一级存储(如 L2 或主存) 数据仅写入缓存,标记为“脏(Dirty)”,延迟写回
带宽消耗 高(每次写操作都触发总线事务) 低(仅当缓存行被替换或显式刷回时才写回)
一致性维护 简单(下一级存储始终是最新数据) 复杂(需要脏位和写回机制)
性能特征 写操作延迟高,读操作无额外开销 写操作延迟低,但写回时可能产生突发延迟
现代使用场景 仅用于特定 I/O 或安全场景 所有通用处理器(x86/ARM)的默认策略
一致性协议关联: 写回策略是缓存一致性协议复杂性的主要来源。当多个核心共享数据时,一个核心的“脏”缓存行必须被其他核心感知,这催生了 MESI 等协议中的“修改(Modified)”状态和“写失效(Write-Invalidate)”机制。

下图对比了写直达与写回的流程差异:

写策略对比:写直达 vs 写回 写直达(Write-Through) CPU 写操作 写入缓存(更新) 同时写入下一级存储 特点:下一级始终最新,但总线压力大 写回(Write-Back) CPU 写操作 写入缓存(标记为脏) 延迟写回(替换/刷回时) 特点:总线压力小,但需要脏位管理 vs 一致性协议影响 写回策略要求协议跟踪“脏”状态,是 MESI 协议中 Modified 状态存在的根本原因

2.4 缓存替换策略

当缓存已满且需要加载新缓存行时,替换策略决定驱逐哪个现有缓存行。不同的替换策略对缓存命中率和一致性协议行为有直接影响。

2.4.1 常见替换策略

策略 原理 硬件开销 命中率 一致性影响
LRU(最近最少使用) 驱逐最长时间未被访问的行 高(需要记录访问顺序) 高 可预测性好,但实现复杂
伪 LRU(pLRU) 使用二叉树近似 LRU 中等 接近 LRU x86 和 ARM 均广泛采用
随机替换 随机选择一个缓存行驱逐 极低 中等 不可预测,可能导致一致性流量波动
FIFO(先进先出) 驱逐最早加载的行 低 较低 可能频繁驱逐共享数据
移植适配要点: x86 通常使用复杂的 LRU 或自适应替换策略,而 ARM 更倾向于使用 pLRU 以降低功耗。在移植涉及缓存预取或缓存锁定(Cache Locking)的代码时,需要了解目标架构的替换策略行为,避免性能回退。

2.4.2 替换策略与一致性协议的交互

替换策略不仅影响性能,还直接影响一致性协议的行为:

  • 写回触发: 当被驱逐的缓存行处于“修改(Modified)”状态时,必须将其写回下一级存储,这会产生一致性流量。
  • 共享行驱逐: 如果被驱逐的行处于“共享(Shared)”状态,通常无需写回,但需要通知其他核心该行不再有效(取决于协议实现)。
  • 伪共享加剧: 不恰当的替换策略可能加剧伪共享问题,导致缓存行在不同核心间频繁“乒乓”传输。

下图展示了 LRU 替换策略在 4 路组相联缓存中的工作流程:

LRU 替换策略示例(4路组相联) 缓存组(Set) Way 0: 行 A 访问时间: T0 (最旧) Way 1: 行 B 访问时间: T2 Way 2: 行 C 访问时间: T1 Way 3: 行 D 访问时间: T3 (最新) LRU 顺序(从最旧到最新) 行 A (驱逐目标) → 行 C → 行 B → 行 D 新行 E 当新行 E 加载时,最旧的行 A 被驱逐 若行 A 为 Modified 状态,则触发写回操作

2.5 本节总结

缓存基础是理解缓存一致性协议的基石。本节回顾了以下核心概念:

  • 缓存层次结构: L1/L2 私有缓存与 L3 共享缓存的协作模式,以及它们在 x86 和 ARM 中的实现差异。
  • 缓存行: 64 字节对齐的数据单元,其状态位和标签字段直接参与一致性协议的消息传递。
  • 写策略: 写回策略是现代处理器的默认选择,它引入了“脏”状态,是 MESI 协议复杂性的根源。
  • 替换策略: LRU 及其变体(pLRU)是主流选择,其行为直接影响一致性流量的模式和频率。