问题引入
在多核处理器模式下,多核共享内存。
CPU缓存嗅探技术(snoop)
总线仲裁(bus arbitration)保证只有一个CPU在使用总线。
选择update还是invalidate?
总线是宝贵的资源,总线带宽是独享资源。
更新的方式,需要将其他CPU的cache都更新。在总线上,存在广播风暴。即使其他CPU没有缓存该数据,也会促发广播操作,而invalidate方式可以不用发送任何消息。
invalidate可以有效降低总线带宽
MESI
- mesi协议尽量降低bus带宽
- write back回写/回填 cache:dirty cache先失效,内存后更新
MESI通过2bit表示4个cache line状态。下面的状态是缓存行的状态。
- Modified。cache被更新,与内存数据不一致。只有一个cache有此更新后的数据拷贝。其他CPU的cache都是dirty。
- Exclusive。cache数据与内存数据一致,只有一个cache缓存了此数据拷贝。
- Shared。cache数据与内存数数一致。其他cache可能也缓存了此数据拷贝。
- Invalid。cache数据无效。
- 缓存行根据内存访问事件更新状态
- 访问事件:
- 缓存访问事件
- 总线事件
- 缓存行只会更新地址匹配的状态。
缓存:
- read hit
- read miss
- write hit
- write miss
read hit
- 该缓存行必须是MES状态之一。要么是Modified状态、要么是Exclusive、要么是Shared。
- 本地cache必须是正确的。(比如,M状态下,必须本地cache已经更新完)
- 直接返回
- 状态不发生改变
read miss
- cache中不存在拷贝
- 该CPU请求总线访问主存
- 将数据从主存读到本地cache,标记为E状态(Exclusive)
- 有一个cache存在E状态(Exclusive)备份
- 该CPU请求总线访问主存
- 嗅探cache将备份数据写到总线
- 该CPU发起的主存访问被放弃
- 该CPU缓存数据
- 将这两个CPU的cache line都设置为状态S(shared)
- 其他的cache有S状态的拷贝
- 该CPU请求总线访问主存
- 其他cache仲裁出一个cache将数据拷贝写到总线
- 该CPU发起的主存访问被放弃
- 该CPU缓存数据
- 该CPU备份设置为S状态
- 其他CPU备份保持为S状态
- 一个cache有M状态的拷贝
- 该CPU请求总线访问主存
- 有M状态拷贝的CPU cache嗅探到后,将数据拷贝写到总线
- 该CPU发起的主存访问被放弃
- 该CPU缓存数据
- 该CPU备份设置为S状态
- 有M状态拷贝的CPU cache将数据写回到主存
- 有M状态拷贝的CPU cache将缓存行状态从M置为S
write hit
该CPU缓存行状态必须是MES之一。下面逐个分析每个状态的情况:
-
M
- M状态下的缓存行其实是排他的(即其他CPU缓存行肯定不存在该数据),其实已经是"dirty"状态了。
- 更新该CPU的缓存行值
- 状态无需变更
-
E
- 更新该CPU的缓存行值
- 更新该CPU缓存行状态,从E置为M
-
S
- 处理器在总线广播无效信号
- 其他CPU嗅探到信号后,将自己的S状态更新为I状态
- 更新该CPU的缓存行值
- 更新该CPU缓存行状态,从S置为M
write miss
该过程取决于该数据在其他处理器的拷贝状态。
- 其他CPU cache不存在该数据拷贝
- 从内存读取到本地cache
- 更新数据
- 设置该缓存行状态为M
- 其他CPU cache存在拷贝,要么其中一个CPU存在E状态的,要么多个CPU存在S状态的
- 从内存(难道不是其他cache嗅探到后,直接把数据放到总线上?)读取数据到本地cache。此时总线事务被标记为RWITM(read with intent to modify)带着修改的意图去读
- 其他处理器嗅探到RWITM信号,设置各自状态为I
- 该CPU更新缓存,设置状态为M
- 其他CPU cache存在拷贝,但是状态为M
- 该CPU向总线发送RWITM请求
- 存在该数据拷贝的CPU嗅探到信号后
- 阻塞RWITM请求
- 获得总线控制权
- 将修改数据写入到内存
- 将自己的状态置为I
- 该CPU向总线再次发送RWITW请求
- 当前应该是:其他处理器不存在该数据拷贝
- 从内存读取数据到本地
- 更新数据
- 设置该缓存行状态为M