阅记-横向优化-《HPC-一文彻底搞懂并发编程与内存屏障》

参考:HPC(高性能计算第一篇):一文彻底搞懂并发编程与内存屏障 [1] [2] [3]

Momory Ordering

memory barrier是memory乱序后产生的问题,和cpu架构强相关。
参考:Intel sdm手册 卷3A 多处理器管理,第二小节:内存顺序,专门讲述Memory barrier问题;

9.2.3.2 Neither Loads Nor Stores Are Reordered

9.2.3.2 节,是第一个关于内存顺序的例子

Q: 何为乱序?
A:

    1. 两个操作独立,互不依赖,多流水线架构下两条指令可以同时执行;
    1. 同时执行或者先后执行的情况下,也可能因为_y变量已经存在于cache中而先于_x执行
    1. intel cpu架构下,虽然2)执行乱序,但是到最后阶段(提交阶段吗?)又会顺序退出,即旁观者看来还是_x先执行完_y再执行完,所以intel的sdm手册这一小节的标题为Neither loads nor strores are reoredered,并描述r1 = 1 and r2 = 0 is not allowed,CPU使用一个叫内存排序区的部件,完成这种顺序性(待研究)
    1. 其他cpu架构,允许提交阶段乱序的话,那么P1就可能看到_y = 1 _x = 0的结果

Q: 对于4)怎么解决?

A:P0加上write_barrier, P1加上read_barrier(read同样可能乱序)


9.2.3.3 Stores Are Not Reordered With Earlier Loads

接下来的9.2.3.3 节描述了另外一种场景先有load操作再有store操作,这种场景下store操作也不会被reorder到load操作前


9.2.3.4 Loads May Be Reordered with Earlier Stores (intel x64架构下唯一会有memory reorder的情况)

9.2.3.4 读可以重排到写之前, intel x64架构下唯一会有memory reorder的情况

比如有种代码逻辑:1)mov _x,1 表示加本地的锁;2)mov r1, _y 表示检测其他线程当前是否有上锁;3)如果r1或者r2为0,表示其他线程没上锁,当前线程可以执行

正常顺序下,某一方赋值先执行,则另外一方读取肯定不为0,r1 r2可以是(1,1)(1,0)(0,1),但是同时为0不会发生,即P0 P1不会同时执行需要互斥的临界代码

有memory reorder下,read先于之前的write先执行,则r1 r2可能会同时为0,导致P0 P1同时执行需要互斥的临界代码
如果不想有这种乱序则需要上内存屏障

+++
内存屏障是内存顺序问题,即,内存操作本来是能分清先后顺序的,写先读后,但顺序被打乱了,读被提到前面了。如果不想打乱顺序,需要“屏障”,挡住后面的读,防止它提前执行、提前完成。
当程序逻辑依赖读写顺序,才需要使用内存屏障,如果程序逻辑并不依赖顺序,就让读被提前吧,这样对性能有帮助
(判断程序逻辑是否依赖顺序,有时候不是那么容易的)

内存屏障的实现

lock 和 mfence 指令

posted @ 2024-05-19 23:25  LiYanbin  阅读(16)  评论(0编辑  收藏  举报