Cache与主存映射方式详解:三种“找车位”策略

🔥作者简介: 一个平凡而乐于分享的小比特,中南民族大学通信工程专业研究生,研究方向无线联邦学习

🎬擅长领域:驱动开发,嵌入式软件开发,BSP开发

❄️作者主页:一个平凡而乐于分享的小比特的个人主页

✨收录专栏:硬件知识,本专栏为记录项目中用到的知识点,以及一些硬件常识总结

欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖💖

Cache与主存映射方式详解:三种"找车位"策略

一、Cache存储结构:先了解Cache的"身份证"

每个Cache行的完整信息

复制代码
| 有效位 | 标记(Tag) | 数据块(Data Block) |
|--------|-----------|-------------------|
| 1 bit  | 若干位    | 通常64字节        |

类比为停车场的车位

  • 有效位:车位是否被占用(0=空,1=有车)
  • 标记:车牌号(用来识别是哪辆车)
  • 数据块:车本身

二、三种映射方式对比总览

映射方式 映射规则 查找速度 空间利用率 实现复杂度 适合场景
直接映射 一个主存块 → 固定一个Cache行 最快 最低 最简单 高速小容量Cache
全相联映射 一个主存块 → 任意Cache行 最慢 最高 最复杂 特殊用途Cache
组相联映射 一个主存块 → 固定组中任意行 中等 中等 中等 大多数现代CPU

三、直接映射:固定车位系统

1. 核心规则

主存块只能放在特定的一个Cache行

复制代码
行号 = 主存块号 % Cache总行数

2. 生活比喻:按车牌尾号停车

停车场规则:车牌尾号为X的车只能停在第X号车位

  • 车牌尾号1 → 只能停1号车位
  • 车牌尾号2 → 只能停2号车位
  • ...
  • 如果1号车位已有车(尾号也是1),新来的尾号1的车必须把旧车挤走

3. 地址结构分解

复制代码
主存地址 = [标记Tag] + [行号Index] + [块内偏移Offset]
           ↑                 ↑               ↑
       前几位           中间几位          最后几位
       
例如:Cache有8行(需要3位表示行号)
主存地址:1101 0110 1011 0010
分解为:Tag=1101 0110, Index=101, Offset=10010

4. 访问过程示例

复制代码
假设: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. 如果匹配 → 命中,返回数据

5. 优点与缺点

优点

  • 查找极快:直接计算行号,只需比较一个Tag
  • 硬件简单:只需要一个比较器
  • 成本低:实现简单

缺点

  • 冲突频繁:多个主存块竞争同一Cache行
  • 命中率低:即使Cache有空位也不能用
  • 抖动问题:频繁替换同一行

6. 冲突问题图示

复制代码
主存块号:0, 8, 16, 24, 32... 都映射到Cache第0行
块号:1, 9, 17, 25, 33... 都映射到Cache第1行
...
这样即使Cache其他行空着,这些块也只能互相替换!

四、全相联映射:自由停车场

1. 核心规则

主存块可以放在Cache的任意行

2. 生活比喻:自由停车

停车场规则:任何车可以停在任何空车位

  • 新来的车选择任意空位停放
  • 查找车辆时需要检查所有车位

3. 地址结构分解

复制代码
主存地址 = [标记Tag] + [块内偏移Offset]
           ↑                     ↑
      整个主存块号             块内位置
       
标记长度 = 整个主存块号(比直接映射长很多!)

4. 访问过程示例

复制代码
Cache有8行,主存有256块

主存块号123要放入Cache:
可以放在第0、1、2...7任意空行

查找主存块号123:
1. 并行检查所有8行的有效位和Tag
2. 任何一行的Tag等于123且有效位=1 → 命中
3. 如果都未命中 → Cache缺失

5. 优点与缺点

优点

  • 空间利用率最高:任何空位都可以利用
  • 命中率最高:避免不必要的冲突
  • 替换灵活:可以选择最佳替换对象

缺点

  • 查找最慢:需要比较所有行的Tag
  • 硬件复杂:需要多个并行比较器
  • 成本高:实现困难,耗电多

6. 查找机制

复制代码
需要N个比较器(N=Cache行数)
所有比较器同时工作:
  比较器0:Tag0 == 目标Tag?
  比较器1:Tag1 == 目标Tag?
  ...
  比较器N-1:TagN-1 == 目标Tag?
  
任何一个匹配 → 命中
全部不匹配 → 缺失

五、组相联映射:分组停车系统

1. 核心规则

Cache分组,主存块映射到特定组,在组内任意行

复制代码
组号 = 主存块号 % 总组数

术语:n路组相联 = 每组有n行

2. 生活比喻:按颜色分组停车

停车场规则

  • 车位分成红、蓝、绿、黄4组
  • 红色车只能停在红色组的任意空位
  • 蓝色车只能停在蓝色组的任意空位
  • 在组内可以自由选择车位

3. 地址结构分解

复制代码
主存地址 = [标记Tag] + [组号Index] + [块内偏移Offset]
           ↑                ↑               ↑
       前几位          中间几位          最后几位
       
例如:4路组相联,共16组(需要4位表示组号)
Tag长度介于直接映射和全相联之间

4. N路组相联具体示例

