🔥作者简介: 一个平凡而乐于分享的小比特,中南民族大学通信工程专业研究生,研究方向无线联邦学习 🎬擅长领域:驱动开发,嵌入式软件开发,BSP开发 ❄️作者主页:一个平凡而乐于分享的小比特的个人主页 ✨收录专栏:硬件知识,本专栏为记录项目中用到的知识点,以及一些硬件常识总结 欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖💖

每个Cache行的完整信息:
| 有效位 | 标记(Tag) | 数据块(Data Block) |
|--------|-----------|-------------------|
| 1 bit | 若干位 | 通常64字节 |类比为停车场的车位:
映射方式 | 映射规则 | 查找速度 | 空间利用率 | 实现复杂度 | 适合场景 |
|---|---|---|---|---|---|
直接映射 | 一个主存块 → 固定一个Cache行 | 最快 | 最低 | 最简单 | 高速小容量Cache |
全相联映射 | 一个主存块 → 任意Cache行 | 最慢 | 最高 | 最复杂 | 特殊用途Cache |
组相联映射 | 一个主存块 → 固定组中任意行 | 中等 | 中等 | 中等 | 大多数现代CPU |
主存块只能放在特定的一个Cache行
行号 = 主存块号 % Cache总行数停车场规则:车牌尾号为X的车只能停在第X号车位
主存地址 = [标记Tag] + [行号Index] + [块内偏移Offset]
↑ ↑ ↑
前几位 中间几位 最后几位
例如:Cache有8行(需要3位表示行号)
主存地址:1101 0110 1011 0010
分解为:Tag=1101 0110, Index=101, Offset=10010假设:Cache有8行(行号0-7),每块4个字
主存有32块(块号0-31)
主存块号17要放入Cache:
行号 = 17 % 8 = 1 → 只能放在第1行
查找主存块号17:
1. 计算行号 = 17 % 8 = 1
2. 检查第1行的有效位是否为1
3. 比较第1行的Tag是否等于17的高位
4. 如果匹配 → 命中,返回数据优点:
缺点:
主存块号:0, 8, 16, 24, 32... 都映射到Cache第0行
块号:1, 9, 17, 25, 33... 都映射到Cache第1行
...
这样即使Cache其他行空着,这些块也只能互相替换!主存块可以放在Cache的任意行
停车场规则:任何车可以停在任何空车位
主存地址 = [标记Tag] + [块内偏移Offset]
↑ ↑
整个主存块号 块内位置
标记长度 = 整个主存块号(比直接映射长很多!)Cache有8行,主存有256块
主存块号123要放入Cache:
可以放在第0、1、2...7任意空行
查找主存块号123:
1. 并行检查所有8行的有效位和Tag
2. 任何一行的Tag等于123且有效位=1 → 命中
3. 如果都未命中 → Cache缺失优点:
缺点:
需要N个比较器(N=Cache行数)
所有比较器同时工作:
比较器0:Tag0 == 目标Tag?
比较器1:Tag1 == 目标Tag?
...
比较器N-1:TagN-1 == 目标Tag?
任何一个匹配 → 命中
全部不匹配 → 缺失Cache分组,主存块映射到特定组,在组内任意行
组号 = 主存块号 % 总组数术语:n路组相联 = 每组有n行
停车场规则:
主存地址 = [标记Tag] + [组号Index] + [块内偏移Offset]
↑ ↑ ↑
前几位 中间几位 最后几位
例如:4路组相联,共16组(需要4位表示组号)
Tag长度介于直接映射和全相联之间N路组相联 | 每组行数 | 总行数=组数×N | 特点 |
|---|---|---|---|
直接映射 | 1路 | 行数=组数 | 直接映射是1路组相联的特例 |
2路组相联 | 2行/组 | 16组×2=32行 | 最常用配置 |
4路组相联 | 4行/组 | 8组×4=32行 | 平衡性能 |
8路组相联 | 8行/组 | 4组×8=32行 | 接近全相联 |
全相联映射 | 所有行一组 | 1组×32=32行 | 全相联是特殊组相联 |
假设:2路组相联,共8组,每块4个字
主存块号19要放入Cache:
组号 = 19 % 8 = 3 → 只能放在第3组
第3组有2行(行6和行7):
1. 检查行6:有效位=1, Tag=Tag6
2. 检查行7:有效位=1, Tag=Tag7
3. 如果Tag6或Tag7等于19的Tag → 命中
4. 如果都未命中 → 需要替换该组中某一行优点:
缺点:
直接映射:固定位置 → 1次比较
组相联(n路):组内n行 → n次比较(并行)
全相联:所有行 → 总行数次比较(并行)
时间:直接映射 < 组相联 < 全相联相同容量Cache的命中率:
全相联映射:~98%
组相联映射(4路):~96%
组相联映射(2路):~93%
直接映射:~85%组件 | 直接映射 | 2路组相联 | 全相联 |
|---|---|---|---|
比较器数量 | 1 | 2 | N(行数) |
控制逻辑 | 简单 | 中等 | 复杂 |
连线复杂度 | 低 | 中 | 高 |
功耗 | 低 | 中 | 高 |
通常采用:2路或4路组相联
原因:需要快速响应CPU请求
举例:Intel Core i7 L1 Cache = 32KB,8路组相联通常采用:全相联或高度组相联
原因:尺寸小,需要高命中率
举例:64条目,全相联映射L1 Cache(最快):4-8路组相联
L2 Cache(中等):8-16路组相联
L3 Cache(最大):16-24路组相联
逐级增加相联度,平衡速度与命中率算法 | 原理 | 优点 | 缺点 |
|---|---|---|---|
随机替换 | 随机选择一行替换 | 简单,硬件成本低 | 性能不稳定 |
FIFO | 替换最早进入的行 | 公平 | 可能替换常用数据 |
LRU | 替换最久未使用的行 | 命中率高 | 实现较复杂 |
LFU | 替换使用频率最低的行 | 考虑访问频率 | 需要计数器,可能"粘住"旧数据 |
每组设置一个LRU位:
LRU=0:最近使用了第0行
LRU=1:最近使用了第1行
替换时选择LRU指出的"最久未使用"行假设:
行0:块0 → 块16(冲突替换) → 块0(又替换)
行1:...
命中率 = 0/5 = 0% (很差!)组0:可存块0、块8、块16中的任意2个
可能存储:块0、块8
访问块16时替换块0(按LRU)
命中率 = 2/5 = 40%可同时存块0、块8、块16
命中率 = 2/5 = 40%
(此例中与2路组相联相同)性能需求:
成本预算:
应用场景:
现代实践:
大多数现代CPU采用:
- L1 Cache:4-8路组相联(速度优先)
- L2/L3 Cache:8-24路组相联(容量+命中率平衡)
- TLB:全相联(小容量,高命中率需求)最终结论:组相联映射是现代计算机Cache设计的主流选择,在速度、命中率和实现复杂度之间取得了最佳平衡!