Cache的使用提升了存储系统的性能,同时也带来了一系列的问题,Cache数据一致性问题就是其中比较引人注目的一个。
由于Cache缓存了主存储器中数据块的内容,使得系统中的一个数据块同时存在多个副本,而某些操作可能造成这些副本之间的不一致,这就是Cache数据一致性问题,又称Cache一致性问题。尤其是在多处理器的系统中,由于多处理器异步地独立操作,不同处理器的Cache中同一个数据块的副本就有可能出现不一致的现象。
Cache一致性问题通常由对共享数据的写操作、进程迁移、I/O传输三个原因引起。
●对共享数据的写操作
在多处理器系统或基于多核处理器的系统中,每个处理器或者每个核心都会有自己私有的Cache。在这些处理器或核心上运行的进程(或线程)需要对一些共享数据进行操作的时候,每个处理器或核心的Cache中会保存这些共享数据的副本。当处理器或核心对这些共享数据进行写操作时,就会引起不同Cache和主存储器中这些共享数据不一致的现象。
以一个由两个处理器共享一个主存储器的简单多处理器系统为例。在这个简单系统中,两个处理器各自有自己的私有Cache,并通过一条共享总线共享一个主存储器(见图5-6a)。当两个处理器上执行的进程同时要访问一组共享数据时,这些共享数据在每个处理器的私有Cache中都会有副本存在,这两个副本和主存储器中的数据副本是相同的,也是有效的(见图5-6b)。
图5-6 多处理器系统中写共享数据引起的数据不一致问题
假设处理器P1上的进程对共享数据X进行了写操作,P1的私有Cache中的数据得到了修改,P1的Cache中保存有共享数据正确的副本X′。当Cache使用写直达策略时,主存储器中的共享数据副本也被更新为正确的X′,但处理器P2的私有Cache中的共享数据副本仍然是未修改前的X,是无效的(见图5-10c),必须从主存储器中重新读入。当Cache使用写回策略时情况更加糟糕,不仅仅P2的私有Cache中的共享数据副本是未修改前的无效的X,主存储器中的副本也同样是未修改前的无效的X(见图5-10d),这时处理器P2上的进程对共享数据的访问必然得到错误的结果。
●进程迁移
多处理器的系统中,进程(或线程)从一个处理器迁移到另一个处理器是一种非常常见的操作,在这个操作过程中就有可能引起数据的不一致。同样以图5-6a所示的多处理器系统为例,当系统中一个进程P在处理器P1上运行时,其所访问的数据在P1的私有Cache中存在一个副本X(见图5-7a),而对这些数据的写操作将导致这个副本被更新为X′。当Cache使用写回策略的时候,主存储器中的副本不会得到更新,依旧是X(见图5-7b)。假设此时因为某些原因导致进程P从处理器P1迁移到处理器P2,由于P2的Cache中没有相关数据的副本,只能从主存储器中读入数据,此时读入的数据明显是没有得到更新的X而不是修改后的X′(见图5-7c)。
图5-7 进程迁移引起的数据不一致问题(1)
使用写回的写策略时会造成进程迁移时的数据不一致性,而写通过的写策略同样也不能避免进程迁移时的数据不一致问题。针对刚才的系统模型,考虑一个进程从处理器P1迁移到处理器P2,后又重新迁移回处理器P1的过程。过程同样从图5-7a所示状态开始,当进程从处理器P1迁移到P2时,P1的私有Cache中留存了一份数据副本X(见图5-8a)。进程在P2上运行一段时间,并对将数据从X修改为X′(见图5-8b),又因为某些原因迁移回处理器P1。这时虽然主存储器和P2的私有Cache中保存的都是正确的数据副本X′,但在P1的私有Cache中所保存的数据副本是未作修改之前的X,从而造成了数据的不一致(见图5-8c)。
图5-8 进程迁移引起的数据不一致问题(2)
●I/O传输(www.xing528.com)
不仅仅在多处理器系统中可能出现数据一致性问题,在单处理器系统中I/O传输也同样有可能引起数据的不一致。考虑一个由以下部件组成的简单系统:带有私有Cache的处理器、主存储器和与处理器异步操作的I/O设备,随着处理器对主存储器中内容的访问,在Cache中保存了一份数据副本X(见图5-9a)。这时I/O设备启动一次异步的I/O操作,从系统外部读入数据将主存储器中的X修改为X′,而处理器Cache中的内容依旧是X,从而引起数据不一致(见图5-9b)。
图5-9 I/O传输引起的数据不一致问题
类似地,写回策略的Cache也有可能在I/O写操作的时候由于Cache中的数据没有及时写回而引起数据的不一致(见图5-9c)。
解决Cache一致性问题,最简单的办法莫过于禁止这些可能被共享的数据进入Cache。但这样对系统的性能影响很大,是一种得不偿失的做法。比较合理的解决方案是采用某种机制,保证任何一个数据副本被修改时其他Cache都能够知道这一修改动作。通常有三类协议机制可以供选用:监听协议、基于目录的协议和编译制导的一致性维护。其中监听协议原理比较简单,对于小规模系统更加有效。而基于目录的协议相对比较复杂,更适合于大规模的计算机系统,编译制导的一致性维护则依赖编译器对可能出现的Cache一致性问题进行防范,生成特殊的指令插入到代码中。
监听协议的基本思想是通过总线监听机制对数据写动作进行监听,在监听到数据写动作时对相应的数据块进行处理,以保证Cache和主存储器的数据一致性。监听协议又可以使用两种不同的策略:写无效(Write-invalid)和写更新(Write-update),它们的区别在于监听到数据写动作时处理策略上的不同。写无效策略是在本地Cache的数据块被修改时通过协议使其他所有Cache和主存储器中的数据块副本无效。而写更新策略则是在本地Cache的数据块被修改时通过总线把改写后的数据块广播到还有该数据块副本的所有其他Cache和主存储器。由于写更新策略需要经常通过总线广播数据,对于总线的压力比较大,为了减少这种对珍贵的总线带宽的无谓占用,大多数处理器采用写无效策略。
在各种写无效策略中,MESI协议是应用最为广泛的一种。MESI协议的名称来自于协议中规定的数据块的四种Cache行的状态:修改态(Modified)、独占态(Exclusive)、共享态(Shared)和无效态(Invalid)。在Cache组织中,每一个Cache行对应一个目录项,目录项中用两个二进制位表示Cache行的状态。每次对Cache行中的内容进行操作的时候,Cache控制器都会根据Cache行的状态进行合适的操作,并控制Cache行的状态转换。MESI协议中Cache行的四种状态的含义是:
●无效态(Invalid):无效态是所有Cache行最原始的状态,当系统加电时,所有的数据都不在Cache中,这时的所有Cache行都处于无效态。另外,无效态还可能由于该Cache行对应的数据块被其他处理器或者被I/O设备修改,造成Cache行中的数据失效从而使Cache行进入无效态。
●独占态(Exclusive):独占态指的是一个Cache行中的内容为该Cache所独占,其他Cache中没有这个数据块的副本。独占态下的Cache行的内容与主存储器中的内容一致,处理器尚未对该数据块做任何写操作,因而主存储器中的数据块内容是有效的。
●共享态(Shared):共享态下的Cache行中的内容为本Cache及其他处理器的Cache所共享,而且Cache行的内容与主存储器中的内容也是一致的。即该Cache行的数据为多个处理器所共享,且尚未被修改。
●修改态(Modified):当处理器对Cache行中的内容进行了修改的时候,该Cache行即进入修改态,或称“脏态”(Dirty)。修改态意味着该Cache行中的内容已经是系统中独一无二的一份,主存储器中的对应数据块以及其他处理器的Cache中的对应Cache行的状态都应当被修改为无效态。
在基于MESI协议的多处理器系统中,各处理器的Cache控制器不仅仅要负责控制自己Cache的读写操作,还要通过总线监听其他处理器的内存读写操作,并对自身Cache中相应Cache行的状态进行转移处理,以达到维护Cache一致性的目的。
MESI协议的关键是Cache行的状态根据本地和远程处理器对数据的读写操作进行适当的转移,这种转移可以用图5-10所示的有限状态自动机简要描述。
图5-10 MESI协议的状态转换
由于Cache写策略等的不同,不同系统中MESI协议的实现会有所差别,但基本原理和状态的转移原则是一致的。Pentium处理器及其后的X86系列处理器均支持MESI协议,以方便实现多处理器系统。多核处理器的出现和推广使得Cache一致性问题普遍出现在基于多核处理器的微机系统之中,MESI协议对于这些基于多核处理器的微机系统更是不可或缺。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。