Memory Barrier是啥

1 Memory Barrier

1.1 编译器

(待补充)

1.2 CPU架构

                    

之所以需要Memory Barrier,是因为现代CPU中Store Buffer和Invalidate Queue两个结构。

1.2.1 MESI

https://en.wikipedia.org/wiki/MESI_protocol

                   

  • Modified (M): The cache line is present only in the current cache, and is dirty - it has been modified (M state) from the value in main memory. The cache is required to write the data back to main memory at some time in the future, before permitting any other read of the (no longer valid) main memory state. The write-back changes the line to the Shared state(S).
  • Exclusive (E): The cache line is present only in the current cache, but is clean - it matches main memory. It may be changed to the Shared state at any time, in response to a read request. Alternatively, it may be changed to the Modified state when writing to it.
  • Shared (S): Indicates that this cache line may be stored in other caches of the machine and is clean - it matches the main memory. The line may be discarded (changed to the Invalid state) at any time.
  • Invalid (I): Indicates that this cache line is invalid (unused).

1.2.2 Store Buffer

                             

如图中,invalidate cache的操作是同步的,store操作需要等待其他CPU的上的invalidate操作的完成,而在此期间,store操作需要stalling等待,此时性能较低。Store Buffer的作用就是将invalidate cache的过程变成异步的。invalidate cache的操作会被放到store buffer中,当invalidate cache完成之后,会更新本地cache。在invalidate没有完成前,本地的读取操作会从store buffer中获取。

如下面的例子中:

       CPU 0           CPU1
Ins

       a = 1           while (b != 2) continue
       b = 2           assert(a == 1)
Cache
       (E) b = 0       (E) a = 0

 变量b的cacheline在CPU0中处于E状态,变量a的cacheline在CPU1中处于E状态;

  • CPU0执行a = 1,存入store buffer执行异步invalidate cache,然后立刻执行下一条指令,
  • CPU0执行b = 2,因为独占cacheline,所以立刻更新到本地cacheline,
  • CPU1读到b的更新状态,然后完成while循环;
  • 此时,a的cacheline的invalidate cache还没有发出来,所以,CPU1仍然使用本地cacheline,于是读到a == 0

此时,我们在a = 1和b = 2之间加入一个smp_mb(),该指令会等待store buffer中所有的异步invalidate cache完成,即收到invalidate response之后。

1.2.3 Invalidate Queue

                              

虽然Store Buffer将Invalidate Cache的过程异步化了,但是如果CPU1这边执行较慢的时候,仍然可能造成Store Buffer填满,此时Store操作仍然需要同步等待。为了优化这个场景,在CPU1那边处理invalidate cache的处理再次被异步化,invalidate cache request会被放入invalidate queue,然后立刻发送response,之后在invalidate queue中慢慢处理。

  

       CPU 0           CPU1
Ins

       a = 1           while (b != 2) continue
       smp_mb()
       b = 2           assert(a == 1)
Cache
       (E) b = 0       (E) a = 0

此时,虽然smp_mb()保证了在b = 2执行时,CPU0收到了来自CPU1的invalidate response,但是因为invalidate queue的存在,此时,invalidate cache可能还没有真正在CPU1上执行,所以,assert(a == 1)仍然可能失败。解决办法是,在assert(a == 1)之前加入一个smp_mb(),它会强制invalidate queue中的invalidate request执行完成。

1.2.4 rmb & wmb

  • smp_rmb()  : 强制执行invalidate queue中的invalidate cache request;
  • smp_wmb() : 等待store buffer中的invalidate cache完成
  • smp_mb()    : smp_wmb() + smp_rmb()

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值