N路组相联 每组行数 总行数=组数×N 特点
直接映射 1路 行数=组数 直接映射是1路组相联的特例
2路组相联 2行/组 16组×2=32行 最常用配置
4路组相联 4行/组 8组×4=32行 平衡性能
8路组相联 8行/组 4组×8=32行 接近全相联
全相联映射 所有行一组 1组×32=32行 全相联是特殊组相联

5. 访问过程示例(以2路组相联为例)

复制代码
假设: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. 如果都未命中 → 需要替换该组中某一行

6. 优点与缺点

优点

  • 平衡性好:速度与命中率的折中
  • 硬件可行:只需要N个比较器(N=路数)
  • 命中率较高:减少冲突
  • 现代主流:大多数CPU采用

缺点

  • ❌ 比直接映射稍慢
  • ❌ 比全相联命中率稍低
  • ❌ 实现比直接映射复杂

六、三种映射方式性能对比分析

1. 查找时间对比

复制代码
直接映射:固定位置 → 1次比较
组相联(n路):组内n行 → n次比较(并行)
全相联:所有行 → 总行数次比较(并行)

时间:直接映射 < 组相联 < 全相联

2. 命中率对比(典型值)

复制代码
相同容量Cache的命中率:
全相联映射:~98%
组相联映射(4路):~96%
组相联映射(2路):~93%
直接映射:~85%

3. 硬件成本对比

组件 直接映射 2路组相联 全相联
比较器数量 1 2 N(行数)
控制逻辑 简单 中等 复杂
连线复杂度
功耗

七、实际应用场景

场景1:L1 Cache(追求速度)

复制代码
通常采用:2路或4路组相联
原因:需要快速响应CPU请求
举例:Intel Core i7 L1 Cache = 32KB,8路组相联

场景2:TLB(快表)

复制代码
通常采用:全相联或高度组相联
原因:尺寸小,需要高命中率
举例:64条目,全相联映射

场景3:现代CPU的多级Cache策略

复制代码
L1 Cache(最快):4-8路组相联
L2 Cache(中等):8-16路组相联  
L3 Cache(最大):16-24路组相联

逐级增加相联度,平衡速度与命中率

八、替换算法:当Cache满时

对于组相联和全相联需要替换策略

算法 原理 优点 缺点
随机替换 随机选择一行替换 简单,硬件成本低 性能不稳定
FIFO 替换最早进入的行 公平 可能替换常用数据
LRU 替换最久未使用的行 命中率高 实现较复杂
LFU 替换使用频率最低的行 考虑访问频率 需要计数器,可能"粘住"旧数据

LRU实现示例(2路组相联)

复制代码
每组设置一个LRU位:
LRU=0:最近使用了第0行
LRU=1:最近使用了第1行

替换时选择LRU指出的"最久未使用"行

九、综合示例:三种映射方式对比

假设:

  • Cache:8行,每块16字节
  • 主存:256块
  • 访问序列:块0, 块8, 块16, 块0, 块8

直接映射结果

复制代码
行0:块0 → 块16(冲突替换) → 块0(又替换)
行1:...
命中率 = 0/5 = 0% (很差!)

2路组相联结果(4组,每组2行)

复制代码
组0:可存块0、块8、块16中的任意2个
可能存储:块0、块8
访问块16时替换块0(按LRU)
命中率 = 2/5 = 40%

全相联结果

复制代码
可同时存块0、块8、块16
命中率 = 2/5 = 40%
(此例中与2路组相联相同)

十、总结与选择建议

选择映射方式的考虑因素

  1. 性能需求

    • 追求速度 → 直接映射或低路数组相联
    • 追求命中率 → 高路数组相联或全相联
  2. 成本预算

    • 低成本 → 直接映射
    • 高成本 → 全相联
  3. 应用场景

    • 小容量Cache → 全相联或高相联度
    • 大容量Cache → 低到中相联度
  4. 现代实践

    复制代码
    大多数现代CPU采用:
    - L1 Cache:4-8路组相联(速度优先)
    - L2/L3 Cache:8-24路组相联(容量+命中率平衡)
    - TLB:全相联(小容量,高命中率需求)

核心要点记忆

  1. 直接映射 = 一个萝卜一个坑(快但易冲突)
  2. 全相联 = 随便停(灵活但找车慢)
  3. 组相联 = 按颜色分组停(最佳折中)

最终结论:组相联映射是现代计算机Cache设计的主流选择,在速度、命中率和实现复杂度之间取得了最佳平衡!

相关推荐
一个平凡而乐于分享的小比特2 天前
Cache(高速缓冲器)完全解读:计算机的速度“秘密武器”
cache·高速缓冲器
robinson19888 天前
验证崖山数据库标量子查询是否带有CACHE功能
数据库·oracle·cache·自定义函数·崖山·标量子查询
星马梦缘10 天前
计算机组成原理 2024级焚决
计算机·cache·计算机组成原理·组合逻辑
zhuanshulz15 天前
Gem5 预取机制介绍
cache·gem5·prefetcher
元亓亓亓1 个月前
考研408--组成原理--day6--外部存储器&Cache
考研·cache·408·存储器
东南门吹雪1 个月前
AI芯片-LLM算子-CPU-Cache
人工智能·cache·昇腾·npu·一致性协议
♛识尔如昼♛2 个月前
计算机组成原理(15) 第二章 - Cache
cache·计算机组成原理·多级cache
JJCar2 个月前
【Cache缓存】分配策略
缓存·cache·多核数据一致性
JJCar2 个月前
【Cache缓存】cache的刷新
缓存·cache·多核数据一致性