MESI协议

1、MESI是Modified、Exclusive、Shared、Invalid的首字母缩写,代表四种缓存状态。任何多核系统中的缓存段都处于这四种状态

之一。按照相反的顺序进行列出:

----Invalid:失效缓存段,要么已经不在缓存中,要么它的内容已经过时。为了达到缓存的目的,这种状态的段将会被忽略。

一旦缓存段被标记为失效,那效果就等同于它从来没被加载到缓存中。

----Shared:共享缓存段,它是和主内存内容保持一致的一份拷贝,在这种状态下的缓存段只能被读取,不能被写入。多组缓存

可以同时拥有针对同一内存地址的共享缓存段。

----Exclusive:独占缓存段,和S状态一样,也是和主内存内容保持一致的一份拷贝。区别在于:如果一个处理器持有了某个E状态

的缓存段,那其他处理器就不能同时持有它,所以叫“独占”。这意味着,如果其他处理器原本也持有同一缓存段,那么它会马上变成

“失效”(Invalid)状态。

----Modified:已修改缓存段,属于脏段,它们已经被所属的处理器修改了。如果一个段处于已修改状态,那么它在其他处理器缓存

中的拷贝马上会变成失效状态,这个规律和E状态一样。此外,已修改缓存段如果被丢弃或标记为失效,那么先要把它的内容回写到

内存中---这和回写模式下常规的脏段处理方式一样。

-- 只有当缓存段处于E或M状态时,处理器才能去写它,也就是说只有这两种状态下,处理器是独占这个缓存段的。当处理器想写某个

缓存段时,如果它没有独占权,它必须先发送一条“我要独占权”的请求给总线,这会通知其他处理器,把它们拥有的同一缓存段的拷

贝失效(如果它们有的话)。只有在获得独占权后,处理器才能开始修改数据--并且此时,这个处理器知道,这个缓存段只有一份拷

贝,在我自己的缓存里,所以不会有任何冲突。

-- 反之,如果有其他处理器想读取这个缓存段(我们马上能知道,因为我们一直在窥探总线),独占或已修改的缓存段必须先回到“

共享”状态。如果是已修改的缓存段,那么还要先把内容回写到内存中。

MESI定律:在所有的脏缓存段(M状态)被回写(回写到内存)后,任意缓存级别的所有缓存段中的内容,和它们对应的内存中的

内容一致。此外,在任意时刻,当某个位置的内存被一个处理器加载入独占缓存段时(E状态),那它就不会再出现在其他任何处理

器的缓存中。

-- 1)


内存模型

不同的体系结构提供不同的内存模型。到本文写作的时候为止,ARM和POWER体系结构的机器拥有相对较弱的内存模型:这类CPU在读写指令重排序(reordering)方面有相当大的自由度,这种重排序有可能会改变程序在多核环境下的语义。通过“内存屏障(memory barrier)”,程序可以对此加以限制:“重排序操作不允许越过这条边界”。相反,x86则拥有较强的内存模型。

弱内存模型如何保证正确性(相比较于MESI协议给缓存带来的顺序一致性),以及为什么。当然,一切都归结于性能。

规则是这样的:如果满足下面的条件,你就可以得到完全的顺序一致性:第一,缓存一收到总线事件,就可以在当前指令周期中迅速做出响应。第二,处理器如实地按程序的顺序,把内存操作指令送到缓存,并且等前一条执行完后才能发送下一条。当然,实际上现代处理器一般都无法满足以上条件:

  • 缓存不会及时响应总线事件。如果总线上发来一条消息,要使某个缓存段失效,但是如果此时缓存正在处理其他事情(比如和CPU传输数据),那这个消息可能无法在当前的指令周期中得到处理,而会进入所谓的“失效队列(invalidation queue)”,这个消息等在队列中直到缓存有空为止。
  • 处理器一般不会严格按照程序的顺序向缓存发送内存操作指令。当然,有乱序执行(Out-of-Order execution)功能的处理器肯定是这样的。顺序执行(in-order execution)的处理器有时候也无法完全保证内存操作的顺序(比如想要的内存不在缓存中时,CPU就不能为了载入缓存而停止工作)。
  • 写操作尤其特殊,因为它分为两阶段操作:在写之前我们先要得到缓存段的独占权。如果我们当前没有独占权,我们先要和其他处理器协商,这也需要一些时间。同理,在这种场景下让处理器闲着无所事事是一种资源浪费。实际上,写操作首先发起获得独占权的请求,然后就进入所谓的由“写缓冲(store buffer)”组成的队列(有些地方使用“写缓冲”指代整个队列,我这里使用它指代队列的一条入口)。写操作在队列中等待,直到缓存准备好处理它,此时写缓冲就被“清空(drained)”了,缓冲区被回收用于处理新的写操作。

这些特性意味着,默认情况下,读操作有可能会读到过时的数据(如果对应失效请求还等在队列中没执行),写操作真正完成的时间有可能比它们在代码中的位置晚,一旦牵涉到乱序执行,一切都变得模棱两可。回到内存模型,本质上只有两大阵营:

在弱内存模型的体系结构中,处理器为了开发者能写出正确的代码而做的工作是最小化的,指令重排序和各种缓冲的步骤都是被正式允许的,也就是说没有任何保证。如果你需要确保某种结果,你需要自己插入合适的内存屏障——它能防止重排序,并且等待队列中的操作全部完成。

使用强一点的内存模型的体系结构则会在内部做很多记录工作。比如,x86会跟踪所有在等待中的内存操作,这些操作都还没有完全完成(称为“退休(retired)”)。它会把它们的信息保存在芯片内部的MOB(“memory ordering buffer”,内存排序缓冲)。x86作为部分支持乱序执行的体系结构,在出问题的时候能把尚未“退休”的指令撤销掉——比如发生页错误(page fault),或者分支预测失败(branch mispredict)的时候。我已经在我以前的文章“好奇地说”中提到过一些细节,以及和内存子系统的一些交互。主旨是x86处理器会主动地监控外部事件(比如缓存失效),有些已经执行完的操作会因为这些事件而被撤销,但不算“退休”。这就是说,x86知道自己的内存模型应该是什么样子的,当发生了一件和这个模型冲突的事,处理器会回退到上一个与内存模型兼容的状态。这就是我在以前另一篇文章中提到的“清除内存排序机(memory ordering machine clear)”。最后的结果是,x86处理器为内存操作提供了很强的一致性保证——虽然没有达到完美的顺序一致性。

无论如何,一篇文章讲这么多已经够了。我把它放在我的博客上。我的想法是将来的文章只要引用它就行了。我们看效果吧。感谢阅读!

查看参考原文:http://fgiesen.wordpress.com/2014/07/07/cache-coherency/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值