多核程序设计——缓存一致性协议MESI

MESI协议

在MP系统中,每个CPU都有自己独立的cache,缓存之间的一致性很很容易受到破坏的,所以缓存一致性协议就应运而生了。MESI是一种使用非常广泛的缓存一致性协议。

MESI存在”modified”,”exclusive”,”shared”和”invalid”四种状态,协议可以在一个指定的缓存中应用这四种状态。因此,协议在每一个缓存行中维护一个两位的状态”tag”,这个”tag”附着在缓存行的物理地址或者数据后。

  • 处于“ modified” 状态的缓存行是由于相应的 CPU 最近进行了内存存储。并且相应的内存确保没有在其他 CPU 的缓存中出现。下边的图有一些误导嫌疑,可以把“叉”看做是invalid状态。这些图是《大话处理器》作者的图,这里直接偷过来了。

  • “exclusive”状态非常类似于“ modified” 状态,唯一的例外是缓存行还没有被相应的 CPU 修改,这表示缓存行中的数据及内存中的数据都是最新的。

  • 处于“ shared” 状态的缓存行可能被复制到至少一个其他 CPU 缓存中,这样在没有得到其他 CPU 的许可时,不能向缓存行存储数据。

  • 处于“ invalid” 状态的行是空的,换句话说,它没有保存任何有效数据。

MESI消息

根据几幅图来看,MESI协议的各个状态是非常容易理解的。但事实上,MESI协议的核心却是MESI消息和状态转移。《Is parallel programming hard, …》中是把消息和状态转移分开讲的,我觉得不是特别直观,所以我把这两个混在一起了。如果CPUs在单个共享总线上,MESI协议一般有以下这些消息。

  • Read:当CPU在自己的cache中没有发现需要的物理地址,就会发送一条“READ”消息,该消息包括缓存行需要读的物理地址。
  • Read Response: 顾名思义,”Read Response”消息是回复“Read”消息的。“Read Response”消息是由内存或者其他CPU缓存提供的。如果其他缓存请求一个处于“modified”状态的数据,则本地缓存必须提供“Read Response”消息。这个很容易理解,别的CPU在请求本地缓存中的数据,而这份数据还没有刷新到内存,所以必须告诉其他CPU该数据的最新值。接收到”Read Response”消息后,该数据的缓存状态就由”invalid”变成了”share”或者”exclusive”,这取决于”Read Response”的提供者是内存还是其他CPU缓存。
  • Invalidate:“ invalidate” 消息包含要使无效的缓存行的物理地址。其他的缓存必须从它们的缓存中移除相应的数据并且响应此消息。当CPU要对一个变量进行写操作,而此变量处于只读状态(share),就需要发送“invalid”消息。由于一个变量被多个CPU缓存,所以单个CPU的改写会造成缓存不一致,所以在写之前必须告诉其他CPU你们缓存的值马上就要过时了。接受到”invalidate”消息的CPU就会把本地缓存中的对应数据无效掉。
  • Invalidate Acknowledge:一个接收到“invalidate”消息的 CPU必须在移除指定数据后响应一个“invalidate acknowledge”消息。这个消息就是告诉“invalidate”消息的提供者“我已经知道你要更改这个数据了,我放弃使用自己缓存中的拷贝!”
  • Read Invalidate:”read invalidate”消息包含要缓存行读取的物理地址。同时指示其他缓存移除数据。因此,它包含一个”read”和一个”invalidate”。“read invalidate”也需要“read response”以及”invalidate acknowledge”消息集。

    “Read Invalidate”消息的发送时机有两个:第一个是CPU对一个数据进行原子读写操作,但是该数据没有在本地CPU的缓存中,在其他CPU缓存中可能有该数据的拷贝。所以它需要发送一条“Read Invalidate”消息,它不仅需要读取该数据的最新值,还要无效掉其他的CPU缓存(它马上就要改写该数据)。

  • Writeback:“writeback”消息包含要回写到内存的地址和数据。这个消息允许缓存在必要时换出“modified”状态的数据以腾出空间。消息的发送时机是,CPU把本地缓存中的数据刷新到内存中,而该数据是share状态(只读),它需要告诉其他CPU”我不再使用这些缓存数据了”

MESI状态转移

有了前面的学习,MESI的状态转移也就不难理解了。MESI协议的状态转移图如下:

其中,a-l是状态转移路径。关于全部状态转移路径,我不准备详细记录了,《Is parallel programming hard…》中有详细的描述。这里我记录几条自己觉得不容易理解的。

  • Transition(e):这条路径从”share”状态通往”Modified”装态。这种状态转移的发生时机是CPU执行一条原子读写指令(如test_and_set或者exchg)。其实从本质上说,是不存在一条从S直接到M的状态转移的。原子读写指令的微指令逻辑依然是先读后写,写之前需要invalid其他的CPU缓存,所以先还是从S到E,然后开始改写,状态从E转移到M。但是,原子读写指令与load+store的区别在于它是原子性的,不能被分割,整个指令执行过程是事务性的,必须一次完成。因此,MESI协议中才会有这样一条状态转移。
  • Transition(h):h是从S到E的一条状态转移路径。该状态转移发生的时机有两个。第一个是:CPU马上要对一个数据进行写入操作,它首先要先invalidate其他的CPU缓存,所以它进入了E状态(其他CPU缓存中都不存在该数据)。另一个时机是接收到其他全部共享某数据的CPU发送的writeback消息,也即是说本地缓存是唯一缓存了,所它就是exclusive了。需要强调的东西是——要改写某数据,要先”拥有”它,即处于S状态其实是无法改写该数据的。

    在《深入理解并行编程V1.0》中,我觉得对Transition(h)部分的翻译是有误的。同时我也已经发现了不少其他错误,在以后的博文中会陆续写出来。

    Blog: intheworld

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-07 12:01:53

