存储层次基础:SRAM、DRAM、Cache 的基本原理与性能差异
做芯片设计这些年,我见过不少工程师把存储层次想得太简单。总觉得不就是快慢区别嘛,大不了全上 SRAM。真到流片的时候,面积和功耗会教你做人。这一章咱们把 SRAM、DRAM、Cache 这三兄弟掰开揉碎,看看它们到底差在哪。
SRAM:速度之王,面积之殇
SRAM 的全称是 Static Random-Access Memory,静态随机存取存储器。为什么叫静态?因为它不需要像 DRAM 那样不断刷新。只要不断电,数据就能一直保持。
它的基本存储单元是 6 个晶体管构成的锁存器。两个交叉耦合的反相器,加上两个传输门。这个结构决定了它的特性:
- 速度快:访问延迟通常在 1-3 个时钟周期
- 功耗高:6 个管子一直在耗电
- 面积大:一个 bit 要 6 个晶体管,密度上不去
- 接口简单:不需要刷新控制器,直接读写
我在做某款 AI 加速器时,L1 Cache 全用的 SRAM。性能确实漂亮,但芯片面积直接爆了预算。后来不得不把部分 SRAM 换成更紧凑的设计,才把面积压下来。
DRAM:容量担当,刷新之痛
DRAM 的全称是 Dynamic Random-Access Memory,动态随机存取存储器。它用一个晶体管加一个电容来存储一个 bit。电容会漏电,所以必须定期刷新。
DRAM 的核心特性:
- 密度高:一个 bit 只要 1T1C,容量可以做得很大
- 速度慢:访问延迟通常在 50-100ns
- 需要刷新:每隔 64ms 必须刷新一次
- 接口复杂:需要行地址、列地址、刷新控制器
你想想看,64ms 内要把所有行都刷一遍。如果芯片工作在 1GHz,那就是 6400 万个时钟周期。这个开销不能忽视。我曾经在一个低功耗项目中,DRAM 刷新功耗占了总功耗的 15%,最后不得不优化刷新策略。
Cache:速度与容量的折中
Cache 说白了就是用 SRAM 给 DRAM 做缓冲。它利用了程序的局部性原理:时间局部性和空间局部性。
Cache 的基本结构:
- Tag:地址标签,用来判断是否命中
- Index:索引,用来定位 Cache 行
- Data:数据块,通常 64 字节
- Valid/Dirty:有效位和脏位
Cache 的映射方式有三种:
| 映射方式 | 特点 | 冲突概率 | 硬件复杂度 |
|---|---|---|---|
| 直接映射 | 每个内存地址只能映射到固定 Cache 行 | 高 | 低 |
| 全相联 | 任何地址可以映射到任何 Cache 行 | 低 | 高 |
| 组相联 | 折中方案,每组内有多个路 | 中 | 中 |
我个人习惯用 4 路组相联。冲突率不高,硬件开销也能接受。全相联虽然命中率高,但比较器太多,面积和功耗都扛不住。
性能差异对比
直接看数据更直观。这是典型存储层次的性能参数:
| 存储类型 | 容量 | 延迟 | 带宽 | 每 bit 成本 |
|---|---|---|---|---|
| SRAM (L1 Cache) | 32-64 KB | 1-3 周期 | ~100 GB/s | 高 |
| SRAM (L2 Cache) | 256-512 KB | 5-10 周期 | ~50 GB/s | 中 |
| DRAM (主存) | 4-32 GB | 50-100 ns | ~20 GB/s | 低 |
注意看延迟差距。L1 Cache 只要 1-3 个周期,DRAM 要 50-100 ns。如果 CPU 主频 2GHz,一个周期是 0.5ns。DRAM 的 50ns 相当于 100 个周期。这就是为什么 Cache 命中率那么重要。
关键指标:Cache 命中率每下降 1%,性能可能下降 10-20%。因为一次 Cache Miss 要去 DRAM 取数据,这个代价太大了。
存储层次结构图
下面这张图展示了典型的存储层次结构。从 CPU 核心到主存,速度和容量呈反比关系。
Cache 替换策略
Cache 满了怎么办?得把旧数据踢出去。常见的替换策略有:
- LRU (Least Recently Used):踢掉最久没用的。效果好,但硬件开销大。
- FIFO (First In First Out):踢掉最早进来的。实现简单,但可能踢掉热点数据。
- Random:随机踢。硬件最简单,但命中率不稳定。
- Pseudo-LRU:近似 LRU,用少量 bit 模拟。我常用这个,性价比高。
实战建议:在 RISC-V 处理器中,L1 Cache 建议用 LRU 或 Pseudo-LRU。L2/L3 可以用 Random,因为访问模式更随机,LRU 的收益不明显。
写策略
Cache 写操作有两种策略:
| 策略 | 操作方式 | 优点 | 缺点 |
|---|---|---|---|
| Write-Through | 同时写 Cache 和主存 | 一致性容易维护 | 写带宽消耗大 |
| Write-Back | 只写 Cache,标记 Dirty | 写带宽小,性能好 | 一致性复杂,需要回写 |
我做过一个项目,用了 Write-Through 策略。结果 DRAM 写带宽被吃满,性能惨不忍睹。后来改成 Write-Back,性能直接翻倍。嗯,这里要注意:Write-Back 虽然好,但多核一致性处理起来很麻烦。这个后面章节会细讲。
Cache 性能公式
平均访问时间 = 命中时间 + 缺失率 × 缺失代价
举个例子:
- L1 Cache 命中时间:2 周期
- L1 Cache 缺失率:5%
- 主存访问时间:100 周期
- 平均访问时间 = 2 + 0.05 × 100 = 7 周期
如果缺失率降到 2%,平均访问时间 = 2 + 0.02 × 100 = 4 周期。性能提升 43%。这就是为什么 Cache 优化那么重要。
避坑指南:我曾经在设计中忽略了 Cache 缺失代价中的总线竞争时间。实际测量发现,多核同时 Miss 时,总线仲裁会额外增加 20-30 周期。这个坑让我多花了两周 debug。
总结
SRAM 快但贵,DRAM 大但慢,Cache 是两者的桥梁。理解它们的特性,才能在芯片设计中做出合理的权衡。记住:没有完美的存储,只有合适的存储。