内存一致性模型
一、背景介绍
在上个世纪的处理器设计当中,指令是完全按照顺序执行的。而现代 CPU 为了提高性能,已经抛弃了这种古老的顺序执行模型,采用很多现代化的技术,比如流水线、写缓存、高速缓存、超标量技术、乱序执行等。这些新技术其实对编程者来说是不可见的:编译时,编译器优化导致内存乱序访问。执行时,多个 CPU 的交互引起内存乱序访问。
所以,在多处理器的情况下,为了保证内存访问的一致性,需要按照某种规则来选出合适的组合, 这个规则叫作内存一致性模型(memory consistency model)。 这个规则需要在保证正确性的前提下,同时保证多个处理器访问时有较高的并行度。
二、顺序一致性内存模型
在一个单核处理器系统中,保证访问内存的正确性比较简单。每次存储器读操作所获得的结果是最近写入的结果,但是在多个处理器并发访问存储器的情况下就很难保证其正确性了。
我们很容易想到使用一个全局时间比例(global time scale)部件来决定存储器访问时序,从而
判断最近访问的数据。 这种访问的内存一致性模型是严格一致性(strict consistency) 内存模型,称为原子一致性(atomic consistency)内存模型。
实现全局时间比例部件的代价比较大,因此退而求其次。 采用每一个处理器的局部时间比例(local time scale) 部件来确定最新数据的内存模型称为顺序一致性(Sequential Consistency, SC) 内存模型。 1979 年, Lamport 提出了顺序一致性的概念。顺序一致性可以总结为两个约束条件。
- 从单处理器角度看,存储访问的执行次序以程序为准。
- 从多处理器角度看,所有的内存访问都是原子性的,其执行顺序不必严格遵循时间顺序
顺序一致性内存模型保证了每一条加载/存储指令与后续加载/存储指令严格按照程序的次序来执行,即保证了“读→读”“读→写”“写→写”以及“写→读” 4 种情况的次序
三、处理器一致性内存模型
处理器一致性(Processor Consistency, PC) 内存模型是顺序一致性内存模型的进一步弱化,
放宽了较早的写操作与后续的读操作之间的次序要求,即放宽了“写→读”操作的次序要求。
处理器一致性模型允许一条加载指令从存储缓冲区(store buffer)中读取一条还没有执行的存
储指令的值,而且这个值还没有被写入高速缓存中。 x86_64 处理器实现的全序写(Total Store
Ordering, TSO)模型就属于处理器一致性内存模型的一种
四、弱一致性内存模型
对处理器一致性内存模型进一步弱化,可以放宽对“读→读”“读→写”“写→写”以及“写→读” 4 种情况的执行次序要求, 不过这并不意味着程序就不能得到正确的预期结果。 其实在这种情况下,程序需要添加适当的同步操作。例如,若一个处理器的存储访问想在另外一个处理器的存储访问之后发生,我们需要使用同步来实现,这里说的同步操作指的是内存屏障指令。
对内存的访问可以分成如下几种方式。
- 共享访问:多个处理器同时访问同一个变量,都是读操作。
- 竞争访问:多个处理器同时访问同一个变量,其中至少有一个是写操作,因此存在竞争访问。
例如,一个写操作和一个读操作同时发生可能会导致读操作返回不同的值,
这取决于读操作和写操作的次序。在程序中适当添加同步操作可以避免竞争访问的发生。与此同时,在同步点之后处理器可以放宽对存储访问的次序要求,因为这些访问次序是安全的。基于这种思路,存储器访问指令可以分成数据访问指令和同步指令(也称为内存屏障指令)两大类,对应的内存模型称为弱一致性(weak consistency)内存模型
五、ARM64 处理器的内存模型
前面介绍了几种内存模型,其中弱一致性内存模型在 ARM64 处理器上得到广泛应用。在
普通类型内存里实现的就是弱一致性内存模型。 在弱一致性内存模型下, CPU 的加载和存储
访问的序列有可能和程序中的序列不一致。因此, ARM64 体系结构的处理器支持如下预测式的
操作。
- 从内存中预取数据或者指令。
- 预测指令预取。
- 分支预测(branch prediction)。
- 乱序的数据加载(out of order data load)。
- 预测的高速缓存行的填充(speculative cache line fill),这里主要涉及包括 LSU(LoadStore Unit, 加载存储单元)、 存储缓冲区、 无效队列以及缓存等与内存相关的子系统。
注意, 预测式的数据访问只支持普通类型内存, 设备类型内存是不支持预测式的数据访问的,因为设备内存实现的是强一致性的内存模型,它的内存访问次序是强一致性的。另一个场景是指令的预取是否支持预测式。指令预取和数据存储是两种不同的方式,一个在 CPU 的前端,一个在 CPU 的后端。在 ARMv8 体系结构里,预测式的指令预取是可以支持任意内存类型的,包括普通内存和设备内存。
参考:
内存一致性模型_宽松内存模型-CSDN博客
https://zhuanlan.zhihu.com/p/694673551