多核程序设计——缓存一致性协议MESI的相关文章

一篇文章让你明白CPU缓存一致性协议MESI

CPU高速缓存(Cache Memory) CPU为何要有高速缓存 CPU在摩尔定律的指导下以每18个月翻一番的速度在发展,然而内存和硬盘的发展速度远远不及CPU.这就造成了高性能能的内存和硬盘价格及其昂贵.然而CPU的高度运算需要高速的数据.广州SEO为了解决这个问题,CPU厂商在CPU中内置了少量的高速缓存以解决I\O速度和CPU运算速度之间的不匹配问题. 在CPU访问存储设备时,无论是存取数据抑或存取指令,都趋于聚集在一片连续的区域中,这就被称为局部性原理. **时间局部性(Tempora

缓存一致性协议MESI

1. 缓存一致性协议的由来: 计算机的存储设备速度与cpu的运算速度之间是数量级的差距,现代计算机不得不加入一层读写速度尽可能接近cpu运算速度的高速缓存来作为内存和cpu之间的缓冲:将运算需要使用到的数据复制到缓存中,让运算能快速进行,当运算结束后再从缓存同步回内存之中,这样cpu就无须等待缓慢的内存读写了. 基于高速缓存的存储交互很好地解决了cpu与内存的速度矛盾,但是也引入了新的问题:缓存一致性.在多cpu系统中,每个cpu都有自己的高速缓存,而它们又共享同一主内存,当多个cpu的运算任务

多线程之缓存一致性协议

前言: CPU在摩尔定律的指导下以每18个月翻一番的速度在发展,然而内存和硬盘的发展速度远远不及CPU.这就造成了高性能能的内存和硬盘价格及其昂贵.然而CPU的高度运算需要 高速的数据.为了解决这个问题,CPU厂商在CPU中内置了少量的高速缓存以解决I\O速度和CPU运算速度之间的不匹配问题. 首先在电脑中,CPU读取RAM中的数据数据的流程是,通过I/O总线(BUS),将数据从RAM中获取需要操作的数据进CPU需要如下几个步骤 CPU中的三级缓存从RAM中获取该数据. CPU中的二级缓存从三级

多线程之:MESI-CPU缓存一致性协议

MESI(Modified Exclusive Shared Or Invalid)(也称为伊利诺斯协议,是因为该协议由伊利诺斯州立大学提出)是一种广泛使用的支持写回策略的缓存一致性协议,该协议被应用在Intel奔腾系列的CPU中,详见“support the more efficient write-back cache in addition to the write-through cache previously used by the Intel 486 processor” MESI

聊聊高并发(五)理解缓存一致性协议以及对并发编程的影响

Java作为一个跨平台的语言,它的实现要面对不同的底层硬件系统,设计一个中间层模型来屏蔽底层的硬件差异,给上层的开发者一个一致的使用接口.Java内存模型就是这样一个中间层的模型,它为程序员屏蔽了底层的硬件实现细节,支持大部分的主流硬件平台.要理解Java内存模型以及一些处理高并发的技术手段,理解一些基本的硬件知识是必须的.这篇会说一下跟并发编程相关的一些硬件知识. 一个基本的CPU执行计算的过程如下: 1. 程序以及数据被加载到主内存 2. 指令和数据被加载到CPU的高速缓存 3. CPU执行

缓存一致性协议

刚看到一篇很好的介绍缓存一致性的文章,晚一点把其中的英文部分翻译过来 https://zhuanlan.zhihu.com/p/25876351 https://en.wikipedia.org/wiki/MESI_protocol

zt:缓存一致性(Cache Coherency)入门 cach coherency

http://www.infoq.com/cn/articles/cache-coherency-primer http://www.cnblogs.com/xybaby/p/6641928.html 本文是RAD Game Tools程序员Fabian “ryg” Giesen在其博客上发表的<Cache coherency primer>一文的翻译,经作者许可分享至InfoQ中文站.该系列共有两篇,本文系第一篇. 我计划写一些关于多核场景下数据组织的文章.写了第一篇,但我很快意识到有大量的

缓存一致性

多核处理器的基本架构 缓存(Cache) 本文是关于CPU缓存的快速入门.我假设你已经有了基本概念,但你可能不熟悉其中的一些细节.(如果你已经熟悉了,你可以忽略这部分.) 在现代的CPU(大多数)上,所有的内存访问都需要通过层层的缓存来进行.也有些例外,比如,对映射成内存地址的I/O口.写合并(Write-combined)内存,这些访问至少会绕开这个流程的一部分.但这两者都是罕见的场景(意味着绝大多数的用户态代码都不会遇到这两种情况),所以在本文中,我将忽略这两者. CPU的读/写(以及取指令

内存管理_缓存一致性

计算机在执行程序时,每条指令都是在CPU中执行的,而执行指令过程中,涉及到数据的读取和写入.由于程序运行过程中的临时数据是存放在SRAM(物理内存)当中的,由于CPU执行速度很快,而从内存读取数 据和向内存写入数据的过程跟CPU执行指令的速度比起来要慢的多,因此如果任何时候对数据的操作都要通过和内存的交互来进行,会大大降低指令执行的速度,因此在CPU里面就有了一级.二级Cache(DRAM).也就是,当程序在运行过程中,会将运算需要的数据从RAM复制一份到Cache中,那么CPU进行计算时就可以