ch4_3高速缓冲存储器

在这里插入图片描述

1. cache出现的原因

cpu: 处理速度快, 但是存储容量小,
主存: 处理速度低,但是存储容量大;

为了弥补两者之间的差距,  使用了缓存;
要想充分发挥cache 的能力, 
需要保证 cpu 所需要的数据和 指令大多数都能够在cache中获取
这里使用到了程序的局部性原理,

1.1 程序的局部性原理

在这里插入图片描述

时间的局部性: 当前正在使用的指令和数据,在不久的将来仍会被使用到,
所以当前正在指令的指令和数据应该放到cache中,以便于将来在执行时, 快速的提取出来;

空间局部性
当前正在使用的指令和数据,在不久的将来,空间位置上相邻的指令和数据将会被使用到的概率较大;,

由时间局部性和空间局部性,从而将当前正在执行的指令和数据放到cache中, 并且将相邻的指令和数据也放到cache 缓存当中去

1.2 Cache的工作原理

将主存储器和cache 分别分成多个块;

将主存储器或者cache分成若干块,

则主存分为两部分,

  • 一部分为块内偏移地址,其位数决定了块的大小;
  • 另一部分为主存的编号,块的编号;

cache地址同样分成块内地址和缓存块号;
而在实际应用当中,并没形成真正的cache地址;

注意到,   
内存块内地址部分和缓存中的块内地址部分大小是相同的 
所以主存和缓存各自对应的块内地址部分, 位数是完全相同的;

一个在内存和cache中传送时, 是整体按照块传送的;
块内字节的顺序不会发生任何变化,

cache 上的标记,标记了主存快和内存块之间的对应关系,

cpu 要从主存中取出某个主存块号时, 则会先从缓存块号中寻找有无对应的标记, 如果有,则直接从cache缓存块号中取出;

主存与缓存按块存储,块的大小相同,块内地址相同。

在这里插入图片描述

1.3 cache 的命中率

缓存共有C 块
主存共有 M块,   M > > C M>> C M>>C

命中: 
主存块调入缓存;
主存块与缓存块建立了对应关系;

用标记记录 与缓存块建立了对应关系的主存块号;

未命中
主存块未调入缓存
主存块与缓存块 未建立对应关系;

cpu 欲访问的信息在cache中的比率(即另一部分在主存中,没有缓存到cache中), 称为命中率

命中率与cache 的容量与块长有关;

一般每块可取4-8个字;

块长取一个周期内从主存调出的信息长度;

CRAY_1 16体交叉  块长取16个存储字;
IBM 370/168  4体叉  块长取 4个存储字;

1.4 主存系统的效率

主存系统的访问效率与命中率有关;

访问效率使用e 表示, 
访问效率的最小值: cpu的命中率为0, 即欲访问的信息在cache中为0, 此时h = 0, e = t c / t m e = t_{c} /t_{m} e=tc/tm;

访问效率的最大值, 命中率为1, cpu每次访问的都是cache, 没有访问主存. 则访问效率此时 = 命中率的倒数;

在这里插入图片描述

注意这里的公式, 代表了
访问cache 和 访问主存是并行进行的;

如果cpu先访问cache ,再访问主存, 这里的公式将发生变化

2. Cache 基本结构

cache 是在cpu 和内存之间作为一个信息传送的缓冲;
图中的主存便是实际中的内存为主;

2.1 cache 工作的基本原理

  1. cpu 访问内存,需要给出地址,该地址包括块号和块内地址两部分;

  2. 由于cache 和内存之间是以块为单位,进行数据传送的, 所以此时cpu给出的块内地址便可以直接做为cache的块内地址。

  3. 然后使用块号, 在cache 的映射机构中(图中右边红色部分)进行确认是否发生命中。 若发生命中,需要进一步确认当前的主存块号保存在哪个 cache 块中, 形成下方的块号当中。

  4. 若没有命中,需要查阅一下,cache 当中是否还有空间能够装入主存块。 如果cache有空间, 则访问主存,将数据块装入到cache当中。

  5. 如果此时cache没有空间。 则启动cache的替换机构(图中左边红色部分),由替换机构决定cache 中哪一个数据块写回到主存当中,或者是直接丢弃, 然后将主存当中需要用到的块写入到cache 当中。

