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)都是可读的,读操作可分为三种情况:
- 地址对应的
cache line不存在,也就是cache miss,需要从外部内存读取,然后填充到对应cache line(这一过程被称为cache line fill)。 - 地址对应的
cache line存在但被标记位了invalidate,处理方法同1是一样的。 - 地址对应的
cache line存在,也就是cache hit(read hit),这种情况最简单了,直接读cache line就可以。
i-cache是只读的,只有d-cache是可写的(这也是为什么cache要划分成i-cache和d-cache的原因),写操作也可分为三种情况::
- 地址对应的
cache line不存在,可以和读操作一样采用cache line fill(这一过程被称为write allocate),再改写该cache line的内容,然后标记为modified状态(intel的P6 family处理器采用),也可以直接写外部内存(intel的Pentium处理器采用)。 - 地址对应的
cache line存在但被标记位了invalidate,同1是一样的。 - 地址对应的
cache line存在,即write hit,和read hit略有不同的是,写完后需要将该cache line标记为modified。
🍃 相关指令
cache一致性的维护由硬件CPU自动完成,同时处理器也会提供一些指令,以支持软件对cache的操作。以x86为例,有四条指令可以对cache进行invalidate/flush。
- 全部
invaliate/flush
WBINVD,即write back invalidate的缩写,具体操作是先将cache中标记为modified的内容全部write back到外部内存,再清空整个cache。INVD,相比WBINVD少了个write back的操作,所以没法保证数据一致性,这条指令只在cache和外部内存不需要保持一致的情况下使用(如某些测试环境)。
- 部分
invalidate/flush
CLFLUSH/CLFLUSHOPT,即cache line flush的缩写,可针对某些cache lines单独操作,适用于该cache line对应的内存区域之后不会再被访问(access)到的情况。
转载:cache之读写一致性
CPU写入数据到L1/L2/L3 cache时,不会立刻写回主存。是否写回主存、何时写回主存,取决于CPU的cache写策略(write policy),主要有以下两种:
🍃 Write-back(写回)
这是现代CPU默认且最常用的策略。
- 数据先写入
cache(如L1),不立即写回主存。 - 对应的
cache line被标记为dirty(脏)。 - 只有在以下情况之一发生时,才会写回主存:
cache line被替换(如LRU失效)CPU显式执行flush操作(如CLFLUSH)- 被其他核心通过一致性协议(如
MESI)访问到,需要同步数据
优点: 减少对主存的访问频率,性能更高 缺点: 数据可能暂时不在主存中,掉电会丢失未写回的数据(除非通过其他手段备份)
✅ 2. Write-through(直写)
- 每次写入 cache 的同时,也写入主存。
- 不存在“脏”cache line。
优点: 数据主存始终是最新的 缺点: 每次写都会访问主存,性能较差
通常用于:
- 某些嵌入式系统
- L3 cache 或共享 cache 的某些配置
- L1 instruction cache(通常是 read-only,不涉及 write)
⛳ 典型写入流程(Write-back 示例):
- CPU 执行
mov [addr], val - 若地址命中 L1 cache,就在 L1 修改该 cache line,标为 dirty
- 等待某个时机再由 L1 写回到 L2 → L3 → 主存(逐层下推)