cache 的基本概念

1. cache 简介

 1.1 为什么需要 cache  

        计算机发展过程中,cpu 的性能已经远大于 memory 的访问性能,因此存储的访问大大限制了 cpu 的工作速度。而 cpu 在工作中具有局部性(·时间局部性:最近访问的内容很可能在短期内被再次访问;·空间局部性:地址相邻的内容很可能在想近的时间被用到。)因此引入 cache 可以很大程度上提高 cpu 的工作效率。

       cache 是微体系结构的概念,是内存的映像,cache 的内容是内存内容的子集。一定程度上,cache没有功能上的意义,其存在意义是为了性能,降低访存延迟;cache没有独立的编址空间,处理器访问cache和访问存储器使用相同的地址,但是访问寄存器不一样,寄存器有单独的编址空间。

       理解为 -> 学生在很大的图书馆看书,每次拿的书大多数都是位置上差不多的书,看完一本再去拿另一本的方法,不如每次都将要拿的书和它附近的书一块都放到桌子上,这样更加节省时间。

              学生->cpu、桌子->cache、图书馆->大而慢的存储空间

1.2 系统中的 cache  

        Cache 在计算机科学中有广泛的应用,主要用于提高计算机系统的性能和效率。下面是一些常见的应用场景:

  1. CPU 缓存:CPU 内部有多级缓存(L1、L2、L3),用于存储最经常访问的数据和指令。通过将数据和指令缓存到高速缓存中,可以减少从主存中读取数据的次数,从而提高 CPU 的访问速度。

  2. Web 缓存:Web 缓存是存储在 Web 服务器和客户端之间的中间层。当客户端请求访问一个网页时,Web 缓存可以将其存储在缓存服务器中。当下次有相同的请求时,缓存服务器可以直接返回缓存的网页,而不需要再次向原始服务器请求,从而减少网络传输时间和服务器负担。

  3. 数据库缓存:数据库缓存是将经常使用的数据存储在高速缓存中,以提高数据库的查询性能。当查询请求到达时,数据库可以首先检查缓存中是否存在相应的数据,如果存在,则直接返回缓存的数据,而不需要再次查询数据库。这样可以减少数据库的访问时间和负载。

  4. 编译器缓存:在编译过程中,编译器会将经常使用的中间代码或已编译的代码存储在缓存中,以便在后续的编译过程中重复使用。这样可以减少重复编译的时间和资源消耗。

  5. 文件系统缓存:操作系统会将经常访问的文件数据缓存到内存中,以提高文件的读取速度。当下次有相同的读取请求时,操作系统可以直接从内存中返回缓存的文件数据,而不需要再次访问磁盘。

        总的来说,缓存的应用能够减少对低速存储设备(如内存、磁盘或网络)的访问次数,从而提高计算机系统的响应速度和性能。

2. cache 的工作原理

2.1  cache 中的数据如何被放置

cache 的空间被分成固定大小的块(cache line),

  • 全相连(Fully associative):可以放在 Cache 的任何位置。
  • 直接映射(Direct mapped):只允许放在 Cache 的某一行。如下图:

  • 组相连(set associative):可以放在Cache的某几行。

2.2 如何在 cache 中查找数据

        cache 没有单独的编址空间,是内存的子集,因此 cache 的一个单元在不同时刻存储不同的内存单元。这需要一个机制区分 cache 单元当前存储的实际是哪个内存单元的数据,因此 cache 每个单元既要存放数据,又要存放该数据单元的内存地址和在 cache 中状态。为 cache 中每个字节都记录其他地址效率太低,因此cache存储数据以 cache 块作为单位,不同 cache 级别 cache 块大小不同;每个 cache 块都需要保存其地址,这个就是 cache tag;此外还要为每个 cache 块记录其 state,例如:是否有效、是否被改写等。

2.3 如何替换 cache 中的数据

        因为 cache 内部被分成了一定数量的 cache line,当 cache line 使用满了之后,再有新的需求时就需要清理掉之前的 cache line,这里清理、替换的规则图下(针对于 组相连 和 全相联 的相连模式):

        

“随机”不怎么用;

LRU 比较复杂,cache line 会统计自身被访问的次数。

FIFO 是先进先出规则;

替换的三种方法:

不在 Cache 替换。如果Cache miss了,直接转发访问地址到主存,取到的数据不会写到Cache。

在读 MISS 时替换。如果读的时候 Cache 里没有该数据,则从主存读取该数据后写入 Cache。

在写 MISS 时替换。如果写的时候 Cache 里没有该数据,则将本数据调入 Cache 再写。

2.4  cache 的写操作

场景1:写命中(CPU要写入的内存在 cache 中有)

这种情况有两处处理方式:

① 写穿透:CPU 同时写 cache 和内存 -> 简化了数据一致性,但是写的慢;

