重点#
- 缓存命中时两种写法:全写、回写的计算
- 了解未命中时的处理方法
1. 缓存一致性#
因为 cache 中的内容是主存块副本,当对 cache 中的内容进行更新时,就存在 cache 和主存如何保持一致的问题。除此之外,以下情况也会出现 cache 一致性问题:
- 多个 I/O 设备访问主存时:如果 CPU 修改了 cache 中的内容,且没有同步到主存,则会造成数据不一致的问题,导致读入 I/O 设备的数据无效
- 多核 CPU 共存问题:每个 CPU 都有着自己的 cache,如果多个 cache 里存储着主存里地址相同的数据块,当某个 CPU 修改了 cache 里的内容,主存此时未同步,会导致其他 CPU 里的 cache 存储的数据以及主存存储的数据无效
一致性需要满足两个条件,最关键的操作就是写操作的同步:
- 写传播:一个 CPU 对某数据的写操作,最终要能被其他 CPU 看到和知道
- 写串行:同一地址的所有写操作,在所有 CPU 看来顺序一致
一般写命中时有两种写方法:全写法、回写法;写缺失时有两种方法:写分配法、非写分配法。
二者搭配使用,例如:全写法 + 非写分配法
2. 写缺失时#
写缺失时有有两种方法:写分配法、非写分配法。
2.1. 写分配法
写分配法(Write-Allocate)的规则是:先更新主存块的目标存储单元,再选择一个 cache 行,把更新后的主存块复制到该 cache 行。即先写主存,再送入 cache。
2.2. 非写分配法
非写分配法(No-Write-Allocate)的规则是:只更新主存单元,不把目标主存块写入 cache。
二者区别很明显:都写入主存块的目标单元,但是否写入 cache?
3. 全写法#
全写法和回写法都是缓存命中是的写规则
规则:写命中时,同时写入主存和缓存。
该方式的做法可保证 cache 和主存始终同步,因此替换 cache 行时,可直接覆盖,不需要担心数据不一致的问题而进行写回(将数据从 cache 写回主存块),通常也被称为通写法或直写法。
但是,这种方法会大大增加写操作的开销(因为主存写速度较慢,会增加 CPU 延时)。例如,假定一次写主存需要 100 个 CPU 时钟周期,那么 的存数指令就使得 CPI 增加了 个时钟。
为了减少写主存的开销,通常在 cache 和主存之间加一个写缓冲(write buffer)。在 CPU 写 cache 的同时,也将信息写人写缓冲,然后由存储控制器将写缓冲中的内容写人主存。写缓冲是一个 FIFO 队列,只有少量空间,在写操作频率不是很高的情况下,因为 CPU 只需将信息写快速的写缓冲而无须写慢速的主存,因而效果较好。但是,如果写操作频繁发生,则会使写缓冲饱和而发生阻塞。

4. 回写法#
回写法的规则是:写命中时,只写入缓存。只有该缓存行被替换时,才写回主存。
即:命中 只写入缓存(不写入主存) 触发替换算法 缓存写回主存。
由此可见,该方式实际上采用的是回头再写或最后一次性写的做法,因此通常被称为回写法或一次性写方式,也有教材称之为写回法。
在 CPU 执写操作时,回写法不会更新主存单元,只有当 cache 中的主存块被替换时,才将该块内容一次性写回主存。这种方式的好处在于减少了写主存的次数,因而大大降低了主存带宽需求。
为了减少写回主存块的开销,每个 cache 设置了一个修改位(dirty bit,也称“脏位”)。
- 若脏位为 1,则说明对应 cache 中的主存块被修改过,替换时需要写回主存
- 若脏位为 0,则说明对应主存块未被修改过,替换时无须写回主存
注意到,由于回写法没有同步更新 cache 和主存内容,所以存在 cache 和主存内容不一致而带来的潜在隐患。通常需要其他的同步机制来保证存储信息的一致性。
5. 常用搭配#
回顾四种写规则:
写命中下,
- 全写法:缓存和主存同时写入;由于主存速度较慢,会增大部分时间开销
- 回写法:只写入缓存;只有该 cache 行被替换时,才从缓存写回主存;由于 cache 和主存不同步,存在不一致性隐患
写缺失下,
- 写分配法(Write-Allocate):先更新目标主存块里的数据单元,再把主存块放入缓存。(先更新,再复制)
- 非写分配法(No-Write-Allocate):只更新主存块的数据,不写入缓存。(只更新,不复制)
常用的搭配:
| 组合 | 作用 |
|---|---|
| 全写法 + 非写分配 | 命中时,同时写入 cache 和主存;缺失时,只写入主存,不放入 cache |
| 回写法 + 写分配 | 命中时,只写入 cache;缺失时,先把主存块送入 cache,再在 cache 里更新 |
提问:为什么 “回写法 + 写分配” 策略中,缺失时是先把主存块送入 cache 再更新,而不是直接先更新主存块的数据单元,再把主存块送入 cache ?
回复提问:因为回写法的核心思想是:减少主存的写入次数,尽可能提高数据的写入速度(显然 CPU 写入 cache 的速度远比写入主存的速度快)。
因此虽然通用的 “写分配” 策略是先更新主存,再送入 cache,但在实际与回写法组合使用时,应遵循回写法的思想,先把主存块送入 cache,再在 cache 里更新,同时脏位标记为 1,主存块等被替换时再写回主存。这样写缺失时不写入主存,只有替换时才写。
即原文的:“若写缺失,则在 cache 中分配一行,将主存块调入该 cache 行中并更新相应单元的内容。因此,该方式下在写不命中时,通常采用写分配法进行写操作。”