CPU缓存

1.缓存结构

CPU缓存的层次结构

        现代处理器至少具有二级缓存,某些高端的多核处理器还具有三级缓存。通常都采用上一级缓存缓存下一级缓存的访问的方式。如寄存器缓存一级缓存访问,一级缓存缓存二级缓存访问,二级缓存缓存三级缓存访问,三级缓存缓存内存访问。当然一些处理器有微小的不同,比如AMD A10 APU中CPU的一级缓存就不缓存来自寄存器的写操作。

        不同的缓存层次组织成一个类似于金字塔的结构,上一级缓存容量小、速度快,下一级缓存容量大、速度慢,上一级缓存下一级。如下图所示,寄存器缓存level 1缓存,level 1缓存level 2,而level 2缓存RAM,RAM缓存硬盘、网络等,而硬盘缓存远程请求等等

          现代处理器至少具有二级缓存,某些高端的多核处理器还具有三级缓存。通常都采用上一级缓存缓存下一级缓存的访问的方式。如寄存器缓存一级缓存访问,一级缓存缓存二级缓存访问,二级缓存缓存三级缓存访问,三级缓存缓存内存访问。当然一些处理器有微小的不同,比如AMD A10 APU中CPU的一级缓存就不缓存来自寄存器的写操作。

        不同的缓存层次组织成一个类似于金字塔的结构,上一级缓存容量小、速度快,下一级缓存容量大、速度慢,上一级缓存下一级。如下图所示,寄存器缓存level 1缓存,level 1缓存level 2,而level 2缓存RAM,RAM缓存硬盘、网络等,而硬盘缓存远程请求等等。

缓存结构

        读写单位:缓存线(cache line)。每条缓存线可以保存L个字节(一般为64)。数据在缓存间上下移动时以缓存线为单位,即读写数据时,每次会读写一个或多个缓存线,不会存在读取半个缓存线(不包括寄存器从一级缓存中读)的情况。

        缓存组:为了减少读取多个映射到同一个缓存的内存地址时造成的存储器访问“抖动”的影响(即冲突不命中),通常将多个cache line组成一组,每个对齐到line的内存地址可映射到一组中的某条缓存线。在读取时,具体读入到组中的哪一条缓存线则由其替换策略决定,常见的替换策略是最近最少使用、随机策略等。通常组的大小为8或16条缓存线。


2.缓存一致性

        缓存一致性协议可以保障在多级缓存环境中,缓存中的数据和内存中的数据是一致的。

        对于单核处理器来说,其缓存一致性协议要保证,某个地址上读得的数据一定是最近写进去的,比如说某条指令修改了地址0x0100上的内容,那么核心对0x0100的缓存需要失效。

        多于多核处理器来说,如果说多个核心缓存了同一个内存地址的数据,若是有一个核心修改了某个地址的数据,其他的核心就需要对该地址的地址数据缓存失效。

        缓存失效是一个长延迟的操作,不能完全流水线化,故很多处理器都提供了失效队列来保存缓存失效操作。伪共享本质上也是一种缓存一致性问题。


3.写缓存

        当程序将数据从寄存器写入内存时,这涉及一个是直接写入内存,还是写入到下一层缓存中的选择问题,依据写是否命中来说,各有两种基本策略。

如果要写的数据已经存在缓存中,即写命中时,有如下两种策略。

        写回(write back),指仅当一个缓存线需要被替换回内存时(缓存已满,或者多线程时,其他线程需要访问这个数据),才将其内容写入内存或下一级缓存。如果缓存命中,则总是不用更新内存。为了减少耗时的内存写操作,缓存线通常还设有一个脏位(dirty bit),用以标识该缓存线在被载入之后是否发生过更新。如果一个缓存线在被置换回内存之前从未被写入过,就不用写回内存。

        写直达(write through),指每当缓存接收到写数据指令,都直接将数据写回到内存或下一级缓存。如果此数据也在缓存中,则必须同时更新缓存。

        无论是写回还是写直达,如果更新的地址被其他核心缓存,那么其他核心对此地址的缓存必须失效。写回的优点是节省了大量的写操作。因为,对一个缓存线内多个不同地址的更新只需一次写操作即可完成,这节省了内存带宽和功耗。写直达比写回更易于实现,并且能更简单地维护数据一致性。

如果需要被写的数据不在缓存中,即写不命中的话,那么现代处理器会执行两种处理方法中的一种;

        写分配(write allocate)。写分配是指,如果要写的数据没有被缓存,那么就在缓存中分配一条缓存线,这类似于大多数处理器对读的处理。如果被写入的数据的局部性很好(在随后会被读),那么写分配就很适合。

        写不分配(write no-allocate)。写不分配是指,如果要写的数据没有缓存,那么数据就直接写入内存,而不占用缓存线,这有点类似于越过缓存。如果被写入的数据的局部性很差(在随后不会被再次使用),那么写不分配就很适合。


4.缓存不命中

        如果处理器无法在某及缓存中得到需要的数据,那么就向下一级缓存请求数据,这称为缓存不命中。不命中意味着从上一级缓存的性能下降到下一级缓存的性能。

        冷不命中:缓存中根本没有数据,因此无论怎么请求都不会命中。

        满不命中:如果缓存已经被全部占用,那么请求的数据如果不在缓存中,就需要将其中的某一个缓存的数据X覆盖为新请求的数据。如果之后又要请求X,此时不命中就成为满不命中。

        冲突不命中:新读取的数据被放入缓存中的某个地址(多个内存地址被映射到同一个缓存地址)。若过该地址的原始数据被访问则不会被命中,此时成为冲突不命中。


5.硬件预取

        为了利用空间局部性,同时也为了掩盖传输延迟,可以投机性地在数据被用到之前就将其取入缓存。这一技术称为预取(Prefetch)。本质上讲,处理器每次加载一条缓存线即是一种预取,即预取了这条缓存线上的其他数据。

        预取可以通过硬件或软件控制。典型的硬件指令预取会在缓存因失效而从内存载入一个缓存线的同时,请求紧随其后的另一个缓存线。某些Intel的处理器需要通过启用BIOS的选项来启用硬件预取,因为如果程序的局部性不好,则硬件预取反而会降低性能。


6.映射策略

        当缓存被数据占满时,哪些缓存的内容要被替换、从下一级缓存取出的数据要放到上一级缓存的什么地方等,这些行为都和映射策略相关。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值