Cache 分配策略 & 更新策略


1. 分配策略

  • 分配策略是指什么情况需要为数据分配cache line。
  • 读分配
    • 当CPU读数据时,cache缺失,分配一个cache line来缓存从主存中取出的数据。
  • 写分配
    • 场景:CPU写数据时,cache缺失。
    • 当不支持写分配时,写指令直接更新主存的数据。例如:对某一页内存进行初始化操作(全部写0),此时就没必要将对应数据写入cache中。
    • 支持写分配时,会首先将主存中的数据加载到cache line中,(变成命中),然后更新cache line的数据/主存的数据。

2. 更新策略

  • 更新策略是指当cache命中时,写操作如何更新数据。
  • 写直通(Write Through)
    • 例如,CPU执行store指令,且cache命中,首先更新cache中的数据,并更新主存中的数据。cache 和主存的数据保持一致。
    • 但是性能不佳,因为每次写操作都会引起写主存的操作,这个延时是比较大的,至少100个处理器时钟周期,大大降低处理器性能。
    • 上面描述情况的解决方案是:write buffer
      • 数据写入cache的同时也写入写缓冲中,之后处理器继续执行。
      • 写缓冲不断向主存中写入数据,如果写缓冲满了,那么处理器必须停顿流水线直到写缓冲中出现空闲表项。
        • 我认为有点类似乒乓操作。
      • 如果主存写操作的速率小于处理器产生写操作的速率,那么多大容量的缓冲都没用,都会很快就满了。
      • 即使处理器产生写操作的写速率小于主存写操作速率,也可能会产生停顿,例如出现写burst传输时,此时可以增加写缓冲容量解决。
  • 写回(Write Back)
    • 仍是CPU执行store指令,且cache命中,我们只更新cache中的数据,而不立即写入主存,此时cache和主存的数据不一致。
    • cache line有1个bit(dirty bit)用于记录数据是否被修改过。
    • 当cache中的数据要被替换(如:出现写失效),才会写回主存中。
    • 需要实现一个write-back buffer
      • 在出现写失效时,需要根据dirty bit判断是否要将cache line中的数据写回到主存中。
      • 在主存读取需要填充到cache中的数据时,将cache line中的数据写入write-back buffer中。
      • 之后再由buffer写入主存中。
  • 写回 & 写直通
    • 写直通的写操作可以在一个周期内完成,读取标签的同时将数据写入对应的数据块。
      • 如果tag匹配,那么完成写操作,处理器继续执行。
      • 如果tag不匹配,那么产生写失效,将主存中对应地址的数据取出送到cache中。
    • 写回的写操作至少需要两个周期去处理:第一个周期用于判断tag是否命中,若命中则第二个周期进行cache写操作。
      • 不能一个周期就完成的原因:如果在第一个周期就将数据写入,如果tag没有命中,会导致cacheline原有数据未来得及写回主存中,导致数据被破坏。
      • 也可以像写直通一样实现一个store buffer
        • 第一个周期,将数据写入store buffer中,同时查找cache,判断是否命中。
        • 如果命中,在下一个无用的cache访问周期将新数据从buffer中写入cache。

3. 实例

  • 具体内容可以看这篇文章中的实例。
  • 这里只列出我觉得需要特殊注意的地方
    • 当发现cache缺失时,会出现CPU从主存中取数据给cache line的情况,此时需要注意dirty bit是否被拉高。
      • 如果该bit被拉高,那么cache的数据不能直接覆盖,说明这个数据对应的地址之前发生过写回操作,并没有同步到主存中,如果直接覆盖则会丢失这部分的数据。
      • 将被替换这部分数据写回至主存中。
      • 将主存中0x28地址(cache line地址对齐,这里应该要被8整除)开始的8个数据写入cache line中,并清除掉dirty bit,将offset找到的数据返回给CPU。

4. Cache 性能评估

  • $ CPU时间 = (CPU执行的时钟周期数 + 等待存储访问的时钟周期数) * 时钟周期 $
  • 假设等待存储访问的时钟周期数主要来自于cache引起的,下面根据读和写分开讨论。
    • 读操作带来的停顿周期数 只由读失效带来。

      \[读操作带来的停顿周期数=\frac{读操作数目}{程序}*\frac{读失效次数}{指令数目}*读失效代价 \]

    • 写操作带来的停顿周期数
      • 写直通策略
        • 有两个停顿的来源,写失效和写缓冲停顿。后者为buffer满时仍进行写操作引发的停顿。

        \[写操作带来的停顿周期数 = \frac{写操作数目}{程序}*\frac{写失效次数}{指令数目}*写失效代价+写缓冲满时的停顿周期 \]

      • 写回策略
        • 停顿主要来源于cache line要被替换,并需要将原数据写回主存中。
  • 前面介绍是未命中时对性能的影响,但是除了失效率,还有命中时间也会对性能有很大的影响。
    • 举例:增大Cache的容量(主要是Cache line的个数),更大的Cache需要更久的命中时间。这个命中时间可以算在CPU执行的时钟周期数上。
    • 定义 平均存储访问时间(AMAT) 将Cache的命中时间也考虑在内,公式如下。

      \[AMAT = 命中时间+失效率*失效代价 \]

posted @ 2023-06-09 14:21  可达达鸭  阅读(400)  评论(0编辑  收藏  举报