超标量处理器设计之Cache(二)

二、Cache

  1. 为什么需要Cache
      在计算机中存在时间相关性和空间相关性,而存储器的访问速度远跟不上处理器的速度,因此需要Cache存储访问概率大的数据。

    • 时间相关性:如果一个数据现在被访问了,那么在以后很有可能还会被访问;
    • 空间相关性:如果一个数据现在被访问了,那么其周围的数据以后有可能也会被访问。
  2. Cache的结构
      Cache主要由两部分组成,Tag部分和Data部分。
      Data部分保存一片连续地址的数据,tag部分存储着这片连续数据的公共地址。
      一个Tag和它对应的所有数据组成的一行称为一个Cache line,而Cache line中的数据部分称为数据块(Cache data block, 也称为Cache block)。
      如果一个数据可以存储在Cache中的多个地方,这些被同一个地址找到的多个Cache Line称为Cache Set
    在这里插入图片描述

  3. 3C定理
      Cache只保存最近被处理过的内容,由于容量有限,很多情况下要找的数据和指令不在Cache中,称为Cache缺失,影响Cache缺失的情况:

    • Compulsory,由于Cache只是缓存以前访问过的内容,因此,第一次被访问的指令或者数据不在Cache中;
    • Capcity, Cache容量越大,就可以缓存更多的内容,因此容量是影响Cache缺失发生频率的一个关键因素;
    • Conflict, 为了解决多个数据映射到Cache中同一个位置的情况,一般使用组相连结构的Cache。
  4. Cache的组成方式

    1. 直接映射
      1> 对于物理内存中的一个数据,如果在Cache中只有一个地方可以容纳它,就是直接映射。
      2> 直接映射中cache line一般有三个组成部分,分别是有效位V,标志位Tag,和数据位Data block。
      3> CPU送来的地址按高低位被分成三部分,tag、index和offset。index用来指定选中哪一个cache line,tag用来与cache line的tag作比较以生成hit信号,而offset则从选择的cache line中选中部分数据进行输出。
      4> 实现结构最简单,执行效率最低。
      在这里插入图片描述

    2. 组相连
      1> 对于物理内存中的一个数据,如果在Cache中有多个地方可以容纳它,就是组相连。
      2> 同样使用Index对Cache寻址,对于找到的多个Cache line,通过比较其Tag确定结果,如果Tag都不匹配,则Cache缺失。
      3> 实际实现中,Tag和Data分开放置,称为Tag SRAM和Data SRAM。同时访问这两个则称为并行访问,先访问Tag再找Data则称出串行访问。
      在这里插入图片描述

    3. 全相连
      1> 对于物理内存中的一个数据,如果在Cache中任意地方可以容纳它,就是全相连。
      2> 不再使用Index,而是直接使用Tag比较得到Cache line,相当于直接使用存储器的内容来寻址,即内容寻址的存储器(Content Address Memory,CAM)。
      3> 实际实现中使用CAM来存储Tag值,使用普通的SRAM来存储数据,CAM中寻址成功时对应的SRAM对应的行也将会被找到。
      4> 灵活度最大,缺失率最低,但是比较最多,延迟最大。一般不会有很大的容量,比如TLB使用这种结构实现。
      在这里插入图片描述

  5. Cache的写入

    • L1 Cache分为I-Cache和D-Cache,对于I-Cache,一般不直接写入内容,而是借助D-Cache实现,将要改写的指令作为数据写入D-Cache,再将D-Cache的内容写入下级存储器如L2 Cache,并将I-Cache的所有内容置为无效,这样处理器再次执行时会使用到修改的指令。
    • 对于D-Cache,执行一条store指令时,假设要写入的地址在D-Cache中,如果只写入D-Cache而被不写入下级存储器,那二者中对于同一个地址就有不同的数据,称为不一致。关乎两种情况:
      • 写通(Write Through):要保持一致性,最简单的就是数据写入D-Cache时也写入下级存储器。问题在于:下级存储器的访问时间长,而store指令在程序中出现频率高,频繁向慢速存储器中写入数据,则执行效率低。
      • 写回(Write Back):如果数据写到D-Cache后,只是将被写入的Cache-line做一个标记,只有当被标记的line要被替换时才写入下级存储器。被标记的记号称为脏(dirty)状态,这样可以减少向慢存储器写入的频率,但是会造成D-Cache和下级存储器的不一致,为存储器的一致性管理增加负担。
    • 如果要写入的地址不在D-Cache中,就发生了写缺失。有两种策略:
      • 写不分配(Non-Write Allocate):最简单的处理方法就是数据直接写到下级存储器,而不写入D-Cache.
      • 写分配(Write Allocate):先把下级存储器中要写入地址的data block取出并于要写入D-Cache的数据合并,再将这个data block写入D-Cache中(写通/写回的方式)。
    • 一般情况下,“写通”和“写不分配”组合,直接将数据更新到下级存储器;“写回”和“写分配”组合。“写通”“写不分配”组合的工作流程、“写回”“写分配”组合的工作流程为:
      在这里插入图片描述
      在这里插入图片描述
  6. Cache的替换策略
      读取或写入D-Cache缺失时,都需要从对应的Cache Set中找到一个line存放从下级存储器读取的数据。如果Cache Set的line都被占用了,就需要替换。常用替换策略有:

    1. 近期最少使用
         LRU(Least Recently Used, LRU)的基本思想是选择最近一段时间使用次数最少的Cache line进行替换,需要对一个Cache set中的每一个cache line的使用情况进行跟踪,实现方法可以是为每一个Cache line都设置一个“年龄位”。当way的数量较多时,为每个way设置年龄位变得复杂,使用“伪LRU”对way进行分组设置(类似编码)实现。
      在这里插入图片描述
    2. 随机替换
        随机替换不需要记录年龄,只需要一个内置的时钟计数器,每当要替换cache line,就根据计数器的当前计数结果来替换cache line。优点是实现起来很简单,缺点是不能体现出数据的使用的规律,可能把最近最新使用的数据给替换出去,不过随着cache的容量越来越大,这个缺点所带来的性能损失也越来越小。总的来说,这是一个折中的办法。
  7. Cache性能的提高

    1. 写缓存
         当D-Cache发生缺失,就需要从下级存储器读写数据,一般访问缓慢甚至只有一个读写端口。比如将缺失的数据从下级存储器中读出并写入选定的Cache line中,如果这个line是脏状态的,那就需要先将这个line写入下级存储器,才能将缺失的数据从下级存储器读出写入Cache中,这是一个串行的过程。
         使用写缓存就可以将这个line的数据写到缓存中,直接将缺失的数据从下级存储器中读出然后写入这个line中,缓存中的数据再伺机写入下级存储器。这样D-Cache写入下级存储器的时间被屏蔽了。
         缺点在于写缓存中的数据是最新的,读D-Cache发生缺失时,需要再写缓存中查找数据,增加了设计复杂度。
    2. 流水线
         读取D-Cache时,可以同时读取Tag SRAM和Data SRAM,基本可以在一个周期完成读取操作;
         写入D-Cache时,必须先读取Tag SRAM,确认写地址在Cache中才能写Data SRAM,串行实现无法在一个周期完成。采取流水线结构,典型方式是将Tag SRAM的读取和比较放在一个周期,写Data SRAM放在下一个周期。
    3. 多级结构
         存储器的容量于速度相互制约,使用多级Cache结构进行提升。
         一般L1 Cache的容量小,保持与处理器内核速度相同等级,L2 Cache容量大但是速度更慢。高阶处理器还会使用容量更大的L3 Cache。
         一般L1 Cache可以采用写通方式,简化流水线设计,而L2 Cache采用写回方式。二者之间的包含关系为:
      • Inclusive:L2 Cache包含L1 Cache,比较浪费硬件资源,简化了一致性管理,多数处理器使用;
      • Exclusive:L2 Cache包含L1 Cache,避免了硬件资源浪费,增加了一致性管理负担。
        在这里插入图片描述
    4. Victim Cache
         Cache中被“踢出”的数据可能马上又要被使用,使用Victim Cache(VC)来保存最近被踢出的数据。一般采用全相连的方式,容量比较小(一般4~16个数据)。
         本质相当于增加了Cache中way的个数,能够避免多个数据竞争Cache中有限的位置,降低缺失率。
      在这里插入图片描述
         类似的设计是Filter Cache,设置在Cache之前,当一个数据第一次被使用是首先放在Filter Cache中,再次被使用时才会搬移到Cache中。作用时防止偶然使用的数据占据Cache,对偶然使用的数据进行一个过滤。
      在这里插入图片描述
    5. 预取
         本质是一种预取技术,猜测处理器在以后可能使用哪些指令或数据,提前将其放到Cache中,用以缓解Compulsory造成的缺失问题。
      • 硬件预取
           对指令而言预测相对简单,因为程序是串行执行的,在没有分支指令的时候只要在访问I-Cache时将后一个数据块也取出即可。
           当I-Cache发生缺失,从下级存储器取出数据放去I-Cache时,将下一个数据块也取出放在Stream Buffer中。
           后续执行中在I-Cache中发生缺失而在Stream Buffer命中时,将当前数据写入I-Cache且将下一个数据块加入到Stream Buffer中。无分支指令时效率高,分支指令会使之造成浪费。
        在这里插入图片描述
      • 软件预取
           硬件实现数据预取不理想,采用软件预取的方式。在程序编译阶段对程序进行分析,得知需要预取的数据,如果指令集设有预取指令,编译器就可以控制程序进行预取。
           预取时间是关键:预取时间太晚,执行时还没预取出来则无意义;预取时间太早, 有可能踢出D-Cache中一些原本有用的数据,造成Cache的“污染”。
  8. 多端口Cache
       超标量处理器中需要每周期同时执行多条load/store指令,这需要一个多端口的D-Cache。但D-Cache容量大,采用物理的多端口设计会对芯片的面积和速度产生大的影响。因此需要其他方法实现多端口的D-Cache。

    1. True Multi-port
         直接使用一个多端口的SRAM实现多端口的D-Cache,缺点在于Cache的所有控制通路和数据通路都需要复制,即多套地址解码器、多个多路选择器、多个比较器、多个对齐器等,会增大面积。而且多端口的SRAM Cell需要驱动多个读端口,延迟、功耗都会增大。
    2. Multiple Cache Copies
         将Tag SRAM和Data SRAM进行复制,本质也是True Multi-port,只不过是通过复制Cache而使得SRAM不需要使用多端口结构。但要保持两个Cache的同步,同样复杂。
    3. Multi-banking
         实际广泛使用的方法。将Cache分为多个bank,每个bank都有一个端口(单端口的SRAM)。
         同样需要多套地址解码器、多个多路选择器、多个比较器和多个对齐器,而Data SRAM不需要实现多端口的结构。由于需要判断Cache每个端口的命中情况,所以Tag SRAM需要有多端口读取功能,需要采用多端口结构。
         一个周期访问地址在不同bank则可以实现并行处理,如果在同一个bank,则会产生bank冲突,这是影响多端口Cache性能的关键因素。

参考资料:
《超标量处理器设计》——姚永斌

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值