cache 缓存器,解决内存墙问题,是主存部分的副本,设计要素有地址、容量、映射功能、替换算法、写策略、行大小、cache 数目。

# Lecture08-cache

# cache 简介

# 存储器层次结构

image-20221101164918401

随着层次的下降,每位价格下降,容量增大,存取时间变长,处理器访问存储器的频率降低。

cache(高速缓存)存储器的目的是使存储器的速度逼近可用的最快存储器的速度。

多级 cache 一般标注为 L1、L2,通常由动态随机存取存储器(DRAM)构成。

# cache 存在的意义:解决内存墙的问题

image-20221101165310897

image-20221101165325716

# cache 的基本思路

image-20221101164904882

只是主存部分信息的副本

image-20221101170441990

# cache / 主存系统的结构

image-20221101205028927

主存系统中 ——M 个块,每块有 K 个字

cache 中 ——m 个块,称作行【控制为 + 标记 + K 个字】

行的数量远远小于主存储器块的数目 m << M

image-20221101170954954

传入地址 RA, 最后红线框处的两步为并行操作。

# cache 的工作流程

image-20221101165017905

  • Hit—— 传送的是
  • Miss—— 读入 cache 的是,传入 CPU 的是

# 问题

image-20221101165200894

# 命中还是未命中?

image-20221101165513269

CPU、cache、主存如何建立地址的一一对应关系?

标记是什么?

# 为什么从内存中读入一个块?

image-20221101165809967

image-20221101171223532

image-20221101171836956

image-20221101172138850

利用空间局限性,所以把块传入 cache 当中。

块在 cache 中,则字在 cache 中。

标记和内存地址之间的关系?

# 使用 cache 需要更多的操作,为什么还可以节省时间?

image-20221101173524901

Tm 是未命中惩罚

两个式子都需要理解,下面的式子更方便做题。

降低 cache 的访问时间与提高命中率矛盾 —— 存的东西多,提高命中率,但是降低了 cache 的访问时间。

# 避免 cache 未命中,提高命中率

image-20221101173558232

容量失效 —— 涉及映射规则和替代原则的问题

冲突失效 —— 例如直接映射中的冲突

# cache 的设计要素

image-20221101173743177

# cache 地址

image-20221101174037678

物理 cache 和逻辑 cache 的比较

逻辑 cache 访问速度快,但是需要 cache 的每一行增加额外的几位来标记与该地址相关的虚拟地址。

# cache 容量

image-20221101174233373

1k 涨到 16k,命中率有明显的上升,可以解决一些容量失效的额问题,但是再往后,命中率的上升近乎达到峰值。

image-20221101174537594

image-20221101174552006

# 映射功能

# 直接映射

image-20221101174930231

左边的映射方式可能会造成容量失效的问题。

image-20221101175153621

000H 和 080H 对应一个 cache 的行,每隔 8 个就会共用一个 cache 的行。

稍微真实一点的示例,一个块里面有 16 个字,每个地址差 10H(即为 16)。

H 是 16 进制的意思。

image-20221101175330724

M = 主存的块数

i = cache 行号(在 cache 中对应的行数)

j = 主存储器的块号

C = cache 的行数(cache 总共的行数)

image-20221101210831620

image-20221101175648891

image-20221101213351613

image-20221101213323009

# 全相联映射(关联映射)

标记域 + 字域(s+w)位,cache 中的行号不由地址格式决定

image-20221103162237911

image-20221101213419743

image-20221103163021051

image-20221103163033660

# 组关联映射

折中方法,体现了直接映射和全相联映射的优点,又避免了两者的缺点。

标记 + 组(v = 2 d)+ 字(块大小 )。

一组中有 K 行。

image-20221103163817034

image-20221103163951991

image-20221103164015137

image-20221103164147269

小容量适合全关联映射

大容量适合直接映射

K 路组关联映射处于两者之间

image-20221103172751908

image-20221103172808723

image-20221103172844027

两个映射到同一 cache 组的块不可能具有相同的标记数。

每组两行 (v = m/2, k = 2) 是最常用的组相联结构,与直接映射相比,它明显地提高了命中率。

# 三种映射方式比较

image-20221103164308172

image-20221103164318953

关联度越低,命中率越低,判断是否命中的时间越短,标记所占额外空间开销越小。【关联度小,其他三个都小】

# 替换算法

image-20221103164810384

# 常用的替换算法

image-20221103165206857

# 最近最少使用算法 LRU

image-20221103165310688

USE 位为 0,不代表没有数据

由前文,可以看到,两路组关联映射是最常用的方法,这个实现是很有现实意义的举例。

image-20221103165326712

最后一个 1110 的替换,LRU 最大为 3 的位置被替换,其他得未被访问的行的 LRU 自增 1。

https://blog.csdn.net/piaopiaolanghua/article/details/9384043

为什么是 log (K!)—— 排列组合的问题

image-20221103165404094

LRU 的命中率可能没有想象中那么高

# 先进先出算法 FIFO

image-20221103165417670

image-20221103165432556

# 最不经常使用算法 LFU

image-20221103165447852

所需要的额外的硬件实现太多,不能够支持。

# 随机替换算法

image-20221103165504705

随机替换算法是一种基线【或者说底线】,随机替换算法在性能上只稍逊于使用其他替换算法,也就说明其他随机替换算法没有那么好。

# 写策略

image-20221103172948799

# 缓存命中时的写策略:写直达 Write Through

image-20221103173037433

# 缓存命中时的写策略:写回法 Write Back

image-20221103173052648

缺点的解决方法:每次 I/O 模块存取的时候先和 cache 做一个同步

# 缓存未命中的写策略:写不分配 / 写分配

image-20221103173811474

# 行大小

image-20221103174054409

不是违反时间和空间关系,而是影响局部性(?

image-20221103180046644

# cache 数目

image-20221103174453746

通常,会有片内和片外的 cache。片内 cache 为第一级(L1),外部 cache 为第二级(L2)。L2cache 大小至少为 L1cache 大小的两倍时,才对提高总命中率有明显的作用。

image-20221103174504972