概述

 随着多核 CPU 的发展,每个 CPU 中都有自己专用的缓存(比如 L1,L2)。当 CPU 处理数据时,会从共享缓存(比如 L3 缓存)中读取数据,然后在本地缓存中进行操作。如果 CPU 每次修改本地缓存的数据都将其写回下层缓存,并且在此期间,其他处理器并不会对该数据进行修改,那么这似乎并不会发生什么问题。但是,这样串行化执行必然会对性能造成影响。但是如果不串行化执行,一个处理器对一个过期的数据进行了操作,那就会造成数据不一致的问题,这就是著名的缓存一致性问题

为了解决缓存一致性问题,人们提出了缓存一致性协议。实现缓存一致性协议的关键在于跟踪数据块的共享状态。目前的协议有两类:

  • 目录式:存储器的共享状态保存在一个目录中,通过查看目录来跟踪数据块的状态
  • 监听式:缓存拥存储器块中的数据副本,所有缓存通常都可以通过某种介质访问,所有缓存监视器都监听这个介质,以跟踪数据块的状态

本文介绍的式 MESI 协议,它属于监听式协议。监听式协议有两种实现方法:

  • 写入失效:确保处理器在写入某一数据项之前,获取对该数据项的独占访问。因此进行读操作的处理器所保留的副本必须都失效,强制读取新副本;进行写操作的处理器都禁止写入,直到可以读取新副本
  • 写入更新:写入一个数据项时,更新该数据项的所有缓存副本。因此必须将所有写入操作都广播到共享缓存线上

MSI 协议

MSI 实现的时写入失效协议。写入失效协议的关键在于使用总线或其他广播介质来执行失效操作,强制其他处理器读取最新的版本。

在 MSI 中,除了设置缓存的有效位外,它还加入了两个新状态:共享状态(shared)和已修改状态(modified),MSI 就是这三个状态的缩写。

  • 共享状态:表明缓存块可能被共享,比如多个处理器可能同时共享一个缓存块(注意这里共享应给缓存块指的是共享下层存储设备的数据块)
  • 已修改状态:表明处理器已经对缓存块进行了修改,同时这个缓存块处于独占状态,即其他处理器并没有该数据块的缓存。
  • 无效状态:处理器还没有将数据库加载到专用缓存块
MSI
MXX
SX
I

当处理器读取一个数据时,会触发读取会缺失事件,这时他会将读取确实消息放到总线上,然后将数据块复制到当前处理器的本地缓存中,这时本地缓存的缓存块处于共享状态。

当处理器对本地缓存进行写操作时,会将失效操作在总线上广播。其他处理器监听到失效命令后会检查本地缓存中是否有该缓存块,如果有,将本地缓存块设置为失效状态。当前处理器会将本地缓存设置为已修改状态,并对其进行修改。如果另外一个处理器发出了读取操作,那么缓存块会从已修改状态变为共享状态。

MSI 协议的状态转换图如下所示:

MESI 协议

对于 MSI 协议来说,如果一个处理器发起写操作时,发现本地缓存中没有缓存该数据,那么他就需要先发起应一个读操作,将数据块读取到本地缓存,这时缓存块处于共享状态。但是处理器又会对其进行写操作,该缓存块又会从共享状态变为已修改状态,并在总线上广播失效操作。但是此时其他处理器并没有该数据块的缓存,因此会造成一次无效的总线操作。

MESI 为了解决这一点,引入了一个独占状态(exclusive)。如果只有一个处理器读取数据块中的数据时,将缓存块设置为独占状态。当对数据进行写操作时,由于处于独占状态,意味着其他处理器并没有缓存该数据块,所以可以直接修改本地缓存,并将缓存块设置为已修改状态而不需要在总线上广播失效操作。

MESI
MXXX
EXXX
SXX
I

MESI 的状态转换图如下:

参考资料

《计算机体系结构 量化研究方法》