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

     2023-02-16     240

关键词:

【中文标题】在此示例中,数据缓存如何路由对象?【英文标题】:How do data caches route the object in this example? 【发布时间】:2019-02-11 19:09:17 【问题描述】:

考虑图表数据缓存架构。 (ASCII艺术随后。)

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

假设

一个对象在缓存 A1 的 dirty 行上出现阴影, 同一对象的旧版本在缓存 2 的 clean 行上被遮蔽,并且 同一对象的最新版本最近已通过 DMA 写入 RAM。

图表:

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

请提三个问题。

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

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

    如果加载或存储的是内核 A 而不是内核 B,是否会发生任何不明显、有趣和/或不同的事情?

我的问题是理论上的。我的问题不涉及任何特定的 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                 |
  --------------------------------------

【问题讨论】:

你所说的“阴影”是什么意思?此外,您的示例表明您假设 DMA 是非连贯的。需要明确的是,这是故意的吗? @HadiBrais 澄清提出问题的层次:我是一名 Debian 开发人员,受过电气工程教育。我的专业领域不是计算机,而是建筑,所以我主要是在计算机方面自学。如果“阴影”是错误的词,请纠正我!关于 DMA,我确实一直假设 DMA 是非连贯的,但 PCI 等对我来说并不为人所知。我提到 DMA 只是为了简化问题。 (否则,问题可能需要四个 CPU 内核和一个三级缓存,这会不必要地复杂化。) 特别是回答您的第一个问题,通过“隐藏 X”,我的意思是“暂时保留 X 的不完全同步、可能可修改的副本以供本地使用,并在必要时用于以后刷新。” 现代 x86 具有缓存一致性 DMA。我认为当 x86 CPU 开始将内存控制器放在芯片上时,这成为了一件事情,因此在通往内存的路上窥探 L3 标签变得实用(并且英特尔的包容性 L3 标签用作私有每核缓存的窥探过滤器)。拥有一致的 DMA 可能会使激进的硬件预取更容易实现,而不必担心在分支错误预测的奇怪极端情况下会产生退相干,从而导致刚刷新的内存中出现不需要的推测性负载。 【参考方案1】:

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

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

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

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

这些行在核心A的L1缓存中已经处于M一致性状态,所以可以直接写入。不会发生任何变化。

如果发生任何不明显、有趣和/或不同的事情, 而不是核心A,核心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 卡形式的英特尔至强融核)内部完全一致。协处理器是 PCIe 互连上的设备,与其他协处理器或 CPU 不一致。因此,协处理器位于它自己的一个单独的相干域中。我认为这是因为没有内置的硬件机制可以使具有缓存的 PCIe 设备与其他 PCIe 设备或 CPU 保持一致。

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

【讨论】:

@thb:如果在 L1d 中是脏的,那么在 L2 中拥有 (older, clean) 副本是不可能的。正如哈迪所说,这已经是语无伦次了。但不仅是 RAM,缓存级别之间也是如此。 MESI 要求如果一行在任何缓存中处于修改(脏)状态,则所有 其他 缓存都将其设为无效。 (通常一行在从 L1 驱逐之前不会被写回,所以我们最终会在 L2 中得到 Modified 而在其他 L1 中是 Invalid。但是有一种机制可以让内部缓存能够在 L2 的脏线实际出现之前读取它的副本回写。) 纯原始 MESI 是关于保持 单独 缓存的一致性(例如,多个内核,每个内核都有自己的私有缓存),而不是具有共享最后一级缓存的层次结构。这就是为什么它谈论窥探内存总线的原因。 (我想就这个问题发表之前的评论,但把它放在这里以防哈迪想要更新答案以解决这个问题,初始状态超出了 DMA 不连贯性,进入无效的 MESI 状态。)跨度> @PeterCordes 我将(older, clean) 解释为该行存在于E 状态。一个实现可以检查如果 L2 的线路处于 E 或 M 状态,那么它必须窥探所有私有缓存。同样在另一个实现中,MESI 只能在 L1 上实现,而 SI 可以在包容性 L2 上实现。在这种情况下,如果任何核心在其私有缓存中未命中并在 L2 中命中,它必须始终窥探所有私有缓存。这效率较低,但在 L2 需要较少的硬件。如果 L2 不包含在内,则无论 L2 中有命中还是未命中,都必须发送窥探... ...MESI 协议基本上只在您进入 L1 时才重要。如果 OP 打算让 MESI 在 L2 并且意味着该线路在那里处于 S 状态,那么它确实是不连贯的,因为另一个内核可以读取 L2 中的陈旧版本(不连贯的 DMA 除外)。 为什么系统应该有一致的缓存?是否有可能在核心之间有一个不连贯的公共 L2,不是吗?英特尔 SCC 就是这种类型的东西(尽管它在内核之间没有公共缓存)。

java示例代码_我们如何在应用程序范围中存储数据以用于缓存

