内存屏障与 MESI 的关系是什么?

来源:1-14 Go 并发编程最佳实践

慕丝1411558

2021-06-18 18:27:29

看了好多文章,理解到“内存屏障”是提供主动调用刷新多级Cache、主存的一些指令,这样理解对么?


而MESI已经由CPU提供了缓存主存一致性方案了,那么他们俩的差别是什么呢?


可以理解成内存屏障是“主动”调用同步多级cache+主存,MESI是当产生cache miss时被动同步cache?  可以这样理解么?


内存屏障主要是用于一些update数据,先主动同步多级缓存与内存,减少之后cache miss导致的性能抖动?


写回答

2回答

Xargin

2021-06-19

另外,perfbook 的附录 C 中对 memory barrier 有非常详尽的说明~


如果想要完全理解还是得看这个(虽然他这个描述其实也已经简化很多了,真正的硬件提供的 barrier 更复杂,https://developer.arm.com/documentation/100941/0100/Barriers)


不过软件开发过程不用理解这么深,只要保证程序没有 race 就可以了~

0

Xargin

2021-06-19

Q: 看了好多文章,理解到“内存屏障”是提供主动调用刷新多级Cache、主存的一些指令,这样理解对么?


其实不太精确。。

内存屏障主要通过一些指令告诉 CPU/编译器(比如 mfence、lock 之类的),不要对这条指令和他前/后的读、写进行重排,从而保证并发编程的正确性。具体还分 read barrier,write barrier。


硬件和软件层的抽象也不太一样:


给应用程序员的抽象层:

内存屏障的应用抽象层比较好理解,就是四种情况:

barrier-types.png

四种 barrier 分别对应四种重排情况下的使用,都是防止相应的内存操作重排,注意,这里说的都是不同的变量,同一个变量的话,逻辑上有依赖关系,编译器/CPU 不会对其操作顺序进行重排。

在 Go 语言里,比如你用了 atomic.Cas,那这条指令前面的读、写操作都不会重排到这条指令之后。同时这条指令后面的读写都不会重排到这条指令之前。

其它语言里会有些区别~

实现的硬件层:

因为 mesi 协议的关系,变量的读写会有大量的同步,会导致 CPU 自己发生阻塞(详情可以看 perfbook 的 Appendix C 中的 Unnecessary Stalls)。为了优化阻塞,CPU 内部还设计了 store buffer 和 invalidate queue,相当于你的写操作和 cache 失效操作要在特定的队列里做缓存:

http://img1.sycdn.imooc.com/climg/60ccce49096a3fd812121270.jpg

Many CPU architectures therefore provide weaker memory-barrier instructions that do only one or the other of these two. Roughly speaking, a “read memory barrier” marks only the invalidate queue and a “write memory barrier” marks only the store buffer, while a full-fledged memory barrier does both.

也就是说 read barrier (功能上要保证它前面所有的 read 都执行完)要把所有 invalidate 里的内容排空,write barrier 要把 store buffer 排空(功能上要保证它前面所有的 write 都执行完)。

个人感觉硬件实现对于软件工程师来说太难了。。你得把最底层的 read memory barrier 和上层编程语言提供的抽象再做一次关联:

barriers

上面这张图是 atomic 的 acquire 和 release 语义,这是软件层对硬件提供的 memory barrier 的又一次抽象。

对于我们应用层开发来说,知道内存屏障是用来防止重排的就行了~


Q: 而MESI已经由CPU提供了缓存主存一致性方案了,那么他们俩的差别是什么呢?

MESI 协议主要是为了在多核间同步单个变量的读、写操作,属于 cache coherence 范畴;

内存屏障是为了解决在多核乱序执行(主要因为 CPU 中的 store buffer 和 invalidate queue)时,防止某些并发场景的内存重排的工具,解决的是多个不同变量的读、写顺序问题,属于 memory consistency 范畴;


Q: 可以理解成内存屏障是“主动”调用同步多级cache+主存,MESI是当产生cache miss时被动同步cache?  可以这样理解么?

不太一样~看上面的解释


Q: 内存屏障主要是用于一些update数据,先主动同步多级缓存与内存,减少之后cache miss导致的性能抖动?

内存屏障主要是为了解决并发时的顺序问题,和性能没关系~

0

Go高级工程师实战营

慕课网与 GoCN 社区官方联手打造,定义行业Go高级人才培养标准,4个月,快速晋升为P6+/D7级高级人才。

458 学习 · 266 问题

查看课程