② 写回:CPU 值写入到 cache 就返回 bresp->被访问的 cache line 被标记为 dirty(正常为 clean 状态)-> 只当此 cache line 被换出时才写回主存 -> 标记为 dirty 的 cache line 写入到下一级存储单元(多级的 cache 可以设置到哪一级 cache 的时候才向 CPU 返回 bresp)

场景2:写不命中(写缺失)(CPU 要写入的内存 cache 中没有)

① 写分配(Write Allocate):在发生写缺失时,先把这一块读到 cache line(写分配),再在cache line 中写;之后再将修改过的主存块取到 cache。

② 写不分配(Write Non-Allocate):写缺失时直接写进内存,cache 中不做修改。

3. cache 的一致性

        如果多个不同处理器的 Cache 存放了缓存了同一个主存单元的内存块,即共享数据这种情况就可能会导致 Cache 一致性问题的出现。cache一致性协议分为主要有两大类:

  • 监听一致性,每个 cache 被监听/监听其他cache的总线活动;
  • 目录一致性,全局统一管理cache状态。

3.1 总线监听一致性(Bus snooping protocol):

        所谓监听,就是每个 CPU 都有一个 Cache 控制器,随时对通过总线中的数据进行判断,判断自己这是否有总线上请求的数据块。

我们讨论两种保持一致性的方式:写作废方式写更新方式

写作废方式:这种方式的基本思想是,当某个 CPU 出现写请求时,将其它 CPU 下的相同地址的 cache line 直接作废。

我们将每个 CPU 的 Cache 的每个块都归结为下述的三种状态:

    未缓冲(U:所有的 Cache 中都无此块。

    专有态(E:即该块仅仅在该Cache 中有副本,且该块的内容与主存中的不一致。

    共享态(S:即该块在一个或多个 Cache 中有副本,且内容与主存中一致。

3.1.1 具体流程:

假设 CPU 1 有一个读请求

若命中,则 Cache 1 直接将值返回给 CPU 1。

若未命中,就把读失效信号、以及相应地址放到总线上,其他的的 CPU 一直监听着总线,

    a. 若该地址不能在其他 CPU 的 Cache 中被匹配,则结果就是 CPU 1 能正常从主存中读取出数据,且将该块设置为共享态。

    b. 若该地址在 CPU 2 中被匹配上,且该块在 CPU 2 的 Cache 中的状态是共享态,那么CPU 2 将不会采取任何操作。

     c. 若该地址在 CPU 2 中被匹配上,且该块在 CPU 2 的Cache 中的状态是专有态,那么CPU 2 将向 CPU 1 提供该块,并停止 CPU 1 访问主存的操作。CPU 1 Cache 以及 CPU 2 Cache 中该块的状态修改为 共享态。

假设 CPU 1 有一个写请求

若写命中

    a. 若该块在CPU 1 Cache 中的状态是共享态,那么 CPU 1 将该块状态改为专有态,且向总线发送写作废信号,使得别的 CPU 将其Cache 中相应的共享块(若存在)设置为无效。

    b. 若该块在CPU 1 Cache 中的状态是专有态,那么 CPU 1 进行正常的写数据的操作,即将新数据写入该块。

若写缺失,

    a. CPU 1 将该块状态改为专有态,并且正常写入数据,且向总线发送写作废信号,使得别的 CPU 将其Cache 中相应的块(若存在)设置为无效。

状态转换图如下:

写更新方式:

这种方式的思想是,当某个 CPU 出现写请求时,将其它的副本一并更新。

具体说来,就是当一个 CPU 写某数据时,若该块是共享块,通过广播使其他所有 Cache 中有对应副本的块都一并更新。

这种方式很需要总线和存储器的带宽,因为要经常性地广播修改的数据,这使得这种方法被采用地越来越少。

从MESI中演化出的MOESI协议,O(Owned)是MESI中S和M的一个合体,表示本Cache line被修改,和内存中的数据不一致,不过其它的核可以有这份数据的拷贝,状态为S。(多核一致性上,core1 修改了一个 share&clearn<S> 状态的 cache line,对于core1 来说,这个 cache line 由S->O,对于其他合来说,这这 cache line 由 S->I)

在上图中,Local Read表示本内核读本Cache中的值,Local Write表示本内核写本Cache中的值,Remote Read表示其它内核读其它Cache中的值,Remote Write表示其它内核写其它Cache中的值,箭头表示本Cache line状态的迁移,环形箭头表示状态不变。

当内核需要访问的数据不在本Cache中,而其它Cache有这份数据的备份时,本Cache既可以从内存中导入数据,也可以从其它Cache中导入数据,不同的处理器会有不同的选择。MESI协议为了使自己更加通用,没有定义这些细节,只定义了状态之间的迁移,下面的描述假设本Cache从内存中导入数据。

  • 24
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值