0

Core A 将值 x 写入 storebuffer,等待无效的 ack,然后将 x 刷新到缓存。它是只等待一个 ack 还是等待所有 ack ?它如何知道所有 CPU 中有多少 ack?

4

1 回答 1

3

我不清楚您所说的“无效确认”是什么意思,但我们假设您的意思是来自另一个请求同一行所有权的核心的窥探/无效。

在这种情况下,存储缓冲区中的存储通常可以自由地忽略来自其他内核的此类无效,因为存储缓冲区中的存储还不是全局可见的。商店只有在他们退休后的某个时间提交到 L1 时才会全局可见。在这一点1缓存控制器将对关联行发出 RFO(所有权请求),如果它尚未在缓存中。基本上在这一点上,商店变得全球可见。L1 缓存控制器不需要知道有多少其他失效在进行中,因为它们是由系统中的一些更高级别的组件作为 MESI 协议的一部分进行调解的,并且当它们获得处于 E 状态的线路时,它们保证他们是独家所有者。

简而言之,来自其他核心的失效对存储缓冲区2中的存储几乎没有影响,因为它们在基于 RFO 请求的单个点处变得全局可见。是已经执行该区域的负载更有可能由另一个核心上的无效活动产生,特别是在不允许可见的负载-负载重新排序的强平台上,例如 x86。例如,x86 上所谓的 MOB 负责跟踪失效是否可能破坏排序规则。

RFO 响应

也许您所说的“acks”是其他内核对写入内核请求获取或升级其对该行的所有权以便它可以写入该行的请求的响应:即,使其他 CPU 中的行副本无效等在。

这通常称为发出 RFO,当成功时,请求核心中的线路将处于 E 状态。

大多数 CPU 都是分层的,各种不同的代理一起工作以确保一致性。在实践中,这意味着 CPU 不需要等待来自 N CPU 系统上其他 N-1 个内核的最多 N-1 个“ack”,而只需等待来自更高级别组件的单个回复,该组件本身负责发送和收集来自其他 CPU 的响应。

一个示例可能是具有私有 L1 和 L2 以及共享 L3 的单插槽多核 CPU。核心可能会将其 RFO 向下发送到 L3,L3 可能会向所有核心发送无效请求,等待它们的响应,然后向发出请求的核心确认 RFO 请求。或者,L3 可能会存储一些位,这些位指示哪些内核可能拥有该行的副本,然后它只需将请求发送到这些内核(在这种情况下,L3 所扮演的角色有时被称为窥探)备案人)。

由于代理之间的所有通信都通过 L3,因此它能够保持任何一致。在多套接字系统的情况下,事情变得更加复杂:本地核心上的 L3 可能会再次获得请求并将其传递给另一个套接字以在那里执行相同类型的失效。同样可能存在窥探过滤器的概念,或者可能存在其他概念并且行为甚至可能是可配置的!

例如,在英特尔的 Broadwell Xeon 架构中,有四种不同的可配置窥探模式

Broadwell 提供四种不同的探听模式,重新引入 Home Snoop with Directory 和 Opportunistic Snoop Broadcast(HS with DIR + OSB)以前在 Ivy Bridge 上可用,以及在 Haswell、Early Snoop、Home Snoop 和 Cluster on Die 上可用的三种探听模式模式 (COD)。表 5 映射了内存带宽和延迟权衡,这些权衡将在每种不同模式下有所不同。大多数工作负载会发现 Home Snoop with Directory 和 Opportunistic Snoop Broadcast 将是最佳选择。

...具有不同的性能权衡:

英特尔 Snoop 模式权衡

该文档的其余部分详细介绍了各种模式的工作原理。

所以我想简短的回答是“它很复杂,取决于详细的设计,甚至可能是用户可配置的设置”。


1或者可能在更早的某个时间点,因为优化的实现可能会在存储缓冲区中“向前看”并为即将到来的存储发出 RFO(所谓的“RFO 预取”),甚至在它们成为最高级存储之前。

2然而,失效可能会使第一个脚注中提到的 RFO 预取复杂化,因为这意味着存在一个窗口,其中行可以被另一个内核“偷回来”,从而使 RFO 预取浪费工作。一个复杂的实现可能有一个预测器,它根据监控是否发生这种情况来改变 RFO 预取积极性。

于 2018-05-27T21:28:31.773 回答