You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
ARM一直想冲击服务器市场,服务器一般cpu核心的数量都是几十个,上百个的,所以,刚才介绍的CCI控制器显然不能满足服务器的需求,所以,arm重新设计了一个新的缓存一致性控制器,叫做Cache Coherent Network,简称CCN,它可以支持48个核心,L3 cache,而且The L3 system cache allows IO and accelerators to allocate memory on chip。这个CCN是基于最新的AMBA 5协议的。
为什么要cache一致性( cache coherency )?
需要关注cache一致性的例子:
a. 驱动中使用DMA(数据cache和内存不一致)
b. Self-modifying code(数据cache的数据可能比指令cache新)
c. 修改了页表(TLB里保存的数据可能过时)
ARM的cache一致性的演进
单核处理器(Cortex-A8)
多核处理器(Cortex-A9 MP以及之后的处理器)
在2006年的时候,cortex-a8处理器横空出世,不过cortex-a8是一个单核的设计,单核处理器只有一个CPU,没有多核之间的cache不一致的问题,不过会有DMA和cache的一致性问题。
到了cortex-a9的时候,就有了多核设计(MPcore)了。多核设计的就需要在核与核之间通过硬件来保证cache的一致性问题,通常的做法是实现MESI类似的协议。
到了A15的时候,就出现了大小核的架构,大小核架构,相当于有两个cluster,每个cluster里有多个核心。cluster里的多个核心,我们就需要用mesi协议来保证一致性,那cluster与cluster之间呢?那么这时候就需要一个AMBA coherency extensions这样的缓存一致性的控制器来解决这个问题了。这个就是系统级别的cache一致性问题。Arm公司在这方面做了不少工作,有现成的IP可以使用,比如CCI-400,CCI-500等
一个例子
如上图, 第一个是单核处理器的情况,它只有一个cpu核心,和单一的cache,没有多核cache一致性问题。第二个图,是一个双核的处理器,每个核心内部有自己的cache,那么就需要一个硬件单元来完成这两个cache的一致性问题,通常就是我们说的SCU的硬件单元了。第三个图,要复杂一些,它由两个cluster组成,每个cluster有两个核心。我们来看一个cluster,它有一个缓冲一致性的硬件单元来保证core与core直接的一致性。那么在最下面有一个缓存一致性总线,或者缓存一致性控制器来保证这两个cluster之间的cache一致性问题
系统级别的cache一致性
系统cache一致性需要cache一致性内部总线(cache coherent interconnect)
我们来看一下系统级别的cache一致性问题。因为现在的arm系统越来越复杂了,从多核发展到多族,例如大小核架构等。比如下面这个图,这是一个典型的大小核架构,小核由A53来担当,大核由A72来担当,两个A53核心构成了一个cluster,这个cluster里,每个a53的cpu都有各自独立的L1 cache,然后一起共享一个L2 cache,然后通过一个ACE的硬件单元连接到缓存一致性总线里,ACE其实就是AXI coherent extensions的简称,这个是AMBA 4协议中定义的。我们再来看大核这边,它同样也是2个核心,每个核心都有一个L1 cache,也是共享一个L2 cache,同样也是通过ACE接口连接到缓存一致性总线上。那么除了CPU之外,系统还有GPU,比如arm公司的mali GPU,还有一些带有DMA的外设等,这些设备他们都有独立访问内存的能力,比如GPU还自己带有cache,那么他们也必须通过ACE接口来连接到这个缓存一致性总线上。这个缓存一致性总线,就是用来实现系统级别的cache一致性的
Cache一致性的解决方案
关闭cache
软件维护cache一致性
硬件维护cache一致性
MESI协议来维护多核cache一致性。ACE接口来实现系统级别的cache一致性
多核之间的cache一致性
Cache一致性协议:
MESI协议:
MESI协议
每个cache line有4个状态:
M:这行数据有效,数据已被修改,和内存中的数据不一致,数据只存在于该高速缓存中
E:这行数据有效,数据和内存中数据一致,数据只存在于该高速缓存中
S:这行数据有效,数据和内存中数据一致,多个高速缓存有这行数据的副本
I:这行数据无效
上面有三个状态都表示这一行cache line数据有效,那怎么去区别呢?
修改和独占状态的高速缓存行中,数据都是独有的,不同点在于修改状态的数据是脏的,和内存不一致;独占状态的数据是干净的,和内存一致。拥有修改状态的高速缓存行会在某个合适的时刻把该高速缓存行写回内存中,其后的状态变成共享状态。
共享状态的高速缓存行中,数据和其他高速缓存共享,只有干净的数据才能被多个高速缓存共享。
失效状态表示这个高速缓存行无效
MESI操作
本地读写:本地CPU读写自己私有的cache line,这是一个私有的操作
总线读写:读写远端CPU的cache line,CPU可以发送请求到总线上,所有的CPU都可以收到这个请求
初始状态下,当cache line中没有加载任何数据时,状态为I
MESI状态转换
当初始化状态为I时,并且发出本地读操作
当初始化状态为I时,并且发出本地写操作
我们假设CPU0发起了本地写请求,即CPU0发出读PrWr请求:
当初始化状态为M时
当本地CPU的cache line状态为M的情况,最简单就是本地读写了,因为M的状态,说明只有你有最新的数据,而且是dirty的数据,所以本地读写,状态不变
收到一个总线读的信号
本地CPU(假设是CPU0)上的cache line的状态为M,而在其他CPU上没有这个数据的副本。当其他CPU(如CPU1)想读这份数据时,CPU1会发起一次总线读操作,所以,流程是这样的:
a. 若CPU0上有这个数据的副本,那么CPU0收到信号后把cache line的内容发送到总线上,然后CPU1就获取这个cache line的内容。另外,CPU0会把相关内容发送到主内存中,把cache line的内容写入主内存中。这时候CPU0的状态从M->S
b. 更改CPU1上的cache line状态为S
收到一个总线写的信号
数据在本地CPU(假设是CPU0)上有副本并且状态为M,而其他CPU上没有这个数据的副本。若某个CPU(假设CPU1)想更新(写)这份数据,CPU1就会发起一个总线写操作。
若CPU0上有这个数据的副本,CPU0收到总线写信号后,把自己的高速缓存行的内容发送到内存控制器,并把该cache line的内容写入主内存中。CPU0上的高速缓存行状态变成I
CPU1从总线或者内存中取回数据到本地cache line,然后修改自己本地cache line的内容。
CPU1的状态变成M
当初始化状态为S时
初始化状态为E的cache line
MESI协议各个状态的转换关系(表格版)
MESI协议分析的一个例子
假设系统中有4个CPU,每个CPU都有各自的一级缓存,它们都想访问相同地址的数据A,大小为64字节。
请分析上述过程中, MESI状态的变化
高速缓存伪共享(False Sharing)
假设CPU0上的线程0想访问和更新data数据结构中的x成员,同理CPU1上的线程1想访问和更新data数据结构中的y成员,其中x和y成员都缓存到同一个高速缓存行里。
根据我们前面学会的MESI协议的状态图,我们可以分析出CPU0和CPU1之间对高速缓存行的争用情况
综上所述,如果CPU0和CPU1反复修改,就会不断地重复步骤(4)和步骤(5),两个CPU都在不断地争夺对高速缓存行的控制权,不断地使对方的高速缓存行无效,不断地把数据写回内存,导致系统性能下降,这种现象叫作高速缓存伪共享
高速缓存伪共享的解决办法
高速缓存伪共享的解决办法就是让多线程操作的数据处在不同的高速缓存行,通常可以采用高速缓存行填充(padding)技术或者高速缓存行对齐(align)技术,即让数据结构按照高速缓存行对齐,并且尽可能填充满一个高速缓存行大小
下面的代码定义一个counter_s数据结构,它的起始地址按照高速缓存行的大小对齐,数据结构的成员通过pad[4]来填充。这样, counter_s的大小正好 是一个cache line的大小,64个字节,而且它的起始地址也是也cache line对齐
系统间的cache一致性
系统cache一致性的解决方案,其实在arm公司实现的AMBA总线里,AMBA总线协议里定义了一个叫做ACE的接口,这个接口规范执行了Hardware Cache Coherency
cache一致性,需要保证系统中所有的CPU,所有的bus master从,例如GPU,DMA等,他们观察到的内存是一致的
一般情况下系统的cache一致性有三种方案:我们在前面已经和大家分析过了。
基于ACE接口协议,arm公司设计了几款cache一致性的控制器。
CCI缓存一致性控制器
这里列出了ARM公司几款CCI控制器,CCI就是Cache Coherent Interconnect的简称
我们以最常见的CCI-400为例,它支持2个cluster,最大支持8个CPU,支持2个ACE slave接口,支持1~3个ACE lite slave接口,然后他使用broadcast snoop coherency策略
下面这个框图是经典的使用大小核的框图,并且使用了CCI-400这个缓存一致性的控制器
大家可以看到,中间这个就是CCI-400的控制器,那么大小核的A57和A53都连接到这个CCI-400上,还有Mali GPU也连接到CCI-400里,除此之外,还有DDR内存,通过DMC-400的内存控制器连接到CC400里,当然还有一些外设,也可以通过ACE Lite接口连接到 CCI400上
CCN缓存一致性控制器
ARM一直想冲击服务器市场,服务器一般cpu核心的数量都是几十个,上百个的,所以,刚才介绍的CCI控制器显然不能满足服务器的需求,所以,arm重新设计了一个新的缓存一致性控制器,叫做Cache Coherent Network,简称CCN,它可以支持48个核心,L3 cache,而且The L3 system cache allows IO and accelerators to allocate memory on chip。这个CCN是基于最新的AMBA 5协议的。
这个表格就是几款CCN IP的规格,最高规格的CCN-512,最大支持48个核心,支持12个cluster,支持L2 cache,1-32MB,最高达到225GB每秒的传输数率
CCN的这个IP的芯片手册现在还没有公开下载,所以,我们只能通过一些简单的介绍资料来了解。
下面这个图是一个典型的CCN控制器的应用场景。这个一个服务器的配置,它支持48个A72,集成了32MB的L3 cache,还支持DDR3/4内存颗粒,支持24 个cache一致性的IO port。总之就是一个典型的服务器配置
高速缓存伪共享的避免
例如 struct zone 数据结构使用 ZONE_PADDING 技术(填充字节的方式)来让频繁访问的成员在不同的 cache line 中
DMA的cache一致性
DMA的cache一致性解决方案
硬件解决办法,需要ACE支持(咨询SoC vendor)
使用non-cacheable的内存来进行DMA传输
软件干预cache一致性,根据DMA传输数据的方向,软件来维护cache一致性
Case 1:内存->设备FIFO (设备例如网卡,通过DMA读取内存数据到设备FIFO)
在DMA传输之前,CPU的cache可能缓存了内存数据,需要调用cache clean/flush操作,把cache内容写入到内存中。因为CPU cache里可能缓存了最新的数据
Case 2:设备FIFO -> 内存 (设备把数据 写入到 内存中)
在这个场景下,设备的FIFO产生了新数据,需要把数据写入到DMA buffer里,然后主机的软件就可以读到设备的数据,这个非常类似网卡的收包的过程.
在DMA传输之前,需要把cache 做invalid操作。因为此时最新数据在设备FIFO中,CPU缓存的cache数据是过时的,一会要写入新数据,所以做invalid操作
DMA小结:
把这两个问题想清楚了,就能知道是要clean cache还是要invalidate cache里
self-modifying code
问题:
self-modifying code解决办法:
解决的思路是,使用cache管理指令和内存屏障指令来保证数据cache和指令cache的一致性。
在armv8手册里,有一段简单的英文来介绍self-modifying code,它是在Armv8.6手册最后面术语一章里面。在这段简单的英文里,我们可以得到重要的信息,就是解决self-modifying code的指令cache和数据cache不一致的问题,需要使用cache管理指令和内存屏障指令来手动干预
解决思路:
在armv8.6手册里,有一段描述这个过程的, 在B2.4.4
参考资料
https://blog.csdn.net/armlinuxww/article/details/110228343?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-2&spm=1001.2101.3001.4242
https://zhuanlan.zhihu.com/p/135462276
The text was updated successfully, but these errors were encountered: