很多人都听说过“缓存一致性”(cache coherency)这一词,但并不完全了解在系统级芯片(SoC)组件的情况下,尤其是在使用片上网络(network-on-chip,NoC)时,缓存一致性的注意事项。为了掌握这些问题,首先必须先了解在内存层结构中的缓存作用。
在CPU内部的寄存器数量相对较少,但速度极快。CPU可以在一个时钟周期内访问这些寄存器。不过,它们的储存容量很小。相比之下,访问主内存进行数据读写则需要占用很多时钟周期。因此,这往往导致CPU在大部分时间都处于闲置状态。
1965年,英国计算机科学家Maurice Wilkes提出了“高速缓存”(cache memory)和“内存缓存”(memory caching)的概念。这涉及在CPU近旁设置少量被称为缓存的快速内存。缓存(cache)一词源于法语“cacher”,意思是“隐藏”(hide)或“隐蔽”(conceal),其概念在于利用缓存将主内存隐藏起来,以隔绝于CPU之外。图1是包括简单缓存的内存层结构排列视图。
图1:高速缓存层中的位置。(来源:Arteris)
这一过程的运行基于两个关键点。首先,当CPU上运行的程序涉及主内存中的一个位置时,通常会对附近的几个位置执行操作。因此,当CPU请求从主内存中获取单项数据时,系统就会从附近的位置导入数据。这种方法确保了相关数据在需要时随时可用。其次,程序通常会对相同的数据集进行大量操作。因此,将常用数据储存在最靠近CPU的缓存中是有益的,这种邻近性允许更快地存取和处理数据。
在SoC中,缓存主要以高速、高功率和低容量的SRAM在芯片上实现。同时,主内存则在印刷电路板(PCB)上的外接芯片(off-chip)上实现,通常采用低速、低功耗且高容量的DRAM形式。
为了尽可能地减少延迟,设计人员在当今的许多SoC中添加了多级缓存。这通常包括三个层级:L1、L2和L3。L1缓存最接近CPU、容量最小,但访问最快,通常在1~2个时钟周期内。L2缓存离CPU稍远,提供更高的容量但访问较慢,通常在4~10个时钟周期之间。L3缓存离CPU更远,提供三者中最大的容量,但访问最慢,约为10~30个时钟周期范围。
多个缓存层级可以最大化地提高性能,同时尽可能地减少对主内存的片外访问。存取此主内存可能消耗数百个时钟周期。借由使用多级缓存,可以更快地从这些缓存中检索数据,而不必从速度较慢的主内存中存取,从而提高整体系统效率。
当涉及多个CPU核心时,相应地复杂度也会增加。以一个常见方案来看,该集群中包含四个CPU核心,标记为核心0到核心3,每个核心都有自己的专用L1缓存。在某些设计中,每个核心还将具有自己的专用L2缓存,而所有四个核心共享一个通用的L3缓存。而在其他设计中,核心0和核心1共享一个L2缓存,核心2和核心3共享另一个L2缓存,并且所有四个核心共同使用相同的L3缓存。这些不同的配置会影响跨不同缓存级储存和访问数据的方式。
通常,在单一集群中的所有处理器核心都是同质的,这意味着它们是相同类型。但是,拥有多个处理器核心集群的情况正变得越来越普遍。在许多情况下,不同集群中的核心是异质的,即是不同类型的。例如,使用Arm的big.LITTLE技术,“big”大核心旨在实现最大性能,但使用频率较低。
“LITTLE”小核心以较低性能要求而为电源效率进行了优化,并且大部分时间都在使用中。例如,在基于Arm的智能手机中,“big”大核心可能会被启动用于Zoom通话等相对较不频繁的任务。相比之下,“LITTLE”小核心可以处理更常见、较低要求的任务,如播放音乐和发送短信等。
在系统中,具有各自缓存的多个处理单元共享同一主内存,可能拥有多个共享数据的副本。例如,一个副本可能位于主内存中,而更多副本则位于每个处理器的本地缓存中。根据保持缓存一致性的要求,对于每个资料副本所做的任何更改,都反映在所有副本中。其实际作法是以新的数据更新所有副本或将其他副本标记为无效。
缓存一致性可以在软件控制下加以保持。但是,软件管理的一致性非常复杂,调试起来也非常困难。尽管如此,它仍然可以使用缓存清理等技术来实现,其中储存在缓存中的修改数据被标记为“脏”数据,这意味着它必须被写回主内存。可以对整个缓存或特定地址执行缓存清理,但它会占用大量的CPU周期,并且必须在保存数据副本的所有CPU上执行。
保持缓存一致性的首选方法是使用专用硬件,并透过软件隐蔽地管理缓存。例如,处理器集群中与核心相关联的缓存通常包括保持缓存一致性所需的硬件。
SoC由大量称为IP模块的功能块组成。处理器集群就是这样一种IP块。连接IP块的常用方法是使用NoC。
在许多SoC设计中,处理器集群之外不需要一致性,从而实现了非一致性或IO一致性的AXI5或AXI5-Lite NoC,例如Arm的NI系列或Arteris的FlexNoC。但是,对于具有多个处理器集群且缺乏固有缓存一致性的SoC设计,或者在集成需要缓存一致性的第三方IP或自定义加速器IP时,则需要一致性NoC。例如,使用AMBA CHI协议的Arm CMN或使用AMBA ACE和/或CHI协议的Arteris Ncore系列。
图2:采用一致性NoC的主系统,搭配采用非一致性NoC的安全岛示例。(来源:Arteris)
在整个芯片中普遍应用缓存一致性可能会耗费大量资源,而且对于特定组件来说也没有必要。因此,如图2所示,将缓存一致性隔离在芯片的一个子集,如CPU集群和特定加速器IP,可以更有效地利用资源并降低复杂性。一致性NoC (如Ncore)在需要严格同步的应用场景中表现出色。同时,非一致性互连(如FlexNoC)则适用于不需要严格同步的情况。
设计人员可以从策略上均衡特定领域对数据一致性的需求,同时在不需要严格一致性的情况下从更精简的通信渠道中获益。在当今复杂的异质SoC中,一致性互连和非一致性互连之间的协同作用已经成为一种策略优势,有助于提高系统的整体效率和适应性。
(原文刊登于EDN美国版,参考链接:SoC design: When a network-on-chip meets cache coherency,由Susan Hong编译)