内存一致性之顺序一致性(sequential consistency)
可以说,最直观的内存一致性模型是sequentially consistent(SC):
内存访问执行的顺序与程序指定的顺序相同
如果是多核心的程序,那么顺序一致性就是,对于任何一个核心而言
所有核心的内存访问实际执行顺序都和程序指定顺序相同
上图中左边是核心C1的程序指定顺序,右边是核心C2的程序指定顺序,中间是实际的内存访问顺序。简而言之,不管是从哪个核心的角度,内存访问的顺序都是遵循程序指定顺序的 。
所以,对于上述程序而言,只要是服从顺序一致性内存模型,最后程序的结果寄存器r2都能够拿到值NEW,唯一不能确定的是执行指令L1的次数。
下面我们展示示例程序几个SC模型的执行顺序:
S1->L1->S2->L2
(r1, r2) = (0, NEW )
S2->L2->S1->L1
(r1, r2) = (NEW, 0).
S1->S2->L1->L2
S1->S2->L2-> L1
S2-> S1-> L1-> L2
S2-> S1-> L2-> L1
(r1, r2) = (NEW, NEW )
综上,这6种内存执行顺序都符合顺序一致模型,而其他的组合都是不符合的。
例如
其他的非顺序一致性模型(例如弱序一致性)可能会放松某些非SC的指令顺序。
顺序一致性(SC)要求每一个load和store都需要按照程序描述的顺序执行下去。
Load ->Store
Store ->Store
Store ->Load / Included for SC but omitted for TSO /
但是由于处理器中write buffer的存在,导致Store ->Load可能发生乱序。另外,在TSO内存一致性模型下,要想store->store保序,其中就要求write buffer是一个first-in-first-out的结构。
程序员可以通过显式的fence指令防止store和load指令之间的乱序。
fence指令的用途就是保证某个内核的fence指令前的所有memory访问能够在fence指令后的memory访问之前完成。
实际上fence指令(或者说是memory barrier)在后续我们即将介绍的弱序内存一致性中更为常用,而在TSO内存一致性模型中很少用,因为仅仅store-load的乱序在大多数情况下都是没有问题的。
到这里,我们已经介绍了顺序一致性和TSO一致性。
什么内存一致性模型才是好的模型呢?
Programmability: 应该可以让程序员比较轻松地编写多线程程序。对于大多数用户来说,该模型的实现应该和程序员的预期差不多 。
Performance: 应该具有比较合理的能效 。
Portability: 应该被广泛采用 。
Precision: 具有比较明确的行为定义,不存在歧义。
SC和TSO到底哪个好?
Programmability: SC实现行为是最直观的。TSO比较直观(存在store-load乱序)。
Performance: TSO可以提供比SC更好的性能。
Portability: SC更容易理解,但是TSO被更多采用。
Precise: 行为定义都比较明确。
原作者:验证哥布林