Appearance
Cache 与虚存:这一类题只在做一个动作——从低位切地址(专题总纲)
Intro
Cache 是一章,虚拟存储是另一章,TLB 又是虚存里的一节。翻书的时候它们隔得很远,做题的时候你会发现三块的动作一模一样。
而且这类题有个特点:一问一算,前一问的结果就是后一问的输入。 地址位数在第一问算错,后面的命中率、平均访问时间、缺页次数会连着一起塌。所以这个专题的地基只有一件事——把地址切对。
(地基之上还叠着两层:数命中、算时间与带宽。少数年份甚至整题都在第三层上,一个地址都不用切——2012、2013 那两道就是。)
地址是被从低位切开的
一个地址永远只表达两件事:哪一块,和块内第几个字节。
低位那一段(块内偏移)的宽度只由一件事决定:块有多大。切完之后,高位那一段是「哪一块」,再按映射方式往下分:
| 场景 | 低位 | 高位怎么再分 |
|---|---|---|
| 直接映射 Cache | 块内偏移 | 块号 → Tag + 行号 |
| 组相联 Cache | 块内偏移 | 块号 → Tag + 组号 |
| 分页 | 页内偏移 | 页号(多级页表再切一次) |
| TLB | —— | 虚页号 → TLB 标记 + TLB 组号 |
最后一行是这个专题的枢纽:TLB 就是存页表项的 Cache,虚页号的切法和 Cache 切块号的切法是同一套。2021 年那道题问的就是这件事——把它当 Cache 看,题目瞬间变熟。
所以这三章讲的是同一个机制,在三个尺度上重复了三遍:都是用一张小的快表,缓存一张大的慢表的一部分。
切地址的三条铁律
- 永远从低位往高位切。 只有低位的含义是固定的(偏移由块大小决定),高位怎么分要看映射方式。反着切必错。
- 命中要同时满足两个条件:有效位 = 1,且标记匹配。 只对了一个就是不命中——这一条在多道真题里被单独列成陷阱,答题时两个都要写出来。
- 算 Cache 总容量时不只是数据区,还要加上标记位和有效位;脏位与替换算法的位则看题面——写直达就没有脏位,而有的年份题面会明写「不考虑一致性维护和替换算法的控制位」,那就真的不算。问「总容量」和问「数据区容量」是两个数,问之前先看题面圈了哪些。
一个反复出现的结构:页内偏移和 Cache 索引重合
有两道真题直接拿这一点设问、另有几道结构上具备:Cache 的(组号 + 块内偏移)位数 ≤ 页内偏移位数时,这几位在虚地址和物理地址里是同一份——页内偏移翻译前后不变。
于是可以不等 TLB 翻译完,就先拿虚地址的低位去查 Cache 的组,查组和地址翻译并行进行。
判断方法很机械:把两个位宽写出来比一下。比如页 4 KB(页内偏移 12 位)、Cache 共 64 行 4 路组相联(= 16 组,组号 4 位)、块 64 B(块内偏移 6 位)——索引一共 4 + 6 = 10 位,10 ≤ 12,成立。
但它不是必然成立的。 有的年份页 8 KB(13 位)、Cache 512 组 64 B 块(9 + 6 = 15 位),15 > 13,这条路就走不通。每道题都要现算一遍,别当成定理。
怎么下笔:先切地址,再叠时间账
- 先写下三个数:块(页)多大、一共多少块或多少组、地址多少位。切法只由它们决定,跟题目讲的故事没关系。
- 从低位切:偏移 → 组号 / 行号 → 标记。把每段的位数标在图上再往下做。
- 往上叠时间账:先算全命中时的基线时间,再把「缺失次数 × 每次缺失的额外代价」加上去。命中率、平均访问时间、CPU 执行时间、主存带宽够不够,全是这一个式子的变形。
必错点:单位
这一类题失分的主要来源不是不理解,而是单位。下笔前确认两件事:
- 按字编址还是按字节编址。 按字编址时,块大小要先换算成"多少个字"再取对数。
- 首地址对齐了吗。 首址不是块大小的整数倍时,同样长度的数组会多跨一个块、多跨一页——2025 年那道题的核心陷阱就在这里,块数和页数都要 +1。
一道题的答卷长什么样
配置取 2019 年那道题:32 位地址、块 64 B、Cache 共 64 行 4 路组相联、页 4 KB。 卷面上真正要写的就这几行:
① 字段划分(从低位往高位切)
块内偏移 = log₂64 = 6 位 → [5:0]
组 数 = 64 行 ÷ 4 路 = 16 组
组 号 = log₂16 = 4 位 → [9:6]
标 记 = 32 − 4 − 6 = 22 位 → [31:10]
② 判两条指令是否在同一页(题面给的是 00401000H 与 0040104AH)
页 4 KB → 页内偏移 12 位 → 比高 20 位
两者高 20 位均为 00401H → 同页
③ 判某条指令落在哪一组(题面给的是 00401025H)
取 [9:6] 四位:025H = 0000 0010 0101B,[9:6] = 0000B
→ 只可能在第 0 组命中
(4 + 6 = 10 ≤ 12,索引落在页内偏移之内,虚实一致,不用等翻译)三步都要落到纸上,尤其是 ① 那张位数表——后面每一问都回来查它。注意 ② 比的是「高 20 位」 (由页大小决定)而 ③ 取的是「[9:6]」(由 Cache 配置决定),两个数来源不同,别混用同一组位宽。
判命中还有一条通用要求:有效位 = 1 且标记匹配,两个条件都要写出来——这道题没问,但别的年份问。
真题的三种形态
12 道真题按下笔套路分三组。
第一组 · 切地址
题目给你一堆配置参数,要你算出各字段的位数、写出映射关系、判断命中。这一组是全专题的地基,另外两组都建在它上面。
值得单独留意的是从题图反向解读的那种问法:给一张 Cache 或 TLB 的结构图,让你反推出这是几路组相联、用的什么替换策略。判断依据很固定——每项都有独立比较器就是全相联,每组画了两行就是 2 路。
⚠️ 但「脏位」这一项是反过来的:题面先告诉你用回写策略,再让你推出每行还得加一个脏位。别当成看到脏位去反推回写。
第二组 · 数命中
给一段循环,问命中率是多少。命中率要画出来数: 把访问顺序和块边界对在一起——一个块里第一次访问必然缺失,其余的在这个块被换出去之前都命中。
这一组真正的考点是空间局部性有没有被访问顺序破坏:数组按行存放却按列访问,如果一行的长度超过 Cache 数据区,就会反复冲突替换,命中率归零;而组相联的路数够宽时,即使按列访问,只要每组的工作集不超过路数就不会替换,命中率照样很高。所以「按列访问 = 命中率低」是错的结论,得看组和路数。
第三组 · 算时间与带宽
命中率算出来之后往上叠一层:平均访问时间、CPU 总执行时间、主存带宽够不够、要不要上多体交叉、DMA 该不该优先于 CPU。
这一组的固定套路是把时间拆成「基线 + 额外开销」:先算全命中时的时间,再把缺失次数 × 每次缺失的额外代价加上去。多体交叉的部分要记住启动是重叠的,不是简单相乘。
交卷前扫一眼
先切地址 · 判命中要「有效位 + 标记」两条件 · 容量看题面圈了哪些位 · 认编址单位与首址对齐
配套内容
逐题精讲(建设中,将按上面三组展开)——真题作答与 AI 判分入口见站内大题专题。
基础没打牢的,先回这几篇:
只作为一小问出现、没有整题考过的(分值不高,但多数年份都会冒头):
- Cache 写策略——写回 / 写直达与写分配的配对,通常和「有没有脏位」绑在一起问
- Cache 替换算法——LRU 位要几位、TLB 命中时要不要更新 LRU 顺序
(Cache 性能分析不在此列——它就是上面第三组的全部内容,是整题级别的考点。)