作为一致性原理的基础,CPU 的一致性协议是非常重要的一环。本篇学习笔记包括内存一致性、缓存一致性以及一些常见的缓存一致性协议介绍。
在讨论共享内存问题时,本文所使用的系统基准模型如下图所示,即系统中存在多个核心,每个核心中都包含各自的私有缓存,这些核心共享一个最低层级的缓存。本文后续的内容中将会以缓存指代核心的私有缓存而使用 LLC(Last-Level Cache) 指代多核共享的缓存。
一、一致性原理
现代计算机体系架构中大多采用多核处理器或者多处理器的架构设计,这样的设计能够直接提升系统的并发度进而提升整体的性能,而这些多核或者多处理器之间会共享使用内存。多核或者多处理器的设计能带来收益的前提都是内存能够在其中正确地共享。
在共享内存的研究中,一致性原理通常分为两个维度 ,即 Consistency 和 Coherence,这是两个密切相关但各自侧重不同的术语。
1.2 Coherence(缓存一致性)
Coherence 是关于单一内存位置的所有缓存副本的一致性问题,它保证了多个处理器对某一个特定数据块的读写操作遵循一定的规则,避免产生不一致的副本。具体来说,缓存一致性要求:不允许同一个内存位置的缓存副本在不同的处理器中出现不一致的值。也就是说,如果一个处理器写入了某个内存位置,其他处理器后续的读取操作必须能够看到这个最新写入的值。此外,要遵循 Single-Writer-Multiple-Reader (SWMR) 模型,即在任意时刻,只有一个处理器可以写入该内存位置,而可以有多个处理器同时读取。
缓存一致性协议(如 MESI、MOESI)通过维护缓存状态和控制写入/读取时的广播机制来确保数据的一致性。
举例来说明 Coherence,假设有两个处理器 P1 和 P2,它们都有某个变量 X 的缓存副本。P1 将 X 更新为新值,缓存一致性保证 P2 读取 X 时一定能看到 P1 写入的新值,而不会读到旧的值。
1.2 Consistency(内存一致性)
Consistency 是更高层次的概念,指的是多个处理器对所有内存位置的读写操作顺序是否符合某种定义好的行为规范。它关注的是不同内存位置之间的访问顺序以及线程之间的交互关系,确保所有处理器都能按照预定的顺序观察到读写操作。 内存一致性模型定义了多处理器系统中,线程如何观察和执行内存操作的顺序。
有两类 Consistency:
Sequential Consistency(顺序一致性):所有处理器看到的内存操作顺序与它们实际发生的顺序相同,即所有处理器都按照统一的顺序观察到内存访问。
Relaxed Consistency(弱一致性):为了提高性能,允许部分处理器看到的操作顺序与其他处理器不同,例如 GPU 常用的 Relaxed Consistency 模型。
举例来说,假设 P1 对变量 X 进行写操作,然后对变量 Y 进行写操作,P2 对这两个变量进行读操作。内存一致性模型定义了 P2 是必须按照 P1 写入 X 和 Y 的顺序读取它们,还是可以看到不同步的结果。
总而言之,Coherence 侧重于单一内存位置的多个缓存副本保持一致,保证每个处理器读取到的值是最新的。Consistency 涉及整个系统中对多个内存位置的访问顺序,定义了所有处理器之间如何协调读写操作的顺序。
二、顺序一致性(Sequential Consistency)
内存一致性模型定义了共享内存系统的行为。顺序一致性作为最直观,最基础的一致性模型,是程序员对共享内存行为的期望。
2.1 共享缓存中存在的问题
这里举出来一个问题来解释为什么缓存行为需要被定义。下图是两个核心依次执行 load/store 的过程,核心 C2 的读取依赖于核心 C1 的写入。
按照期望,执行流应该是 C1 写入数据后将标志位置位,C2 检查标志位并读取数据。但由于现代处理器是乱序执行的,C1 的读取操作可能会被重排序先置位在写入数据,而这就可能导致以下这种执行流的产生。
对于这个更加极端的例子,即两个核心都需要读取和写入。
则可能出现四种不同的结果,(x,y)分别为(0,0) ,(0,NEW),(NEW,0),(NEW,NEW)。这种执行结果的不确定性在当前的多处理器都是可能出现的,因为目前所知的所以体系架构都允许并发线程的多重交错执行。
2.2 顺序一致性的基本理念
顺序一致性最早由 Lamport 规范化的,他定义:
-
单核系统中的顺序一致性:当一个单核处理器执行指令时,执行的结果应该与按照程序中指定的顺序依次执行操作的结果一致。这意味着程序中的每一个操作都严格按照其书写顺序被执行。
-
多核系统中的顺序一致性:在多核处理器系统中,执行的结果应该与所有处理器的操作可以看作按照某个全局顺序依次执行的结果一致。并且在这个全局顺序中,每个处理器的操作依然按照它自己的程序顺序执行。
该定义换句话说,顺序一致性要求整个系统中所有处理器的操作可以视为按某种全局的串行顺序执行,而每个处理器内部的操作必须按照它的程序中指定的顺序出现在这个全局顺序中。
按照顺序一致性的要求,上一小节的例子的正确执行流应该如下图所示ÿ