多种内存一致性模型的特性分析

早期的cpu是通过提高主频来提升cpu的性能,但是随着频率“红利”越来越困难的情况下,厂商开始用多核来提高cpu的计算能力。多核是指一个cpu里有多个核心,在同一时间一个cpu能够同时运行多个线程,通过这样提高cpu的并发能力。
内存一致性模型(memory consistency model)就是用来描述多线程对共享存储器的访问行为,在不同的内存一致性模型里,多线程对共享存储器的访问行为有非常大的差别。这些差别会严重影响程序的执行逻辑,甚至会造成软件逻辑问题。在后面的介绍中,我们将分析不同的一致性模型里,多线程的内存访问乱序问题。
目前有多种内存一致性模型:
顺序存储模型(sequential consistency model)
完全存储定序(total store order)
部分存储定序(part store order)
宽松存储模型(relax memory order)
在后面我们会分析这几个一致性模型的特性
在分析之前,我们先定义一个基本的内存模型,以这个内存模型为基础进行分析
上图是现代cpu的基本内存模型,cpu内部有多级缓存来提高cpu的load/store访问速度(因为对于cpu而言,主存的访问速度太慢了,上百个时钟周期的内存访问延迟会极大的降低cpu的使用效率,所以cpu内部往往使用多级缓存来提升内存访问效率。)
c1与c2是cpu的2个核心,这两个核心有私有缓存l1,以及共享缓存l2。最后一级存储器才是主存。后面的顺序一致性模型(sc)中,我们会以这个为基础进行描述(在完全存储定序、部分存储定序和宽松内存模型里会有所区别,后面会描述相关的部分)
为了简化描述的复杂性,在下面的内存一致性模型描述里,会先将缓存一致性(cache coherence)简单化,认为缓存一致性是完美的(假设多核cache间的数据同步与单核cache一样,没有cache引起的数据一致性问题),以减少描述的复杂性。
顺序存储模型是最简单的存储模型,也称为强定序模型。cpu会按照代码来执行所有的load与store动作,即按照它们在程序的顺序流中出现的次序来执行。从主存储器和cpu的角度来看,load和store是顺序地对主存储器进行访问。
下面分析这段代码的执行结果
在顺序存储器模型里,mp(多核)会严格严格按照代码指令流来执行代码
所以上面代码在主存里的访问顺序是:
s1 s2 l1 l2
通过上面的访问顺序我们可以看出来,虽然c1与c2的指令虽然在不同的core上运行,但是c1发出来的访问指令是顺序的,同时c2的指令也是顺序的。虽然这两个线程跑在不同的cpu上,但是在顺序存储模型上,其访问行为与up(单核)上是一致的。
我们最终看到r2的数据会是new,与期望的执行情况是一致的,所以在顺序存储模型上是不会出现内存访问乱序的情况
3完全存储定序
为了提高cpu的性能,芯片设计人员在cpu中包含了一个存储缓存区(store buffer),它的作用是为store指令提供缓冲,使得cpu不用等待存储器的响应。所以对于写而言,只要store buffer里还有空间,写就只需要1个时钟周期(哪怕是arm-a76的l1 cache,访问一次也需要3个cycles,所以store buffer的存在可以很好的减少写开销),但这也引入了一个访问乱序的问题。
首先我们需要对上面的基础内存模型做一些修改,表示这种新的内存模型
相比于以前的内存模型而言,store的时候数据会先被放到store buffer里面,然后再被写到l1 cache里。
首先我们思考单核上的两条指令:
s1:store flag= set
s2:load r1=data
s3:store b=set
如果在顺序存储模型中,s1肯定会比s2先执行。但是如果在加入了store buffer之后,s1将指令放到了store buffer后会立刻返回,这个时候会立刻执行s2。s2是read指令,cpu必须等到数据读取到r1后才会继续执行。这样很可能s1的store flag=set指令还在store buffer上,而s2的load指令可能已经执行完(特别是data在cache上存在,而flag没在cache中的时候。这个时候cpu往往会先执行s2,这样可以减少等待时间)
这里就可以看出再加入了store buffer之后,内存一致性模型就发生了改变。
如果我们定义store buffer必须严格按照fifo的次序将数据发送到主存(所谓的fifo表示先进入store buffer的指令数据必须先于后面的指令数据写到存储器中),这样s3必须要在s1之后执行,cpu能够保证store指令的存储顺序,这种内存模型就叫做完全存储定序(tso)。
我们继续看下面的一段代码
在sc模型里,c1与c2是严格按照顺序执行的
代码可能的执行顺序如下:
s1 s2 l1 l2
s1 l1 s2 l2
s1 l1 l2 s2
l1 l2 s1 s2
l1 s1 s2 l2
l1 s1 l2 s2
由于sc会严格按照顺序进行,最终我们看到的结果是至少有一个core的r1值为new,或者都为new。
在tso模型里,由于store buffer的存在,l1和s1的store指令会被先放到store buffer里面,然后cpu会继续执行后面的load指令。store buffer中的数据可能还没有来得及往存储器中写,这个时候我们可能看到c1和c2的r1都为0的情况。
所以,我们可以看到,在store buffer被引入之后,内存一致性模型已经发生了变化(从sc模型变为了tso模型),会出现store-load乱序的情况,这就造成了代码执行逻辑与我们预先设想不相同的情况。而且随着内存一致性模型越宽松(通过允许更多形式的乱序读写访问),这种情况会越剧烈,会给多线程编程带来很大的挑战。
4部分存储定序
芯片设计人员并不满足tso带来的性能提升,于是他们在tso模型的基础上继续放宽内存访问限制,允许cpu以非fifo来处理store buffer缓冲区中的指令。cpu只保证地址相关指令在store buffer中才会以fifo的形式进行处理,而其他的则可以乱序处理,所以这被称为部分存储定序(pso)。
那我们继续分析下面的代码
s1与s2是地址无关的store指令,cpu执行的时候都会将其推到store buffer中。如果这个时候flag在c1的cahe中存在,那么cpu会优先将s2的store执行完,然后等data缓存到c1的cache之后,再执行store data=new指令。
这个时候可能的执行顺序:
s2 l1 l2 s1
这样在c1将data设置为new之前,c2已经执行完,r2最终的结果会为0,而不是我们期望的new,这样pso带来的store-store乱序将会对我们的代码逻辑造成致命影响。
从这里可以看到,store-store乱序的时候就会将我们的多线程代码完全击溃。所以在pso内存模型的架构上编程的时候,要特别注意这些问题。
5宽松内存模型
丧心病狂的芯片研发人员为了榨取更多的性能,在pso的模型的基础上,更进一步的放宽了内存一致性模型,不仅允许store-load,store-store乱序。还进一步允许load-load,load-store乱序, 只要是地址无关的指令,在读写访问的时候都可以打乱所有load/store的顺序,这就是宽松内存模型(rmo)。
我们再看看上面分析过的代码
在pso模型里,由于s2可能会比s1先执行,从而会导致c2的r2寄存器获取到的data值为0。在rmo模型里,不仅会出现pso的store-store乱序,c2本身执行指令的时候,由于l1与l2是地址无关的,所以l2可能先比l1执行,这样即使c1没有出现store-store乱序,c2本身的load-load乱序也会导致我们看到的r2为0。从上面的分析可以看出,rmo内存模型里乱序出现的可能性会非常大,这是一种乱序随可见的内存一致性模型。
6内存屏障
芯片设计人员为了尽可能的榨取cpu的性能,引入了乱序的内存一致性模型,这些内存模型在多线程的情况下很可能引起软件逻辑问题。为了解决在有些一致性模型上可能出现的内存访问乱序问题,芯片设计人员提供给了内存屏障指令,用来解决这些问题。
内存屏障的最根本的作用就是提供一个机制,要求cpu在这个时候必须以顺序存储一致性模型的方式来处理load与store指令,这样才不会出现内存访问不一致的情况。
对于tso和pso模型,内存屏障只需要在store-load/store-store时需要(写内存屏障),最简单的一种方式就是内存屏障指令必须保证store buffer数据全部被清空的时候才继续往后面执行,这样就能保证其与sc模型的执行顺序一致。
而对于rmo,在pso的基础上又引入了load-load与load-store乱序。rmo的读内存屏障就要保证前面的load指令必须先于后面的load/store指令先执行,不允许将其访问提前执行。
我们继续看下面的例子:
例如c1执行s1与s2的时候,我们在s1与s2之间加上写屏障指令,要求c1按照顺序存储模型来进行store的执行,而在c2端的l1与l2之间加入读内存屏障,要求c2也按照顺序存储模型来进行load操作,这样就能够实现内存数据的一致性,从而解决乱序的问题。
arm的很多微架构就是使用rmo模型,所以我们可以看到arm提供的dmb内存指令有多个选项:
ld load-load/load-store
st store-store/store-load
sy any-any
这些选项就是用来应对不同情况下的乱序,让其回归到顺序一致性模型的执行顺序上去

构建广凌房产管理系统会带来哪些效益?
人工智能的下一步是什么?我们应如何定义生命?
STM32真的要比51单片机好用吗
芯讯通荣获2023汽车芯片大赛最佳合作伙伴奖
智慧医疗登上舞台 养老消费需求巨大
多种内存一致性模型的特性分析
家庭用户长时间使用液晶电视的注意事项
2020年6月正式实施GB4343.1-2018对部分家用电器辐射发射的要求
二次电池是什么_二次电池有哪些_二次电池充放电方程式
VMOS场效应管,VMOS场效应管是什么意思
人脸识别算法遇到的困难和挑战
夏普深陷亏损 郭台铭何以执著寻求“联姻”?
规避智慧医疗风险亟须法律支持
远程IO模块的特点
变速箱的倒挡原理
镭神智能荣获首批“广东省制造业单项冠军产品”称号
什么是硅光电池 ?
CineBench R23最新笔记本CPU跑分汇总
三星声称已开发出行业领先的Blue QLED技术,旨在加速QLED商业化
解读致钛SSD、3D NAND的故事