在这里插入图片描述

2.2 cache 中地址映射和变换机构

如上图中右边红色部分,

  • 主存cache的地址映射机构 map
    给出一种规则,规定主存中的块如果可以放到cache块中, 那么映射机构便规定了该块可以放到cache中哪些块中;

比如说, 同学们去公共教室做实验, 这里便会规定哪些计算机是同学们可以使用的, 哪些是不可以用的,留作管理员使用的。

  • 主存cache的地址变换机构:
    将主存的块号转换成 cache 的块号, 
    或者将主存的地址转换成cache 的地址,
    在cache 当中找到相应的主存块号。

  • cache的替换机构:
    当cache中给定的位置已经 占满, 使用替换算法, 决定将cache哪些块给替换掉,

2.3  主存和cache之间的通信

主存和cache 之间是有一条直接通路的, 通过该直接通路完成主存和cache 之间的信息交换的,

若cpu需要访问的信息不在cache块中, 即发生不命中的情况,
则主存通过下方的数据总线,先将信息传送给cpu , 并且同时将该块的信息放到cache存储体中;

  • cache存储体, 需要用的信息,以块为单位保存在cache存储体当中;

  • 映射机构: 主存的块 哪些块可以放到cache的哪些地方

  • 变换机构: 主存的块在cache哪一个块中查找;

3. Cache的读写操作

cache 中的块是内存当中某些块的缓存, 即cache 中缓存的信息在内存中也有。

3.1 读操作

那么读操作:
当对cache 中的块进行读操作时,不会对cache块中的任何信息进行修改。主存和cache的信息便是一致的,相同的。

3.2 写操作

写操作,会改变cache块中的内容信息;

为了解决cache和主存的一致性问题;

  • 写直达法 write_through
    写操作时数据既写入 cache又写入主存,
    写操作时间就是访问主存的时间, cache块退出时,
    不需要对主存执行写操作, 更新策略比较容易实现。

不足之处: 当一个for循环,需要求和时, 当和的结果需要保存到某一个内存单元中, 此时,写直达法便会造成,该求和的内存单元频繁的和 cache块之间 发生信息交换。

  • 写回法 write -back
    写操作时, 只把数据写入cache, 而不写入主存, 当cache数据被替换出去时, 才将数据写回主存。

此时,写操作时间便是访问cache的时间
当cache块退出时, 被替换的块需写回主存,增加了cache的复杂性。

不足:并行计算机中, 在多处理器情况下, 每个cpu都会有自己的cache,内存的一个块在各个处理的cache中都会有一个副本。如何保证,这多个副本之间信息一致性的问题。

3.3 cache的改进

增加cache的级数

  1. 片载cache: 离处理器比较近或者离core核比较近的,可以直接将cache制作在cpu内部当中。甚至会在cpu内部做两级的cache.

现代处理器,都是多核的,每一个核都会有自己的cache.
并且多个核还会另外有公用的cache

统一缓存: 冯诺依曼结构的计算机 是将指令和数据以同等的方式保存在存储器当中, cache也是一个存储器; 冯氏结构 是将指令和数据统一的放到一个cache 当中。

分立缓存: 而现代计算机会使用分立缓存,
指令cache, 数据cache;
与指令执行的控制方式有关,  是否流水。

Pentium 8k 指令cache, 8k 数据cache.
Power PC620, 32k 指令cache, 32k 数据cache.

4. cache和主存之间的地址映射

主存中任意一个块要加载到cache当中的话,可以加载到cache 当中的哪些块中。

4.1直接映射

主存中任意一个给定的块只能装载到cache当中某个指定的块中。