java示例代码_我们如何在应用程序范围中存储数据以用于缓存 查看详情

如何在此表中激活排序?

】如何在此表中激活排序?【英文标题】:Howtoactivatesortinginthistable?【发布时间】:2017-09-0716:29:14【问题描述】:我正在使用DataTable插件。链接页面中的示例很棒。但我有一个问题。在示例中,用户可以在搜索后对数据表进行排... 查看详情

在此示例中,如何强制 EF 仅更新 Db 中的一列?

】在此示例中,如何强制EF仅更新Db中的一列?【英文标题】:HowtoEnforceEFtoupdateonlyonecolumnintheDbinthisexample?【发布时间】:2013-12-1218:54:19【问题描述】:我想要实现的是只更新数据库中实体的特定属性。(模仿UPDATEFooSetStatus=\'kool\'... 查看详情

如何解决尝试将对象数组中的数据存储到新对象中的错误

...jectsintonewone【发布时间】:2017-09-2808:24:00【问题描述】:在此代码中,我尝试从Web服务中获取tripID和NoteID并将它们存储在行程中,然后通过读取trips[i].noteID缓存来自其他Web服务的其他参数,但会发生错误:pub 查看详情

springboot缓存教程示例(代码片段)

在本SpringBoot教程中,学习如何从Spring框架缓存支持中轻松管理应用程序缓存。Spring在缓存方面有一些很好的特性,Spring缓存API的抽象使用起来非常简单。1、缓存是什么?缓存是一种增强系统性能的机制。它是位于应用程... 查看详情

springboot缓存教程示例(代码片段)

在本SpringBoot教程中,学习如何从Spring框架缓存支持中轻松管理应用程序缓存。Spring在缓存方面有一些很好的特性,Spring缓存API的抽象使用起来非常简单。1、缓存是什么?缓存是一种增强系统性能的机制。它是位于应用程... 查看详情

在java中同步string对象

...能测试,特别是在我们希望有几百个用户访问同一页面并在此页面上每10秒点击一次刷新的功能。我们发现我们可以使用此功能进行改进的一个方面是在一段时间内缓存来自Web服务的响应,因为数据没有变化。在实现这个基本缓... 查看详情

java示例代码_在EclipseLink中打印存储在隔离缓存中的对象

java示例代码_在EclipseLink中打印存储在隔离缓存中的对象 查看详情

java示例代码_如何在此任务中仅运行一次任务

java示例代码_如何在此任务中仅运行一次任务 查看详情

hibernate脏检查和刷新缓存机制

刷新缓存:  Session是Hibernate向应用程序提供的操作数据库的主要接口,它提供了基本的保存,更新,删除和加载java对象的方法,Session具有一个缓存,可以管理和追踪所有持久化对象,对象和数据库中的相关记录对应,在某些时间点,Sessio... 查看详情

如何在 Rails 中缓存模型对象?

...首先在memcached中搜索结果,只有在没有找到结果时才会对数据库?理想情况下,我希望解决方案是隐式的,这样我就可以编写Model.find(id),它首先检查缓存,如果需要 查看详情

PHP 持久化缓存数据

...乎)永远不会改变的大数据来干扰数据库。另外,我无法在此环境中添加模块(如APC缓 查看详情

java具有多个对象流的列表:在此示例中,将列值,titlevalue和titlesortvalue赋予列表。在迭代l(代码片段)

查看详情

java示例代码_JTable:如何从绑定到数据源的表中获取所选对象

java示例代码_JTable:如何从绑定到数据源的表中获取所选对象 查看详情

jQuery.getJSON:如何避免在每次刷新时请求 json 文件? (缓存)

...fresh?(caching)【发布时间】:2012-11-3022:33:09【问题描述】:在此示例中,您可以看到生成的HTML列表。每次刷新时,脚本都会请求数据文件(ajax/test.json)并再次构建列表。生成的文件“ajax 查看详情

如何通过 ID 从 Apollo 缓存中读取嵌套对象?

...顶层组件中使用一个GraphQL查询来获取我需要的几乎所有数据。在组件树更下方的 查看详情

如何在 Flutter 中缓存 Firebase 数据?

】如何在Flutter中缓存Firebase数据?【英文标题】:HowtocacheFirebasedatainFlutter?【发布时间】:2019-12-1414:17:03【问题描述】:在我的应用中,我使用Firebase中的数据构建了一个对象列表。在StreamBuilder中,我检查快照是否有数据。如果... 查看详情

如何禁用 Express 4 应用程序中某些路由的缓存?

】如何禁用Express4应用程序中某些路由的缓存?【英文标题】:HowtodisablecachingforsomeroutesintheExpress4applications?【发布时间】:2021-06-2514:41:13【问题描述】:我试过这些例子:Removingallheadersfromexpress.js这个DisableetagHeaderinExpressNode.js和... 查看详情