当核心在其L1缓存中写入而另一个核心在其L1中具有相同的行时会发生什么?

时间:2017-10-18 18:48:56

标签: cpu-cache

当核心写入其L1缓存而另一个核心在其L1中具有相同的行时会发生什么?

请说一下英特尔Skylake CPU。

缓存系统如何保持一致性?它是否实时更新,是否会阻止其中一个核心? 使用两个内核连续写入相同缓存行的性能成本是多少?

1 个答案:

答案 0 :(得分:5)

通常,现代CPU使用MESI协议的一些变体 1 来保持缓存一致性。

在L1写入的场景中,细节取决于缓存行的现有状态:缓存行是否已经存在于写入核心的缓存中?在另一个核心中,缓存行处于什么状态,例如,它是否被修改过?

让我们看一下这条线已经不在写入核心(C1)中的简单情况,并且它位于" exclusive"状态在另一个核心(C2)。在已知写入地址的位置,C1将向"总线"发出RFO(所有权请求)事务。使用该行的地址,其他核心将snoop总线并注意到该事务。然后,具有该行的另一个核心将其行从独占转换为无效状态,并且该行的值将被提供给请求核心,将在修改状态下使用它,此时写入可以继续。

注意,此时,写入内核对该行的进一步写入很快就会进行,因为它处于M状态,这意味着不需要进行总线事务。在线路被驱逐或其他核心请求访问之前就是这种情况。

现在,实际实施中还有很多其他细节,上面没有涉及,甚至还没有在协议的维基百科描述中。

例如,基本模型涉及每个CPU一个私有缓存和共享主内存。在这个模型中,核心C2通常会将共享线路的值提供给总线,即使它没有对其进行修改,因为这比等待从主存储器读取值要快得多。但是,在最近的所有x86实现中,都有一个 shared 最后一级L3缓存,它位于所有私有L2和L1缓存以及主内存之间。此缓存通常为inclusive,因此它可以直接向C1提供值,而无需从C2执行缓存到缓存传输。此外,拥有这个共享缓存意味着每个CPU实际上可能不需要窥探"总线"因为可以首先查询L3高速缓存以确定哪个(如果有的话)核实际上具有该行。然后,只有具有该行的核心才会被要求进行状态转换。推动模型而不是拉动。

尽管有这些实现细节,但基本原理是相同的:每个缓存行都有一些"每个核心"状态(即使这种状态可以存储或复制在像LLC这样的某个中心位置),并且该状态在原子上经历逻辑转换,以确保高速缓存行始终保持一致。

鉴于背景,以下是最后两个子问题的具体答案:

  

是否实时更新,是否会阻止其中一个核心?

任何现代核心都将实时执行此操作,并且还可以并行执行不同的缓存行。这并不意味着它是免费的!例如,在上面的描述中,C1的写入被停止,直到高速缓存一致性协议完成,这可能是几十个周期。与普通写入相比,只需几个周期。还存在带宽问题:用于实现协议的请求和响应使用可能具有最大吞吐量的共享资源;如果一致性交易的速度超过某个限制,即使它们是独立的,所有请求也可能会减慢。

在过去,当真正有一辆共用公交车的时候,可能会有一些局部的“停止世界”。在某些情况下的行为。例如,x86原子指令的lock前缀显然是根据CPU在进行原子事务时在总线上断言的lock信号命名的。在整个期间,其他CPU无法完全使用总线(但可能他们仍然可以继续使用CPU本地指令)。

  

在具有两个内核的同一缓存行中连续写入的性能成本是多少?

成本非常高,因为如上所述,线路将在两个核心之间连续乒乓(在所描述的过程结束时,只需反转C1和C2的角色并重新启动)。确切的细节因CPU甚至平台而有很大不同(例如,2插槽配置会大大改变这种行为),但基本上可能会考虑每次写入10次循环与1次非共享输出的罚分。每个周期写一次。

你可以在this question的答案中找到一些特定的数字,它们涵盖了同一物理核心上的两个线程"案例和"单独的核心"情况下。

如果您想了解有关特定性能方案的更多详细信息,您应该提出一个单独的具体问题,列出您感兴趣的特定行为。

1 MESI的变化经常引入新的状态,例如"拥有的" MOESI中的州或者#34; Forwarded" MESIF中的州。这个想法通常是为了使某些过渡或使用模式比普通的MESI协议更有效,但基本思想大致相同。