ver 0.2
前言
前面的文章中阐述了Cache相关的基础概念,以及Cache在使用的中的一些策略,而且我们还单独开了一篇文章介绍了cache的多级架构。在介绍Cache的策略的时候,我们在纵向的维度介绍了Cache机制在运行时的一些场景下的处理方式。那么本文我们将从横向的维度介绍Cache机制在各个Core之间、各个Cluster之间、以及各个Master之间的一致性问题。
正文
Cache一致性的介绍将从三个部分展开:首先是一致性的基础、一致性的机制、一致性编程的相关课题。
1. 一致性的相关基础
本节我们将详细梳理Cache一致性相关的基础概念,扫清后续章节展开的障碍。让我们来看一下典型的基于ARM架构的SOC的实例,现代处理器早已经不是一个单独的计算单元(CPU)那么简单,目前基于ARM架构的SOC已经集成了各种功能的处理单元,如图1-1所示。前面讲解Cache的多级架构的时候我们介绍了一致性总监CCI和CMN以及它们是如何通过CHI、ACE等接口将各个独立的功能模块通过总线以分布式、模块化的形式串联到了一起,以总线的视角看过去,这些独立的功能模块我们可以称之为Master,如图1-1中CPU、GPU、VPU、ADSP等等。
上面叙述的视角还是基于硬件(总线)的视角看过去SOC,但是实际在程序眼中这些Master是通过内存模型联系到一起的,啥AMBA、CHI、ACE、InterconnectBUS等,都是透明的,他们在编写启动代码、BSP代码、应用层代码的时候只认识内存地址已经地址空间。那么这里Memory Master就是一个很关键的节点了,可以说是其他的一些Master,例如NPU或者ADSP等可以在一些嵌入式设备上剪裁掉,例如电话手表,但是内存是物理如何都要保留的。
基于这样一个背景,结合前序的文章我们知道,为了提高CPU以及各个协处理的执行速度,引入了Cache机制,就是缓存一部分内存中的数据到Cache中。这个世界普遍的一个真理,就是这个世界上所有的事物都是矛盾的,比如Cache机制也一样,享受了它带来的优势就要承受它让人挠头的一面。前面我们在讲述Cache策略的时候,比如对Cache执行写的时候,就算是Cache命中的情况下还有Write Back这样的策略,也就是PE-Core把数据送到Cache就结束了,内存中与Cache相对应数据要靠Cache Controller在合适的时机更新。那么在内存中的数据这一段时间内,被其他的PE-Core访问或者其他的Master访问,怎么办?这就会引出我们今天要讨论的问题,Cache的一致性。
1.1 Cache一致性的概念
有了前面的介绍,我们这里可以整理一下,对Cache的一致性下一个定义,先来看看ARM手册中的说法。
Coherency means ensuring that all processors or bus masters within a system have the same view of shared memory. It means that changes to data held in the cache of one core are visible to the other cores, making it impossible for cores to see stale or old copies of data. This can be handled by simply not caching, that is disabling caches for shared memory locations, but this typically has a high performance cost.
我们结合总线架构,重新整理一下一致性的定义:
Cache一致性是一种软件或者硬件的机制,这种机制可以保证在CPU的微架构中引入Cache之后,并发场景下保证CPU内部各个PE-Core之间以及SOC中所有的Master之间使用的共享的内存中的数据始终是保持一致的,不会产生歧义。
让我们具象化一下,让大家能够理解:
(1) 保证多线程之间共享的数据始终保持一致,不会产生逻辑错误,生产者线程更新的数据能及时同步到消费者线程。(PE-Core之间的数据一致)
(2) 保证跑在CPU上驱动程序维护的图层数据和DPU中数据一致,从而避免显示器上显示的数据不至于花屏。(总线上Master之间的数据一致)
1.2 维护一致性的场景
这一节,我们梳理一下本文要讨论的一致性课题的范围,基于总线架构和CPU的微架构,大致分成三个场景:
(1) Cluster内部各个PE-Core之间的Cache一致性,讨论Big.Little架构或者DSU架构下一个Cluster内的各个PE-Core之间是如何实现Cache一致性的。(图1-1 Master1中高性能Cluster中的4个PE-Core之间的视角)
(2) Cluster之间的Cache一致性,讨论Big.Little架构或者DSU架构下各个Cluster中的PE-Core之间的Cache一致性问题,例如Cluster-0中的A53-Core中的Cache和Cluster-1中A57-Core的Cache是如何保持一致性的。(图1-1 Master1中高性能Cluster中的4个PE-Core之间和低功耗Cluster的4个PE-Core之间的视角)
(3) CPU和其他Master之间的一致性,例如GPU和CPU中的数据一致性问题,或者一个USB设备中的数据和驱动中数据的一致性。(图1-1,Master1和Master2之间或者Master-1和Master7之间的视角)
后面章节我们会详细讨论这三个场景下的一致性问题。
1.3 维护⼀致性的方式
前面我们讨论了Cache一致性的基础概念和需要做一致性管理的场景,这里我们要讨论基于ARM体系的一致性管理的方式,这里我们直接引用ARM的原文。
There are three mechanisms to maintain coherency:
Disable caching
This is the simplest mechanism but might cost significant core performance. To get the highest performance processors are pipelined to run fast, and to run from caches that offer a very low latency. Caching of data that is accessed multiple times increases performance significantly and reduces DRAM accesses and power. Marking data as “non-cached” could impact performance and power.
Software managed coherency
Software managed coherency is the traditional solution to the data sharing problem. Here the software, usually device drivers, must clean or flush dirty data from caches, and invalidate old data to enable sharing with other processors or masters in the system. This takes processor cycles, bus bandwidth, and power.
Where there are high rates of sharing between requesters the cost of software cache maintenance can be significant, and can limit performance.
Hardware managed coherency
Hardware maintains coherency between level 1 data caches within a cluster. A core automatically participates in the coherency scheme when it is powered up, has its D-cache and MMU enabled, and an address is marked as coherent.
However, this cache coherency logic does NOT maintain coherency between data and instruction caches.
In the ARMv8-A architecture and associated implementations, there are likely to be hardware managed coherent schemes. These ensure that any data marked as shareable in a hardware coherent system has the same value seen by all cores and bus masters in that shareability domain. This adds some hardware complexity to the interconnect and to clusters, but greatly simplifies the software and enables applications that would otherwise not be possible using only software coherency.
这里我们简单解释一下:
▪ 禁⽤缓存
鲁迅先生曾经说过:解决不了问题,就解决提出问题的人。既然在CPU的微架构中引入Cache会引发一致性问题,那么禁止Cache这不就解决一致性问题了嘛。早期的CPU还真是这样的,因为调校一致性真的是非常耗费脑细胞的事情,干脆就别上这个Cache机制了,至于访问内存的性能问题,那就留给后来人,因为后来人总是聪明的。好在,后来人还真的是聪明的,现在ARM手册中已经删除了禁用缓存机制的相关表述。
▪ 软件管理的⼀致性
这种方式在目前的阶段应该算是一种对硬件管理一致性的补充,而不是主要的方式,道理很简单,因为软件管理方式的成本太高了,性能提高多少且放一放,软件工程师都得累死,所以说只能是个别硬件一致性机制覆盖不到的场景下的一种补充。想想只要共享且支持的共享数据,在CPU和Master之间的软件驱动代码中要时刻识别上下文,做清除或刷新缓存中的脏数据,并使旧数据⽆效,以便与系统中的其他处理器或主设备共享。这不仅需要处理器周期、总线带宽和功率,也需要码农的头发。
▪硬件管理的⼀致性
提供了⼀种简化软件的替代⽅案,或者说是降低了软件管理Cache一致性的使用频率。使⽤此解决⽅案,任何标记为“共享”的缓存数据将始终⾃动更新。该共享域中的所有处理器和总线主控器看到的值完全相同。但是,在总线架构层面,对于那些不支持探测功能的Master还要有软件管理Cache的方式作为补充来保证一致性。在CPU架构层面和总线架构层面引入了硬件管理一致性后,绝大多数的场景下,码农们可以说是解放了双手,这一点也是要讲清楚。
1.5 Cache的维护机制(软件管理)
上面说了,Cache可以通过软件的方式做清除和冲刷以及无效操作,这一节就简要做一下Cache维护的一些操作,就算是天生的武学奇才苏乞儿练就打狗棒法之前也要给他一根棍子吧。这里先引用一段手册中的原文,
It is sometimes necessary for software to clean or invalidate a cache.
• Invalidation of a cache or cache line means to clear it of data, by clearing the valid bit of one or more cache lines. The cache must always be invalidated after reset as its contents are undefined. This can also be viewed as a way of making changes in the memory domain outside the cache visible to the user of the cache.
• Cleaning a cache or cache line means writing the contents of cache lines that are marked as dirty, out to the next level of cache, or to main memory, and clearing the dirty bits in the cache line. This makes the contents of the cache line coherent with the next level of
the cache or memory system. This is only applicable for data caches in which a write-back policy is used. This is also a way of making changes in the cache visible to the user of the outer memory domain, but is only available for data cache.
• Zero. This zeroes a block of memory within the cache, without the need to first of all read its contents from the outer domain. This is only available for data cache.
这部分不做过多的解释,就是ARM提供了一些直接操作Cache的指令,可以通过软件编程的方式管理Cache的上下文,这里截图一部分指令,如图1-2所示,但不做展开讨论,必要时大家可以查询手册。
1.5 一致性管理的数据(内存的属性)
Cache缓存的是内存中的数据,那么是不是所有内存中的数据都可以被缓存,被缓存的共享数据是否可以被所有Master共享,有没有范围限制,本节就是回答这些问题。先来看一下手册中的描述:
Data memory accesses can take longer and consume more power with cache coherency hardware than they otherwise would do. This overhead can be minimized by maintaining coherency between a smaller number of masters while ensuring that they are physically close in the processor. For this reason, the architecture splits the system into domains, and makes it possible to limit the overhead to those locations where the coherency is required.
Software must define which address regions are to be used by which group of masters, that is which other masters are sharing this address, by creating appropriate translation table entries. For Normal cacheable regions, this means setting the shareable attribute to one of Non-shareable, Inner Shareable, or Outer Shareable. For non-cacheable regions, the shareable attribute is ignored.
Locations marked as Normal also have cacheability and shareability attributes. The cacheability attributes control whether a location can be cached. If a location can be cached, the shareability attributes control which other agents need to see a coherent copy of the memory. This allows for some complex configuration, which is beyond the scope of this guide. However, Arm expects operating systems to mark the majority of DRAM memory as Normal Write-back cacheable, Inner shareable.
讨论Cache的一致性问题还是绕不开内存,事实上ARM体系的很多子系统都绕不开内存,因为内存子系统太重要了,它足够庞大、足够有趣,让我们可以深入的研究下去。这里我们还是简单分解一下,从哪儿说起呢,还是从签字售书说起吧。先来看一下ARM的内存模型,ARM将内存分层了两个大类Device和Normal两种类型,如图1-3所示:
除了设备空间(IO空间)的内存之外,全部的Normal类型的内存理论上都是可以Cache的,但是这部分Normal内存的是可以配置的,配置的基本单位是页或者块,如图1-4所示。
通过图1-4可以看到页表项的提供了很多属性位供软件进行编程配置,这些属性具体如图1-5所示:
这些属性中就有配置共享的属性,这些页表的属性可以在使用的时候被配置成相应的共享属性,显然这个属性是有范围的,如图1-6、1-7所示。其实很好理解了,内存可以配置成不能共享,那么就会被PE-Core独占,也可以被配置成所有的PE-Core共享,最后还可以被配置成所有的Master共享,比如和GPU共享图层数据,具体如图1-8所示。
那么接下来,我们看一下内存管理的体系下是如何配置cache属性的,如图1-9所示,除了前面介绍的通过指令可以干预Cache运行的机制,这里ARM还提供了另外一个通道干预Cache的行为,如图1-9、1-10所示。
通过本节的介绍了,我们终于破解了Cache一致性管理的根源,就是源于内存中的数据可以在PE-Core之间,总线的Master和CPU之间共享,而现代处理器的多指令流执行的环境下,被共享的数据的一致性非常重要,为了在多线程的执行环境下不产生共享数据的额歧义,所以才会产生Cache数据的一致性管理的课题。
作为介绍Cache一致性的预备知识,这里我们简单的介绍一下,不展开讨论,而关于ARM内存的模型和管理,我们会开一个专门的系列专门讨论,这里大家只需要知道Cache一致性问题的由来就可以了。
结语
关于Cache的一致性,写着写着就超了篇幅了,这里就分成了两部分,先介绍理解Cache一致性的预备知识,下一篇再介绍现在ARM体系下采用的Cache的一致性策略。现在大多数的场景都能够被处理器的硬件吸收了,程序员其实不太需要关注一致性的相关细节,作为基础知识作为补充就可以了。硬件越强大,码农还是越幸福的,不用拘泥于繁杂的底层一致性问题的调查中,但是还是有需要注意的点,这些下一篇文章也会加以介绍。
谢谢大家,请大家保持关注。
Reference
[01] <DDI0487K_a_a-profile_architecture_reference_manual.pdf>
[02] <DEN0024A_v8_architecture_PG.pdf>
[03] <80-LX-MEM-yk0008_CPU-Cache-RAM-Disk关系.pdf>
[04] <80-ARM-ARCH-HK0001_一文搞懂CPU工作原理.pdf>
[05] <80-ARM-MM-Cache-wx0003_Arm64-Cache.pdf>
[06] <80-ARM-MM-HK0002_一文搞懂cpu-cache工作原理.pdf>
[07] <80-MM-yd0001_Caches-From-a-Mostly-OS-Software-Perspective.pdf>
[08] <80-MM-yd0002_Improving-Kernel-Performance-by-Unmapping-the-Page-Cache.pdf>
[09] <arm_cortex_a710_core_trm_101800_0201_07_en.pdf>
[10] <DDI0608B_a_armv9a_supplement_RETIRED.pdf>
[11] <arm_cortex_a520_core_trm_102517_0003_06_en.pdf>
[12] <arm_cortex_a720_core_trm_102530_0002_05_en.pdf>
[13] <79-LX-LK-z0002_奔跑吧Linux内核-V-2-卷1_基础架构.pdf>
[14] <80-ARM-MM-Cache-wx0001_Cache多核之间的一致性MESI.pdf>
[15] <80-ARM-MM-Cache-wx0002_深度学习armv8_armv9_cache的原理.pdf>
[16] <80-ARM-MM-Cache-ym0001_带着几个疑问-从Cache的应用场景学起.pdf>
[17] <80-ARM-MM-Cache-ym0002_Cache是如何工作的-概念以及工作过程.pdf>
[18] <80-ARM-MM-Cache-ym0003_多核多Cluster多系统之间的缓存一致性.pdf>
[19] <DDI0500J_cortex_a53_trm.pdf>
[20] <DDI0488H_cortex_a57_mpcore_trm.pdf>
[21] <cortex_a72_mpcore_trm_100095_0003_06_en.pdf>
[22] <corelink_cci550_cache_coherent_interconnect_technical_reference_manual_100282_0100_01_en.pdf>
[23] <80-ARM-DyIQ-wx0001_ARM架构系列(2)-DynamIQ技术.pdf>
[24] <ARM_DynamIQ_The_future_of_multi-core_computing.pdf>
[25] <cortex_a72_mpcore_trm_100095_0003_06_en.pdf>
[26] <arm_cortex_a710_core_trm_101800_0201_07_en.pdf>
[27] <DEN0013D_cortex_a_series_PG.pdf>
[28] <DDI0329L_l220_cc_r1p7_trm.pdf>
[29] <arm_dsu_120_trm_102547_0201_07_en.pdf>
[30] <80-Cache-MESI-yd0001_Cache_coherency_controller_for_MESI_protocol_based.pdf>
[31] <80-Cache-MESI-yd0002_cache-coherence.pdf>
[32] <80-Cache-MESI-yd0003_Cache-coherence-in-shared-memory-architectures.pdf>
[33] <80-Cache-MESI-yd0004_Designing-Predictable-Cache-Coherence-Protocols-for-Multi-Core-Real-Time-Systems.pdf>
Glossary
SRAM - Static Random-Access Memory
DRAM - Dynamic Random Access Memory
SSD - Solid state disk
HDD - Hard Disk Drive
SOC - System on a chip
AMBA - Advanced Microcontroller Bus Architecture 高级处理器总线架构
TLB - translation lookaside buffer(地址变换高速缓存)
VIVT - Virtual Index Virtual Tag
PIPT - Physical Index Physical Tag
VIPT - Virtual Index Physical Tag
AHB - Advanced High-performance Bus 高级高性能总线
ASB - Advanced System Bus 高级系统总线
APB - Advanced Peripheral Bus 高级外围总线
AXI - Advanced eXtensible Interface 高级可拓展接口
DSU - DynamIQ Share Unit
ACE - AXI Coherency Extensions
CHI - Coherent Hub Interface 一致性集线器接口
CCI - Cache Coherent Interconnect
ADB - AMBA Domain Bridge
CMN - Coherent Mesh Network