S03 —— 有了 DRAM,为什么 CPU 还需要 Cache?多层 Cache 是怎么配合的
金句:木桶最大的那块短板,往往决定了你努力的上限。
CPU 和内存的速度鸿沟
现代 CPU 的计算能力非常强,但访问内存的速度却慢得可怜:
性能差距(2024 年典型桌面 CPU):
CPU 计算一个加法:~1 cycle(约 0.3ns @ 3.5GHz)
访问 L1 Cache:~4 cycles(约 1.2ns)
访问 L2 Cache:~12 cycles(约 3.5ns)
访问 L3 Cache:~40 cycles(约 11ns)
访问 DRAM:~200~300 cycles(约 60~90ns)
内存带宽:DDR5-4800 ≈ 76.8 GB/s(双通道)
CPU 计算能力:3.5GHz × 8 cores × 4 FLOPs/cycle ≈ 112 GFLOPS
问题:
- 内存延迟 ~60~90ns,CPU 全速等待的话,每年有 200 多天在等内存
- 内存带宽虽然高,但单个内存请求的延迟改善很慢速度对比(把 CPU 计算速度设为"1秒"):
CPU 核心计算 ─────────── 1 秒 ───────────
L1 Cache 命中 ───────────── 4 秒 ────────────
L2 Cache 命中 ────────────────── 12 秒 ─────────────────
L3 Cache 命中 ────────────────────────── 40 秒 ──────────────────────
DRAM 访问 ─────────────────────────────────────────── 200 秒 ──────────────────────────────────
内存延迟比 L1 慢了 200 倍,这就是"内存墙"(Memory Wall)。为什么 DRAM 不能做快一点
"让 DRAM 和 CPU 一样快"——技术上很难,原因是物理限制:
DRAM 速度受限的根本原因:
1. DRAM Cell 的物理限制:
- 电容充放电需要时间(RC 延迟)
- 位线(Bit Line)的电容很大,充放电慢
- 刷新操作占用带宽(~1.4%)
2. 内存总线的物理限制:
- DDR5 内存通道带宽可达 76.8 GB/s
- 但单个请求的延迟(latency)由物理距离决定
- 从 CPU 到内存控制器到 DIMM 槽,距离 ~10~20cm
- 光速下 20cm 往返 ≈ 1.3ns(这是最小延迟)
- 实际加上晶体管延迟和协议开销,~60~90ns
3. 成本权衡:
- SRAM Cache 做在 CPU 芯片上,功耗大、面积贵(6T/Cell)
- DRAM 是独立的芯片,便宜、容量大
- 用 SRAM 做所有内存,成本是天价Cache 的基本原理:局部性
Cache 的存在基于两个重要的局部性原理:
时间局部性(Temporal Locality):
- 如果一个数据刚被访问过,它很可能很快又被访问
- 例:循环变量 i,在循环的每次迭代中都被访问
空间局部性(Spatial Locality):
- 如果一个数据被访问,它附近的数据很可能很快被访问
- 例:访问数组元素 a[i],a[i+1]、a[i+2] 很可能马上需要
Cache 的设计就是为了抓住这两个局部性。Cache Line:Cache 不是按"字节"管理的,而是按"Cache Line"(64 字节)管理。当 CPU 读取地址 A 的数据时,Cache 会把 A 所在的整个 Cache Line(64 字节)都取过来——因为空间局部性意味着附近的数据很可能也需要。
Cache Line 的工作方式:
CPU 读地址 0x1000(1 byte)
→ Cache 发现这个地址不在 Cache 里(Cache Miss)
→ 从 DRAM 读取整个 Cache Line(0x1000 ~ 0x103F,共 64 字节)
→ 放到 Cache 里(tag=0x10, index=..., offset=0)
→ 返回 1 byte 给 CPU
后续访问 0x1001~0x103F:
→ Cache Miss → 已在 Cache,直接返回(Cache Hit)多层 Cache 的架构
现代 CPU 典型 3 层 Cache:
典型 3 层 Cache 架构(桌面 CPU,2024):
CPU Core 0 CPU Core 1 CPU Core 2 CPU Core 3
│ │ │ │
L1d ──┬── L1i L1d ──┬── L1i L1d ──┬── L1i L1d ──┬── L1i
4-way │ 4-way 4-way │ 4-way 4-way │ 4-way 4-way │ 4-way
32KB │ 32KB 32KB │ 32KB 32KB │ 32KB 32KB │ 32KB
~1ns │ │ │ │
│ │ │ │
└──────────────────┴──────────────────┴─────────────────────┘
│ │ │
L2 L2 L2
12-way 12-way 12-way
512KB ~ 1MB 512KB ~ 1MB 512KB ~ 1MB
~3.5ns ~3.5ns ~3.5ns
┌────────────────────────┐
│ L3(共享) │
│ 16~32MB │
│ ~11ns(不命中率) │
└──────────┬─────────────┘
│
DRAM
DDR5-4800
~60-90ns每层 Cache 的特点:
| 层 | 大小 | 延迟 | 共享方式 |
|---|---|---|---|
| L1 | 32KB~64KB/CPU | ~1ns | 每个核心独享(L1d 数据/L1i 指令) |
| L2 | 256KB~1MB/CPU | ~3.5ns | 每个核心独享(越来越普遍) |
| L3 | 16MB~64MB | ~11ns | 所有核心共享(Inclusive 或 Exclusive) |
Cache 的映射方式:N-way Set Associative
Cache 不是随意放的,是通过映射来决定数据放在哪里:
直接映射(Direct Map)—— 最简单但冲突多:
每个地址只能放在 Cache 的一个固定位置
冲突时直接替换 → 颠簸(Thrashing)
全关联(Fully Associative)—— 无冲突但硬件贵:
数据可以放在 Cache 的任意位置
需要比较所有 Cache Line 的 Tag → 硬件复杂、功耗高
N路组相联(N-way Set Associative)—— 工业界的折中:
Cache 分为多个 Set,每个 Set 有 N 个 Way
同一地址先找 Set,再在 N 个 Way 里找 Tag
现代 CPU 典型配置:L1 = 8-way,L2 = 12-way,L3 = 16-way
8-way Set Associative 示例(64KB L1,64B Cache Line):
- Cache Line 数量:64KB / 64B = 1024 行
- Set 数量:1024 / 8 = 128 个 Set
- 地址划分:offset(6bit) + index(7bit) + tag(51bit)
- 同一个地址的数据,最多只能出现在同一个 Set 的 8 个 Way 之一
- 冲突概率:只有同一个 Set 的 8 个位置会冲突缓存一致性和 MESI 协议
多核 CPU 里,每个核心有自己的 L1/L2 Cache。如果 Core 0 修改了地址 X,Core 1 的 Cache 里也有同一个地址 X 的副本——谁来决定最终值?
MESI 协议(缓存一致性协议):
M(Modified)—— 本核独占且已修改,数据不在主内存
E(Exclusive)—— 本核独占但未修改,数据和主内存一致
S(Shared) —— 多个核共享,数据和主内存一致
I(Invalid) —— Cache Line 无效(不在缓存中)
状态转换:
Core 0 读地址 X:
→ X 不在任何 Cache → 从 DRAM 读入,状态 = E(Core 0 独占)
Core 1 也读地址 X:
→ Core 0 的 Cache 状态变为 S(共享)
→ Core 1 也持有 X 的副本,状态 = S
Core 0 写地址 X:
→ Core 0 发出 RFO(Read For Ownership),广播给所有核
→ Core 1 的 X 副本变为 I(无效)
→ Core 0 写入 X,状态变为 M(已修改)
Core 1 再读地址 X:
→ Core 1 发现自己的 X 是 I → 向 Core 0 请求
→ Core 0 把 X 的最新值写回 DRAM(M→S)
→ Core 1 从 DRAM 读到 X(状态=S)MESI 的开销:每次跨核写数据都要广播 RFO,在核心数很多的 CPU(16核以上)会成为瓶颈。新的协议(MOESI/ARM 的 DMB)在向这个方向发展。
总结
- 内存墙:DRAM 延迟比 L1 Cache 慢 200 倍,CPU 大部分时间在等内存
- Cache 基于局部性:时间局部性(刚访问的数据再访问)+ 空间局部性(附近的数据也访问)
- Cache Line:最小单位是 64 字节,一次抓一批,充分利用空间局部性
- 多层架构:L1(~1ns,独享)→ L2(~3.5ns,独享)→ L3(~11ns,共享)→ DRAM(~60ns)
- N路组相联:8-way/12-way/16-way 是工业界成本和性能的折中
- MESI 协议:多核 Cache 一致性,Modified/Exclusive/Shared/Invalid 四个状态保证数据不冲突
下篇预告(S04):Cache 是怎么和 CPU 核心连在一起的?核心内部的访存单元、数据通路、以及总线宽度是怎么设计的?
关注公众号「AI不着急」,回复”资料”获取内存学习路线图。
评论