Caching 在本例中,数据缓存如何路由对象?

Caching 在本例中,数据缓存如何路由对象?,caching,cpu-architecture,cpu-cache,dma,memory-model,Caching,Cpu Architecture,Cpu Cache,Dma,Memory Model,考虑图表化的数据缓存体系结构。(下面是ASCII艺术。) 假设 对象在缓存A1的脏行上阴影 同一对象的较旧版本将阴影显示在Cache2的clean行上,并且 同一对象的最新版本最近已通过DMA写入RAM 图表: -------------------------------------- | CPU core A | CPU core B | | |------------|------------| Devices | | (dirty) |

考虑图表化的数据缓存体系结构。(下面是ASCII艺术。)

假设

  • 对象在缓存A1的行上阴影
  • 同一对象的较旧版本将阴影显示在Cache2的clean行上,并且
  • 同一对象的最新版本最近已通过DMA写入RAM
图表:

  --------------------------------------
  | CPU core A | CPU core B |          |
  |------------|------------| Devices  |
  |  (dirty)   |            | with DMA |
  |-------------------------|          |
  |     (older, clean)      |          |
  |------------------------------------|
  |          (newest, via DMA)         |
  --------------------------------------
请回答三个问题

  • 如果CPU coreA尝试加载(读取)对象,会发生什么

  • 相反,如果CPU coreA尝试存储(写入)对象,会发生什么

  • 如果不是coreA,而是coreB进行加载或存储,会发生任何不明显、有趣和/或不同的情况吗

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

    注释。如果忽略窥探可以简化你的回答,那么你可以根据自己的判断忽略窥探。或者,如果修改后的问题能够更好地说明您认为的主题,您可以修改该问题。如果您必须编写代码来回答,那么我更喜欢C/C++。据我所知,您不需要在答案中指定某个或MOESI协议的特定标志,但一个更简单、不太详细的答案可能就足够了

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

    更新

    在我理解的范围内,@HadiBrais建议,与我之前绘制的架构相比,以下绘制的架构更为常见,尤其是如果实现了DDIO(见下面的答案)

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

    您假设的系统似乎包括一致、回写L1缓存和非一致DMA。除了没有二级缓存之外,一个非常类似的真实处理器是。然而,大多数现代处理器都有一致的DMA。否则,软件有责任确保一致性。图中所示的系统状态已经不一致

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

    它将只读取其本地一级缓存中保存的行。不会发生任何变化

    相反,如果CPU核心A尝试存储(写入)该对象,会发生什么 发生了什么

    在核心A的一级缓存中,这些线已经处于M相干状态。因此,它可以直接写入。不会发生任何变化

    如果:, 不是核心A,而是核心B进行加载或存储

    如果core B向同一条线路发出加载请求,则会窥探core a的一级缓存,发现该线路处于M状态。线路在二级缓存中更新,并发送到核心B的一级缓存。还会发生以下情况之一:

    • 该行从core A的一级缓存中失效。线路以E一致性状态(对于MESI协议)或s一致性状态(对于MSI协议)插入核心B的一级缓存。如果L2使用snoop筛选器,则该筛选器将更新,以指示core B的线路处于E/S状态。否则,L2中的线路状态将与核心B的L1中的线路状态相同,只是它不知道线路在那里(因此必须始终广播监听)
    • 核心A的一级缓存中的线的状态更改为s。该线以s一致性状态插入核心B的一级缓存中。L2以S状态插入该行
    无论哪种方式,一级缓存和二级缓存都将保存行的相同副本,该副本与内存中的副本不一致

    如果core B向同一行发出存储请求,该行将从core a的缓存中失效,并在core B的缓存中以M状态结束

    最终,该行将从缓存层次结构中移出,以便为其他行留出空间。发生这种情况时,有两种情况:

    • 该行处于S/E状态,因此将从所有缓存中删除它。稍后,如果再次读取该行,则DMA操作写入的副本将从主存储器中读取
    • 该行处于M状态,因此将被写回主存,并(可能部分)覆盖DMA操作写入的副本
    显然,这种非相干状态决不能发生。可以通过在DMA写入操作开始之前使所有缓存中的所有相关行无效,并确保在操作完成之前,没有内核访问要写入的内存区域来防止这种情况。每当操作完成时,DMA控制器发送一个中断。在读DMA操作的情况下,需要将所有相关行写回内存,以确保使用最新的值

    (DDIO)技术使DMA控制器能够直接从共享的最后一级缓存进行读写,以提高性能


    这一部分与问题没有直接关系,但我想把它写在某个地方

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

    除了商用x86芯片外,还有一些原型x86芯片的缓存不一致。我所知道的唯一一个例子是英特尔的(SCC),它后来发展成
      --------------------------------------
      | CPU core A | CPU core B | Devices  |
      |------------|------------| with DMA |
      |  Cache A1  |  Cache B1  |          |
      |------------------------------------|
      |              Cache 2               |
      |------------------------------------|
      |                RAM                 |
      --------------------------------------