以 cache 存储体为尺度,将主存储体划分为若干个区, 每个区的大小 和cache 存储体的大小相同。
此时,每个区当中包含的字块数和 cache存储体当中包含的字块数是相同的。

在这里插入图片描述

每个区中编号,都从0开始编号,一直到 2 c − 1 2^c -1 2c1,  在进行映射的时候,
主存储体中任何一个区的字块0  只能 放到 cache中 字块0 当中;
主存储体中任何一个区的字块1 只能 放到 cache中字块1 当中;

上述方式便是直接映射。
在这里插入图片描述

此时, cpu 给出一个主存储体的地址, 
该地址包含三个部分,

区号 + 块号 + 块内偏移地址

主存地址中:
主存字块标记对应 cache中的标记,
用来鉴别主存中的该块号 是否被放到cache当中。
主存中的字块地址 便是对应cache中的字块;

好处是,检查块是否对应时, 只需要检查主存的区号和cache标记中的 其中一个对应的标记位是否相同就可以。

这种方式的不足:
命中率不高, 如果读入的指令是跳转指令, 正好跳到第二个区中的第一个字块, 则需要将cache当中的字块0替换出来,重新将第二个区中的第一个字块写入到其中, 而此时cache当中的其他字块却是空着的。

造成这个问题的原因便是:

  • cache中每个缓存块 可以和若干个 主存块对应
  • 但是,实际存储时,每个缓存块却只能存放主存块中的一个;即,虽然对应多个,但只能存放一个;

4.2 全 相联映射

好处是:主存储器中任意一个块可以放到cache存储器中任意一个位置。

不足之处:当需要检查, 主存储器中的块是放到cache存储器中的哪个块时,
在这里插入图片描述

此时的标记位 = 主存字块标记 + 字块内地址;
电路实现起来不简单明了。
此时标记位变长了, 则需要和每个标记位进行比较,
比较器的位数变多了。
遍历次数变多了。

4.3 组 相联映射

组相联是直接相联和全相联的配合,

  1. 现将cache 分块;
  2. 在将这些cache 块按组进行划分,每组中cache块的数目,可以根据情况设定;
  3. 将主存储器进行划分,这里进行分区, 此时每个区的大小= 上面cache的组数,表明主存储器中每个区中的块数 =  cache的组数
  4. 这样,每次将主存储器中的一个区 缓存到 cache块中;
  5. 映射的时候, 主存储器的一个区中第0块,可以放到cache缓存中第0组中的任意一个块位置;

这里的对应关系是,
主存储器中,在一个区中,每个块在区里的编号决定了该主存块会被放到cache中的哪个组里。

这里用到了直接相联的思想:给定的一个块 只能放到给定的cache一个组里。

也包含了全相联的思想:内存的一个块, 可以放到cache给定一个组中的任何一个位置。

此外, 靠近cpu的cache 要求高速度,此时可以采用直接相联, 中间层次使用组相联, 越远的使用全相联,举例越远要求对cache的利用率越高;

5. 替换算法

选择cache中哪些块可以退出了,腾出位置,用来放入新的内存块到cache中。

替换的核心思想是利用了 程序的局部性原理,
即某段程序中, 离该程序越近的内容,将来越有可能被使用到, 越远的则不会被使用。

4.3 FIFO 先进先出算法

最先放入到 缓存的块,则优先被替换出去;

4.3 LRU 近期最少使用算法

替换出去的块是cpu 不在使用的块,
或者是在cache块当中, 所有的这些块中, 某个块在将来需要被cpu读取该块或写该块, 这个时间间隔越长的块, 则优先将该块替换出去。

小结: 主存和cache之间的 地址映射方法

直接相联映射:某一个主存块只能固定 映射到某一缓存块上。 结构简单, 但是cache的空间利用率低;

全相联: 某一主存块能映射到任一 缓存块当中; 成本高,速度慢,但cache利用率高。

组相联: 某一主存块只能映射到 某一缓存组中的任一块中

猜你喜欢

转载自blog.csdn.net/chumingqian/article/details/129353928