经典内存系统一致性
M5 2.0b4引入了一个经过大幅重写和精简的缓存模型,包括一个新的一致性协议。(旧的2.0版本之前的缓存模型已经被修补以适应2.0beta引入的新内存系统,但没有重写以利用新内存系统的功能。)
新一致性协议的关键特性是设计为适应或多或少任意的缓存层次结构(每个多层级缓存)。相比之下,旧协议将共享限制在单个总线上。
在现实世界中,系统架构对协议可以设计的缓存数量或配置有一定限制。设计一个完全真实且高效的协议以适应任意配置是不切实际的。为了使我们的协议能够在(几乎)任意配置下工作,我们目前在真实性和可配置性上做了一些妥协。我们的目标是,该协议对于研究系统行为其他方面(而非一致性机制)的研究人员来说是足够的。专门研究一致性的研究人员可能需要用他们正在研究的具体协议实现来替换默认的一致性机制。
该协议是一个MOESI监听协议。不强制包含性;在多核处理器配置中,如果多个L1缓存的总容量占共享的L2缓存容量的相当一部分,那么强制包含性会非常低效。
上层缓存(即靠近CPU的缓存)的请求以预期的方式向内存传播:L1未命中会在本地L1/L2总线上广播,由总线上的其他L1监听(如果没有响应)并由L2服务。如果在L2未命中,那么在一定延迟后(目前设置为等于L2命中延迟),L2会在其内存侧总线上发出请求,可能被其他L2监听,然后发出给L3或内存。
不幸的是,以类似方式逐级向上层传播监听请求会导致众多几乎无法解决的竞争条件。实际上,真正的系统通常不会这样做;通常希望在L2总线上进行一次监听操作即可获知整个L1/L2层次结构中块的状态。有几种方法可以实现这一点:
-
仅监听L2,但强制包含性,这样L2就拥有所有关于L1的信息——这一点我们已经在上面否定了。
-
在L2中为所有L1保留一套额外的标签,这样可以同时监听它们(参见Compaq Piranha)——这在层次结构不太深时是合理的,但现在你必须根据上层缓存的数量、大小和配置来调整下层缓存中的标签大小,这会导致配置上的困难。
-
与L2并行监听L1,如果它们都在同一芯片上,这并不难(我相信Intel在Pentium Pro中开始这样做;不确定他们是否在Core2芯片中继续这样做,或者AMD是否也这样做,但我怀疑如此)——这也是合理的,但为这些监听添加显式路径会使配置过程变得非常繁琐。
我们通过引入“快速监听”解决了这个难题,这是一种特殊的监听请求,可以在层次结构中瞬间且原子地传播(类似于内存系统页面中描述的原子模式访问),即使系统在定时模式下运行。功能上,这种方式与上述选项2或3非常相似,但由于监听沿着常规总线互连传播,因此没有额外的配置开销。这确实引入了一些时间不准确性,但如果我们假设实际硬件中有专门的路径用于这些监听(或用于在低层缓存中维护上层标签的额外副本),那么这些差异可能是次要的。
(更多内容待续:缓存如何知道其请求已完成?以及其他有趣的问题……)
注意:截至2.0b4版本,该协议仍有一些漏洞,特别是如果你有多个L2,每个L2后面有多个L1,但我相信它适用于2.0b3中可行的任何配置。