高速缓冲存储器一致性(Cache coherence),也称
缓存一致性,高速缓存间一致性。是指在采用层次结构存储系统的计算机系统中,保证高速缓冲存储器中数据与主存储器中数据相同机制。在一个系统中,当许多不同的设备共享一个共同存储器资源,在高速缓存中的数据不一致,就会产生问题。这个问题在有数个
CPU的
多处理机系统中特别容易出现。
简介
内存系统的本质是,一个内存系统应该能提供一组保存值的存储单元,当对一个存储单元执行读操作时,应该能返回“最近”一个对该存储单元的写操作所写入的值。在串行程序中,程序员利用内存来将程序中某一点计算出来的值,传递到该值的使用点,实际上就是利用了以上的基本性质。同样,运行在单处理器上的多个进程或线程利用共享地址空间进行通信,实际上也是利用了内存系统的这个性质。一个读操作应返回最近的向那个位置的写操作所写的值,而不管是哪个线程写的。当所有的线程运行在同一个物理处理器上时,它们通过相同的高速缓存层次来看内存,因此在这种情况下,高速缓存不会引起问题。当在
共享存储的
多处理器系统上运行一个具有多个进程的程序时,希望不管这些进程是运行在同一个处理器上,还是在不同的处理器上,程序的运行结果都是相同的。然而,当两个运行在不同的物理处理器上的进程通过不同的高速缓存层次来看共享内存时,其中一个进程可能会看到在它的高速缓存中的新值,而另一个则可能会看到旧值,这样就引起了一致性问题。
高速缓冲存储器一致性的比较正式的一个定义是当一个共享存储的机器满足以下条件时,则可以认为该系统是高速缓冲存储器一致的:
以上定义保证了两个属性写广播和写串行化。写广播指的是写操作被其他所有处理器所观察到。定串行化是指对某一存储位置的所有写操作的顺序,在所有处理器看来都是一样的。高速缓冲存储器一致性可以分为三个层级:
一致性
关于一致性的概念,直观上可以定义为每个读操作必须返回最后写入此位置的值。对于每个处理器单元的操作都有一个总体的、串行的操作序是我们希望在任何一个一致性存储系统中见到的。因此,可以对高速缓存一致性进行一个更加形式化的定义方法:如果某个程序的任何执行结果都满足下列条件:对于任何单元,有可能建立一个假想的操作序列(也就是说,将所有进程发出的读写操作排成一个全序,此序列与执行结果一致,并且在序列中):任何特定进程发出的操作所表现出来的序和该进程向存储系统发出它们的序相同,且每个读操作返回的值是对相应单元按照串行顺序写入的最后一值,那么此多处理器存储系统是一致性。
此外,关于多个私有缓存还存在另外一方面的问题:如果数据是由一个处理器核对某个单元写入,而另一个处理器从中读出这样的方式来进行传递的话,那么我们前面所关注的一致性将是非常重要的。最终,写在一个单元中的数据将对所有的读取者都会是可见的,但这种一致性并没有指明所写入的数据何时会成为可见的。通常,在编写一个并行程序时,我们希望在写和读之间建立一种序,即我们需要定义一个序模型,依照该模型,程序员能推断他们程序的执行结果及其正确性。这个模型就是存储同一性。
一个完整的
一致性模型包括高速缓存一致性及存储同一性两个方面,且这两个是互补的:高速缓存一致性定义了对同一个存储地址进行的读写操作行为,而存储同一性模型定义了访问所有存储地址的读写行为。在
共享存储空间中,多个进程对存储的不同单元做并发的读写操作,每个进程都会看到一个这些操作被完成的序。一个存储同一性模型规定了对这种序的若干约束,值得一提的是,这里所涉及到的并发存储操作既包括对相同单元的,也包括对不同单元的;即可以来自同一进行,也可以来自不同的进程。在这个意义上,存储同一性包含了高速缓存一致性。
实现
高速缓存一致性协议是解决缓存一致性问题的主要方案,同时也是保证存储同一性的重要手段。它定义了共享缓存块在各个私有缓存中的存在形式,并详细定义了各个私有缓存之间的通信行为。学术界及工业界已经提出了多种高速缓存一致性协议模型,但所有模型的出发点都是一样的,它们都是为了保证存储模型SWMR(single-writer,multiple-reader)属性,即对于一个给定的缓存块,在系统运行的任意时刻,保证(1)同时只能有一个处理器核拥有对此缓存的写权限;或者(2)同时可以有零个或者多个处理器核拥有对此缓存块的读权限。根据共享数据的修改方式的不同,可以将高速缓存一致性协议的实现分为两种形式:写无效协议、写更新协议。其中,在写无效协议中,处理器核在对某个存储块进行写操作之前,必须保证当前的处理器核拥有对此缓存块的读写权。如果两个或者多个处理器核试图同时访问同一个数据项并执行写操作,那么它们中同时只能有一个在进行,另一个访问请求会被阻塞;在某个处理器执行写操作时,其它所有私有缓存中该数据的副本都会被置为无效状态。在当前处理器完成写操作后,后续的对此数据的所有操作,都必须首先获得此新写入数据的副本。因此,写无效型的协议强制执行了写操作的串行化。写更新协议也称为写广播协议,它是指处理器核在对某个数据进行写操作时,同时更新当前数据在其它所有缓存中的数据副本。
有两种主要的缓存一致性协议:基于侦听形式的高速缓存一致性协议(或侦听协议)及基于目录结构的高速缓存一致性协议(或目录协议)。在这两种协议中,侦听协议的实现依赖于一个总线或者类总线形式的网络连接,使用此网络,单个处理器核的私有缓存所发出的所有请求会被广播到系统中所有的其它处理器核的私有缓存中,而所有处理器的访问请求也可以在此总线上进行定序操作,以实现缓存一致性模型及存储同一性模型中对访存序的要求。此外,此协议还可以通过总线结构来很好的处理对同一数据块的多个冲突请求,而且多个处理器的私有缓存之间可以通过此总线结构进行直接的通信,减少了通信延迟。但是,由于所有请求都是通过总线来进行传输的,但总线带宽资源有限,因此它会影响整个系统的扩展性。目录协议则是采用一个目录结构来实现对缓存块的管理的。在目录协议中,处理器核的私有缓存发出的访存请求,会首先发送到拥有相应缓存块的目录结构中,此目录结构中记录了当前缓存块的共享情况,目录结构控制器会根据当前缓存块的状态,选取响应此请求或者转发此请求到其它相应的私有缓存中。此种方法不需要依赖于特定拓扑结构的网络,并通过点对点的直接通信形式降低了网络中的带宽消耗,因此这种协议易于扩展。但由于此协议的实现中,所有请求都必须通过目录结构进行处理,因此会引入额外的延迟。
MESI协议
单核Cache中每个Cache line有2个标志:dirty和valid标志,它们很好的描述了Cache和Memory(内存)之间的数据关系(数据是否有效,数据是否被修改),而在多核处理器中,多个核会共享一些数据,
MESI协议就包含了描述共享的状态。
在MESI协议中,每个Cache line有4个状态,可用2个bit表示,它们分别是:
M(Modified):这行数据有效,数据被修改了,和内存中的数据不一致,数据只存在于本Cache中。
E(Exclusive):这行数据有效,数据和内存中的数据一致,数据只存在于本Cache中。
S(Shared):这行数据有效,数据和内存中的数据一致,数据存在于很多Cache中。
I(Invalid):这行数据无效。
在该协议的作用下,虽然各cache控制器随时都在监听系统总线,但能监听到的只有读未命中、写未命中以及共享行写命中三种情况。读监听命中的有效行都要进入S态并发出监听命中指示,但M态行要抢先写回主存;写监听命中的有效行都要进入I态,但收到RWITM时的M态行要抢先写回主存。总之监控逻辑并不复杂,增添的系统总线传输开销也不大,但MESI协议却有力地保证了主存块脏拷贝在多cache中的一致性,并能及时写回,保证cache主存存取的正确性。