目录

Cache高速缓存

Cache和内存地址映射

1、直接相联映射

内存指定的块只能缓存到指定的Cache行中,采用mod的方式,并且块号用中间的位数,这样主要是为了能利用局部性原理将附近的几个块都能够有机会同时缓存起来

缺点是缓存利用率底,指定的块只能对应指定的行,如果对应的缓存行慢了,即时其他缓存行空着也无法缓存,需要将自己对应的缓存行的数据置换出去

2、全相联映射

内存每块都可以映射到Cache的每一行,优点是缓存利用率高,缺点是查找缓存效率低,需要遍历查找所有缓存行判断当前地址是否存在与缓存中

3、组相联映射

直接映射+全相联映射的结合,将多块分为一组,同时将缓存行里面的多行分为一组,每组内采用全相联映射,组间采用直接相联映射

Cache数据读取和写入

读命中和读不命中

CPU拿到真实的内存地址之后需要先检查Cache是否命中,如果命中则直接返回,否则需要向下一级Cache加载数据。如果下一级也没有命中则需要直接访问内存,访问内存的时候通常会根据局部性原理预读一些数据到各级缓存中

写命中

写数据的时候如果Cache命中了,则我们需要考虑多级缓存以及和内存同步问题,因为L3缓存、内存等都是多核共享的,如果不能及时将脏数据更新回L3或则内存则会造成数据不一致问题,通常有下面两种处理方式:

  • Write Through 直写

    如果写命中,则直接同时跟新当前Cache以及下一级Cache、内存等,这种方式能很好的保障数据一致性,但是会引起总线流量过大,每次写都需要立即更新

  • Write Back 写回

    如果写命中则不会立即更新下一级缓存或则内存,而是标记位dirty ,等到此缓存行被替换的时候再写回,此策略的缺点就是无法保障数据一致性,优点就是可以减少总线流量

写不命中

写数据如果没有命中Cache,则也会有如下几个策略:

  • Write Allocate 写分配

    首先加载对应的数据到缓存行中,然后往缓存里面写入,此策略通常和 Write Back 配套

  • Not Write Allocate 非写分配

    避开高速缓存,直接操作内存,此策略通常是与 Write Through 配套

综上: 我们得出,Cache一致性问题有两种策略解决 (命中和不命中两种情况对应的策略)

  • Write Through+Not Write Allocate
  • Write Back + Write Allocate

Cache分级

https://raw.githubusercontent.com/biningo/cdn/master/2021-04/CPU-Cache.png

L1缓存分为两种: 指令缓存和数据缓存

L2缓存为每个核单独享有,一个更大的缓存

L3缓存为多核共享,在L3中不需要考虑数据不一致问题,因为CPU都可以访问L3

Cache一致性问题[TODO]

  • 写传播: 一个CPU的cache跟新时需要传播到其它的CPU的cache中
  • 事务串行化(锁内存)

参考

关于CPU上的高速缓存

10 张图打开 CPU 缓存一致性的大门 【写的不错】

缓存一致性协议MESI