天天看点

cache之读写一致性(一)

cache之读写一致性(一)

cache根据写操作后是否要直接同步到内存,可分为write back(稍后同步)和write through(立刻同步)。write through的方式虽然享受不到写cache带来的性能优势,但是还是可以享受读cache的好处的,而且其(和内存的)一致性维护也更简单,适用场景包括视频输出等。

而write back可以减少不必要的内存写入,减轻总线竞争。现在大部分应用场景下,cache多采用write back的方式,本文以下的讨论都基于write back且只有一个level的cache。

cache一致性(coherency)

cache为维护一致性的操作可分为flush和invalidate。

当CPU更改了某条cache line中的数据,则该cache line中的数据比对应内存中的数据新,此时需要将这条cache line标记为modified,以便在必要时候(cache满了,该cache line需要被释放,把位子腾出来给新的cache line)将cache line中的内容flush到内存来同步。

在使用DMA的时候,外设(比如网卡)过来的数据会不经过CPU直接传送到内存,这时内存中的数据就比对应cache中的数据要新,需要使无效(invalidate)相关的cache line(标记为dirty),这样CPU下次读取这条cache line里的数据的时候,才能知道这些数据不是最新的,得从内存更新。其实某条cache line被invalidate之后就没有利用价值了,等同于不存在,相当于被清空了,所以也可以算是一种flush。

cache读写

首先,需要系统的cache是enable的状态(在x86中由CR0寄存器的CD位控制),并且要读写的地址所在内存区域的属性是cachable的,CPU才会首先尝试去cache中读写。

d-cache(data cache)和i-cache(instruction cache)都是可读的,读操作可分为三种情况:

  1. 地址对应的cache line不存在,也就是cache miss,需要从外部内存读取,然后填充到对应cache line(这一过程被称为cache line fill)。
  2. 地址对应的cache line存在但被标记位了invalidate,处理方法同1是一样的。
  3. 地址对应的cache line存在,也就是cache hit(read hit),这种情况最简单了,直接读cache line就可以。

i-cache是只读的,只有d-cache是可写的(这也是为什么cache要划分成i-cache和d-cache的原因),写操作也可分为三种情况::

  1. 地址对应的cache line不存在,可以和读操作一样采用cache line fill(这一过程被称为write allocate),再改写该cache line的内容,然后标记为modified状态(intel的P6 family处理器采用),也可以直接写外部内存(intel的Pentium处理器采用)。
  2. 地址对应的cache line存在但被标记位了invalidate,同1是一样的。
  3. 地址对应的cache line存在,即write hit,和read hit略有不同的是,写完后需要将该cache line标记为modified。

相关指令

cache一致性的维护由硬件CPU自动完成,同时处理器也会提供一些指令,以支持软件对cache的操作。以x86为例,有四条指令可以对cache进行invalidate/flush.

  1. 全部invaliate/flush
  • WBINVD, 即write back invalidate的缩写,具体操作是先将cache中标记为modified的内容全部write back到外部内存,再清空整个cache。
  • INVD, 相比WBINVD少了个write back的操作,所以没法保证数据一致性,这条指令只在cache和外部内存不需要保持一致的情况下使用(如某些测试环境)。

2. 部分invalidate/flush

CLFLUSH/CLFLUSHOPT,即cache line flush的缩写,可针对某些cache lines单独操作,适用于该cache line对应的内存区域之后不会再被访问(access)到的情况。

继续阅读