在此示例中,数据缓存如何路由对象?

时间:2019-02-11 19:09:18

标签: caching cpu-architecture cpu-cache dma memory-model

考虑图解数据缓存体系结构。 (随后是ASCII艺术。)

  --------------------------------------
  | CPU core A | CPU core B |          |
  |------------|------------| Devices  |
  |  Cache A1  |  Cache B1  | with DMA |
  |-------------------------|          |
  |         Cache 2         |          |
  |------------------------------------|
  |                RAM                 |
  --------------------------------------

假设

  • 一个对象在缓存A1的行上被遮盖,
  • 同一对象的旧版本在Cache 2的 clean 行上显示为阴影,并且
  • 同一对象的最新版本最近已通过DMA写入RAM。

图:

  --------------------------------------
  | CPU core A | CPU core B |          |
  |------------|------------| Devices  |
  |  (dirty)   |            | with DMA |
  |-------------------------|          |
  |     (older, clean)      |          |
  |------------------------------------|
  |          (newest, via DMA)         |
  --------------------------------------

请问三个问题。

  1. 如果CPU内核A尝试加载(读取)对象,会发生什么?

  2. 相反,如果CPU内核A尝试存储(写入)对象,会发生什么?

  3. 如果不是装载核心B,而是装载核心B,而不是核心A,会发生什么不明显,有趣和/或不同的事情?

我的问题是理论性的。我的问题不涉及任何特定的CPU体系结构,但如果愿意,您可以在答案中涉及x86或ARM(甚至RISC-V)。

注意事项。如果不使用监听功能可以简化您的回答,那么您可以自行决定不使用监听功能。或者,如果修改后的问题可以更好地说明您的观点,则可以修改问题。如果您必须编写代码来回答问题,那么我希望使用C / C ++。据我所知,您无需在答案中命名MESI或MOESI协议的特定标志,但是更简单,更详细的答案可能就足够了。

动机。我要问的动机是,我正在阅读有关C ++标准中的并发和内存模型的信息。如果可能的话,我想学习大致在硬件操作方面可视化该模型。

更新

据我所知,@ HadiBrais建议以下图解架构比我之前图解的架构更常见,尤其是如果实现了DDIO(请参见下面的答案)。

  --------------------------------------
  | CPU core A | CPU core B | Devices  |
  |------------|------------| with DMA |
  |  Cache A1  |  Cache B1  |          |
  |------------------------------------|
  |              Cache 2               |
  |------------------------------------|
  |                RAM                 |
  --------------------------------------

1 个答案:

答案 0 :(得分:4)

您的假设系统似乎包括相干的回写L1高速缓存和不相干的DMA。 ARM11 MPCore是一个非常相似的真实处理器,只是它没有二级缓存。但是,大多数现代处理器的确具有连贯的DMA。否则,确保一致性是软件的责任。如图所示,系统状态已经不一致。

  

如果CPU内核A尝试加载(读取)对象,会发生什么?

它将仅读取保存在其本地L1缓存中的行。不会发生任何变化。

  

相反,如果CPU内核A尝试存储(写入)对象,那么   发生了吗?

在核心A的L1高速缓存中,这些行已经处于M相干状态。因此它可以直接对其进行写入。不会发生任何变化。

  

如果发生以下任何非显而易见,有趣和/或不同的事情,   而不是核心B,核心B是否进行了加载或存储?

如果核心B向同一行发出了加载请求,则将侦听核心A的L1高速缓存,并且发现该行处于M状态。该行将在L2高速缓存中更新,并发送到核心B的L1高速缓存。还将发生以下情况之一:

  • 该行从内核A的L1缓存中无效。该行以E一致性状态(在MESI协议的情况下)或S一致性状态(在MSI协议的情况下)插入核心B的L1缓存中。如果L2使用探听过滤器,则更新过滤器以指示核心B的线路处于E / S状态。否则,L2中的线路状态将与核心B的L1中的线路状态相同,只是它不知道它的存在(因此监听必须始终进行广播)。
  • 核心A的L1高速缓存中的行状态更改为S。该行以S相干状态插入核心B的L1高速缓存中。 L2将线插入为S状态。

无论哪种方式,L1高速缓存和L2高速缓存都将保存该行的相同副本,而这与内存中的副本保持不一致。

如果核心B向同一行发出存储请求,则该行将在核心A的缓存中无效,并在核心B的缓存中以M状态结束。

最终,该行将从高速缓存层次结构中逐出,为其他行腾出空间。发生这种情况时,有两种情况:

  • 该行处于S / E状态,因此只需将其从所有缓存中删除即可。稍后,如果再次读取该行,则将从主存储器读取通过DMA操作写入的副本。
  • 该行处于M状态,因此它将被写回到主存储器,并(可能部分地)覆盖由DMA操作写入的副本。

显然,这种不相干状态绝对不能发生。通过在DMA写操作开始之前使所有高速缓存中的所有相关行无效,并确保在操作完成之前确保没有内核访问要写入的内存区域,可以防止这种情况发生。每当操作完成时,DMA控制器都会发送一个中断。如果是读取DMA操作,则所有相关行都需要写回到内存中,以确保使用最新的值。

Intel Data Direct I/O(DDIO)技术使DMA控制器可以直接从共享的最后一级缓存中读取或写入数据,以提高性能。


本节与问题没有直接关系,但我想将此内容写在某个地方。

所有商用x86 CPU都是完全缓存一致的(即整个缓存层次结构是一致的)。更准确地说,同一共享内存域中的所有处理器都是高速缓存一致的。此外,所有商用x86多核协处理器(即PCIe卡形式的Intel Xeon Phi)在内部都是完全一致的。作为PCIe互连上的设备的协处理器与其他协处理器或CPU不协调。因此,协处理器驻留在其自己的单独的一致性域中。我认为这是因为没有内置的硬件机制可以使具有与其他PCIe设备或CPU一致的缓存的PCIe设备。

除商用x86芯片外,还有一些原型x86芯片不具有缓存一致性。我知道的唯一例子是英特尔的Single-Chip Cloud Computer(SCC),后来演变为连贯的Xeon Phi。