MESI协议以及内存屏障

一、MESI协议
1.1 MESI协议的消息类型
1.2 数据在缓存中的四种状态
1.3 数据转换状态时需要发送或接收的消息

二 、CPU架构
2.1 cpu架构
2.2 为什么需要store buffer

三 、内存屏障
3.1 内存屏障的作用

一、MESI协议

(一)MESI协议的消息类型
MESI的六种消息大致分为两类:请求消息和响应消息
cpu接收响应消息的顺序决定了->其他cpu感知到的当前线程的执行顺序
1)read:(请求消息)
cpu发送read消息请求需要读取数据的物理地址。
2)read response:(响应消息)
"read response"消息包含先前“read”消息请求的数据。此“read response”消息可能由内存或其他缓存之一提供。
3)invalidate:(请求消息)
“invalidate”消息包含要作废的缓存行的物理地址。所有其他缓存都必须从其缓存中删除相应的数据并进行响应。
4)invalidate acknowledge:(响应消息)
接收到“invalidate”消息的CPU必须在从其缓存中删除指定的数据后以“invalidate acknowledge”消息响应。
5)read invalidate:(请求消息)
“read invalidate”消息包含要读取的缓存行的物理地址,同时指示其他缓存删除数据。“read invalidate”消息需要“read response”和一组“invalidate acknowledge”消息作为应答。
6)writeback
“writeback”消息包含要写回内存的地址和数据(也可能是沿途“窥探”到其他cpu的缓存中)。此消息允许缓存根据需要弹出处于“修改”状态的行,以便为其他数据腾出空间。

(二) 数据在缓存中的四种状态
M:modified 数据被修改,处于cpu独占状态。
E:exclusive 数据处于cpu独占状态,cpu可能要对数据进行写入。
S:shared 数据处于cpu共享共享状态。
I:invalid cpu缓存行中没有相应的有效数据,需要发送请求来获取。
 MESI通信消息
(三) 数据转换状态时需要发送或接收的消息
如上图(其中r为receive接收、s为send发送)
例如

g线:数据状态从E独占状态转为S共享状态时,需要接收read消息以驱动,然后以read response消息作为响应。
h线:数据由S共享状态转为E独占状态时,需要发送invalidate以通知其他cpu相应数据将要失效,并等待其他cpu的回应消息(invalidate acknowledge)。

二、cpu架构

(一)cpu架构

此处仅仅描述与本文章有关的组件:
cpu、store buffer队列缓冲区、cache缓存行、message queue消息队列、memory内存
由于store buffer中的内容对其他cpu不可见,因此此为产生乱序的根本原因
cpu架构图

(二)为什么要store buffer
上一节提到store buffer的存在可能会使其他cpu观察当前cpu的执行顺序时,观察到的结果为乱序。既然会产生乱序,那为什么要加入store buffer?
1)store buffer可以减少cpu的等待时间以提高cpu的吞吐量
2)store buffer产生的乱序是可控的
①----cpu为什么要等待,以及store buffer如何减少cpu的等待时间:
以上述h线举例,cpu想要修改数据时会将数据修改为独占状态,于是向其他cpu发送invalidate消息,并等待收到所有其他cpu的确认消息(invalidate acknowledge)后才能将数据状态修改为E。如图:
在这里插入图片描述
下面看一段代码:

Thread t1 = new Thread(() -> {
                a = 1;
                x = b;
            });

当cpu在执行a=1时,若此时a的状态不为E,则需要发送消息并等待,对当前线程而言,在等待期间把b的值赋值给x,cpu的效率便得到了提升(cpu并不是在无聊的等待,而是找了件事做,比如读取b的值并赋值给x),并且对该线程的运行结果并无影响。
但是cpu只能按顺序执行代码,要做得这一点便引入了store buffer,有了store buffer之后cpu暂且将a=1先写入store buffer,然后去做其他的事情,待收到所有的invalidate acknowledge之后再将store buffer中的值写入cache。
虽然cpu的效率提升了,但是也产生了乱序,即先加载b,后写入a。(a只写入store buffer对其他cpu并不可见,只有写入cache才能被其他cpu观察到)
此乱序可以提升性能,但也可能产生问题,由于cpu工程师并不知道cpu会去执行何种业务代码,也就不会知道什么时候这种乱序可以被容忍,便把控制手段留给了编写业务代码的应用程序员,即内存屏障。

三、内存屏障

(一)内存屏障的作用
首先来看一段内存屏障的定义:

All of a given CPU’s accesses (loads and stores) preceding a full memory barrier (smp_mb()) will be perceived by all CPUs to precede any accesses following that memory barrier.

此段定义将cpu对数据的操作分为两部分:
1、在smp_mb()指令之前的操作
2、在smp_mb()指令之后的操作
并且规定了在指令之前的操作能够被其他cpu可见之后,指令之后的操作才能真正执行。
继续以上述例子解释:

Thread t1 = new Thread(() -> {
                a = 1;
                smp_mb();//插入完全内存屏障
                x = b;
            });

原来将a=1写入store buffer后cpu就可以去访问b的值,而在加入内存屏障smp_mb()之后,会对store buffer中的内容进行标记,被标记的内容必须优先访问cache,从而保证对b的访问在a=1写入cache之后执行。

参考文献:

Is Parallel Programming Hard, And, If So,What Can You Do About It?
Edited by:Paul E. McKenney

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值