Cache 的基本工作原理
Cache 是本章唯一真正降低平均访问延迟的部件——其余所有手段提高的都是带宽(见 3.1.2)。它做到这一点的方式是把最近用过的主存内容留在一小块 SRAM 里,赌下一次访问还会落在里面——这个赌注的依据就是 局部性。
这一节要立住三件事:Cache 与主存之间以块为单位交换;一行里除了数据还有一组控制位;以及平均访问时间的两种口径。后面三节都建立在这三件事上。
机制
块是交换单位,行是存放位置
主存被划分成大小相等的块(Block),Cache 被划分成同样大小的行(Line / 槽 Slot)。
块大小必须是 2 的幂,因为主存地址要按位段切分。
CPU 的一次访问
flowchart TD A["CPU 发出主存地址"] --> B["按映射方式拆地址<br/>标记 | 行号/组号 | 块内地址"] B --> C{"该行有效位=1<br/>且标记相符?"} C -->|"是:命中"| D["直接从 Cache 取字<br/>用时 Tc"] C -->|"否:缺失"| E["从主存读入整块"] E --> F{"有空行?"} F -->|"有"| G["装入空行"] F -->|"没有"| H["按替换算法淘汰一行<br/>脏则先写回"] H --> G G --> D classDef hit fill:#d5f5e3,stroke:#27ae60 classDef miss fill:#fadbd8,stroke:#c0392b class D hit class E,H miss
整个过程对程序员透明:程序发出的始终是主存地址,没有任何指令能指定”访问 Cache”。
Cache 行里有什么
疑问点:Cache 行中的"标记项"包括哪几部分
一个 Cache 行由数据块和标记项两部分构成,标记项就是一行里除数据之外的全部控制信息:
位 作用 什么时候有 标记 Tag 记录这一行当前装的是哪个主存块 总是有,位数由映射方式决定 有效位 V 这一行是不是有效数据 总是有(1 位) 脏位 / 修改位 D 这一行被写过、与主存不一致 只有写回法才有(1 位) 替换控制位 LRU 计数 / 年龄位 / 使用位 只有需要替换时才有(直接映射不需要) 有效位不能省。 开机时 Cache 内容是随机的,如果没有有效位,一个随机的标记恰好与地址相符就会读出垃圾数据。进程切换或 Cache 清空时,硬件做的事就是把所有有效位清 0,而不是清数据。
两个容量口径要分清(这是计算题最爱设的陷阱): 数据容量
行数 块大小; 总容量 行数 (块大小 标记位 有效位 脏位 替换位)。 题目说”Cache 容量为 32 KB”时通常指数据容量;问”实际需要多少存储位”时才算总容量。
命中率与平均访问时间 AMAT
设命中率
平均访问时间有两种口径,必须从题干判断用哪一种:
判断方法:看题目给的
Cache 的效率(加速比):
三类缺失
| 类型 | 原因 | 怎么减少 |
|---|---|---|
| 强制性缺失(冷启动) | 第一次访问该块,Cache 里必然没有 | 增大块大小(预取更多邻居) |
| 冲突缺失 | 多个块争抢同一行/同一组 | 提高相联度 |
| 容量缺失 | 工作集超过 Cache 总容量 | 增大容量 |
全相联 Cache 没有冲突缺失——任何块可以放进任何行,冲突这个概念本身不存在。这是判断”某次缺失属于哪一类”的关键判据。
块大小的权衡
块变大的好处:更好地利用空间局部性,强制性缺失减少。
块变大的代价:
- 行数减少 → 冲突缺失增多
- 每次缺失要搬更多数据 → 缺失代价上升
- 块内可能有大量用不到的数据 → 有效利用率下降
所以命中率随块大小先升后降,存在一个最优值。 这一条”先升后降”是判断题的常客——“块越大命中率越高”是错的。
边界
Cache 对程序员和操作系统都透明,虚拟存储器不透明。 这是两个缓存对最本质的差别,完整对照见 3.6.5。
Cache 缺失不产生中断。 硬件自己从主存取回,CPU 只是多等几十个周期,不发生进程切换。缺页才产生异常。
“Cache 容量越大命中率越高”只在一定范围内成立,超过工作集大小后收益迅速趋于平坦,而成本和访问延迟继续上升。大容量 Cache 本身也更慢,这正是要分 L1/L2/L3 多级的原因。
命中率的分母是访存次数。 一道题给”执行 100 条指令、平均每条访存 1.2 次、缺失率 5%“,缺失次数是
指令 Cache 与数据 Cache 分开(哈佛结构)是为了消除取指与取数在流水线中的结构冒险,见 第 5 章。分开之后两者的命中率要分别统计。
对照速查
| 量 | 公式 |
|---|---|
| 命中率 | |
| AMAT 口径一 | |
| AMAT 口径二 | |
| 数据容量 | 行数 × 块大小 |
| 总容量 | 行数 ×(块大小 + 标记 + 有效位 + 脏位 + 替换位) |
| 判断 | 对错 |
|---|---|
| Cache 与主存以块为单位交换 | ✅ |
| Cache 对程序员透明 | ✅ |
| 有效位可以省略 | ❌ |
| 脏位任何写策略都需要 | ❌(只有写回法) |
| 块越大命中率越高 | ❌(先升后降) |
| 全相联没有冲突缺失 | ✅ |
| Cache 缺失会产生中断 | ❌ |
考点
- 块是交换单位,块大小 = 行大小,且为 2 的幂
- 标记项 = 标记 + 有效位 + 脏位(写回法)+ 替换控制位
- 有效位不可省;清空 Cache 就是清有效位
- 数据容量与总容量是两个口径
- AMAT 两种口径都合法,从题干判断并写明
- 命中率的分母是访存次数
- 三类缺失:强制性 / 冲突 / 容量;全相联无冲突缺失
- 块大小与命中率是先升后降的关系
- Cache 缺失由硬件处理,不产生中断
链接
- 🏠 返回总览:计算机组成原理第 3 章:存储系统总览
- ⬅️ 上一节:3.5.1 程序访问的局部性原理
- ➡️ 下一节:3.5.3 Cache 和主存的映射方式
- 🔗 3.1.2 存储器的性能指标(唯一降低延迟的手段)
- 🔗 3.6.5 虚拟存储器与 Cache 的比较
- 📖 名词库:第 3 章名词库