CPU一致性的解决办法
博主微信:flm13724054952,不懂的有疑惑的也可以加微信咨询,欢迎大家前来指教共同探讨,谢谢!博主最近的工作是CPU集成设计,所以接下来的篇章将以CPU的学习讲解为主。最后再打个小广告,欢迎各位对数字IC设计感兴趣的博友来我们公司“众星微”,可以内推哦。
about Coherency
如下图所示,在芯片系统一般会有放OS程序的L2 Cache或者main memory。当系统是一个单主机的CPU处理器,那么系统便不会有一致性的数据问题。
当一个系统存在多个主机(多个CPU)的时候,当多个主机同时访问相同的MEM时候,如果一个或者多个CPU有自己的cache时候就会出现以下的问题:
(1)CPU0写数据到L2 Cache的地址Q,但是采用的是write-back缓存,导致数据写在他自己的L1 Cache里面,而当CPU1去读取L2 Cache的地址Q,这个时候读到的数据就是旧的数据。
(2)CPU1读L2 Cache的地址Q数据并缓存数据到自己的L1 Cache,然后CPU0继续写数据到L2 Cache的地址Q,采用write-through写缓存到L2 Cache,然后当CPU1继续读地址Q,但是读的数据是从自己的L1 Cache搬移,那么这个时候读取到的依然是旧的数据。
Coherency policy
当Cortex-R5在集成双核的时候,每一个CPU可以拥有自己的L1 Cache。而且Cortex-R5也可以与其他主机一起集成在同个系统里,只是这个时候难免会遇到一致性的问题,那这个时候就得考虑如何解决一致性的问题了。
下面就有五种办法:
(1)数据不共享:当确保多个CPU之间不会访问一样的地址数据即可,那么就不会出现一致性问题。
(2)数据共享但是不缓存:即对于共享区域的数据永远不会缓存到自己的L1-Cache里面去,确保实时共享数据为最新的。但是如果遇到CPU连上L2 Cache的时候,那么共享区域的数据就有可能会缓存到L2 Cache里面去,这个时候就要来配置一下L2 Cache的区域属性。
(3)数据共享但是仅仅缓存在share cache:即多个CPU共用分享一块L2 Cache,并且不会缓存数据到他们本身的L1 Cache里面去,确保L2 Cache的数据永远是一致性的。
(4)软件缓存维护操作:缓存维护操作可以用于操作cache当与其他CPU共享数据时。例如在第一个例子里面,如果CPU0采用write-through方式缓存就可以避免上面第一个例子的一致性问题;而对于第二个例子的一致性问题,如果CPU1执行缓存维护操作是使其本身的cache位置数据无效,那么就会去L2 Cache读取到正确的数据。也就是说可以通过软件方式执行invalidate operations跟barrier operations来规避一致性的问题。
(5)硬件一致性:CPU与本身L1 Cache之间增加一致性逻辑,通过执行适当的缓存操作来确保与其他CPU共享数据的一致性。一般来说在多核CPU里面都会有一致性逻辑电路cluste来共享核与核之间数据。在Contex-R5里面没有提供MP-cluster的一致性电路,只是简单提供了一致性的ACP接口。
MESI/MEOSI Protocol
MESI/MEOSI是现在一种使用广泛的协议,用来维护多核Cache一致性。我们可以将MESI看做是状态机。cache contronal会将每一个cache line进行状态标记,并且维护状态的切换。cache line的状态有M (Modified), O (Owned), E (Exclusive), S (Shared) or I (Invalid)。
1、Modified :代表当前Cache行的数据是修改过的(Dirty),并且只在当前CPU的Cache中是修改过的;此时该Cache line的数据与其他Cache中的数据不同,与内存中该行的数据也不同。
2、Owned:指示当前cache line的数据是dirty并且有可能其他CPU的cache也有。但是只有当前的这个CPU可以保持这个状态Owned,其他CPU只能显示为shared状态。
3、Exclusive:代表当前Cache line的数据是有效数据,其他CPU的Cache中没有这行数据;并且当前Cache line数据与内存中的数据相同。
4、Shared:代表多个CPU的Cache中均缓存有这行数据,并且Cache中的数据与内存中的数据一致;
5、Invalid:表示当前Cache line中的数据无效;
其中Owned是在MEOSI Protocal特有的,在ARM的CPU体系里面,Cortex-A9等系列用的就是MESI Protocal。这里讲基础的MESI Protocal为例。下图为MESI协议的状态机切换图:
继续以上面的问题(1)为例与这个MESI Protocal状态机结合做讲解:
(1)当CPU0采用write-back写数据到L2 Cache的地址Q,数据被缓存到CPU0的L1 Cache,此时L2 Cache还没有缓存到地址Q数据,所以cache控制器标记此cache line状态为Modified 。Modified 代表cache line对应的数据仅在数据只在CPU0的L1 Cache之中,并且其cache中的内容与L2 Cache的内容不一致。
(2)然后CPU1请求读地址Q数据之前,并发送消息给CPU0,发现数据被缓存到CPU1的L1 Cache。然后cache控制器将数据从CPU0 Cache传输到L2 Cache再返回给CPU1。此时CPU0和CPU1同时缓存地址Q数据,此时cache line状态从Modified 切换到Shared状态。Shared代表cache line对应的数据在”多”个CPU私有Cache中被缓存,并且其在缓存中的内容与主存的内容一致。
(3)CPU0继续写修改地址Q数据,发现地址Q内容所在cache line状态是Shared。CPU0发出invalid消息传递到其他CPU,这里是CPU1。CPU1接收到invalid消息。将地址Q所在的cache line置为Invalid状态。Invalid状态表示表明当前cache line无效。然后CPU0收到CPU1已经invalid的消息,修改地址Q所在的cache line中数据。并再次更新cache line状态为Modified。
(4)如果CPU0继续修改地址Q数据,此时发现其对应的cache line的状态是Modified。因此CPU0不需要向其他CPU发送消息,直接更新数据即可。
summary
多核CPU的Cache一致性是在CPU内部做硬件电路设计来保证,对软件来说是透明的。另外,现在CPU硬件采用的一致性协议一般是MESI协议的改进版MEOSI协议。例如最新ARM64架构采用的MOESI Protocol。多一种Owned状态。而多出来的状态也是为了更好的优化性能。