代码之家  ›  专栏  ›  技术社区  ›  bokan

当一个核在其一级缓存中写入,而另一个核在其一级缓存中也具有相同的行时,会发生什么情况?

  •  1
  • bokan  · 技术社区  · 7 年前

    比如说英特尔天湖CPU。

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

    1 回复  |  直到 7 年前
        1
  •  6
  •   BeeOnRope    7 年前

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

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

    让我们来看一个简单的例子,其中行不在写核(C1)中,而在另一个核(C2)中处于“独占”状态。在写入地址已知的点,C1将在“总线”上发出RFO(所有权请求)事务,其中包含线路地址,其他核心将 snoop 总线并通知事务。另一个具有该线的核心将从 独家 无效的 线路的状态和值将提供给请求的核心,该核心将在 被改进的 状态,此时可以继续写入。

    注意,在这一点上,从写入核心到该行的进一步写入将快速进行,因为它处于M状态,这意味着不需要发生总线事务。在线路被逐出或其他一些核心请求访问之前,情况将一直如此。

    现在,在实际实现中有很多额外的细节,上面甚至维基百科对该协议的描述中都没有涵盖。

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

    尽管有所有这些实现细节,但基本原理是相同的:每个缓存线都有一些“每核”状态(即使该状态可以存储或复制在诸如LLC之类的中心位置),并且该状态在原子上经历逻辑转换,以确保缓存线始终保持一致。

    在这种背景下,以下是对最后两个子问题的一些具体回答:

    它是否实时更新,是否停止其中一个核心?

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

    在过去,当确实存在共享总线时,在某些情况下可能存在部分“阻止世界”行为。例如 lock x86原子指令的前缀显然是基于 CPU在执行原子事务时在总线上断言的信号。在这整个过程中,其他CPU无法完全使用总线(但据推测,它们仍然可以继续执行CPU本地指令)。

    用两个核连续写入同一缓存线的性能成本是多少?

    成本非常高,因为线路将在上述两个核心之间持续乒乓(在所述过程结束时,只需反转C1和C2的角色并重新启动)。具体细节因CPU甚至平台而异(例如,2插槽配置将大大改变这种行为),但基本上可能会看到每次写入10秒的惩罚,而不是每个周期1次写入的非共享输出。

    你可以在答案中找到一些具体的数字 this question 它涵盖了“同一物理核上的两个线程”和“独立核”的情况。

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


    1. MESI的变体通常会引入新的状态,例如 MOESI 或中的“转发”状态 MESIF . 其思想通常是使某些转换或使用模式比普通MESI协议更有效,但基本思想基本相同。