片上嵌入式多处理器的一致性机制设计
扫描二维码
随时随地手机看文章
目前,大多数高端嵌入式SoC都属于异质芯片在单纯地提高时钟速度的方法退出主流之后,保持这种单线程的编程抽象,迫使通用的单处理器设计工程师采用双处理器或四处理器的一致性系统(coherent system)。具有丰富软件的高性能嵌入式系统也是如此,只是情况稍有不同。
这些SoC中的处理器通过非一致性(noncoherent)共享内存,以某种形式的消息传递进行通讯。在第三代蜂窝电话中,通过双端口SRAM和中断进行通讯的经典RISC/DSP组合,就是这些简单机制的一个很好例子。 未来的高性能SoC将是处理器的分层和异质系统,即在层次结构中嵌入由同质多处理器组成的一致性处理器集群。这种转变已经出现在一个特定的高性能嵌入式市场中,即以一致性网络多处理器实现的联网市场。
目前,对于未来嵌入式芯片多处理器(CMP)的准确特性仍存在争议。CMP是属于异质型,还是用同质处理器以分层方式实现的异质型还不明确。但对于许多CMP而言,使共享内存保持一致性至关重要。
定义和基本概念
对于一个带有缓存的多内核共享内存系统而言,如果由任何处理器发布的任何“载入”操作所返回的值总是在该内存位置最新“存储”的值,则认为该系统是缓存一致的。为了明确术语“最新存储 (latest Store) ”的定义,我们需要探讨一下内存模型。
借助于顺序一致性(SC)模型这个常用的内存模型进行阐述。在SC系统中,可以根据一个并行程序的任何一次执行的结果,对在一个位置完成的所有操作(主要是“载入”和“存储”)建立全局串行顺序。因此,“一致性”意味着:(1)每个处理器发出的“载入”和“存储”操作顺序,以同样的方式出现在该系统的全局串行顺序中,该处理器按照全局串行顺序把这些操作传给内存系统;(2)在该系统中,处理器每次所读取的操作所返回的值,就是在全局串行顺序中上次写入到该位置的值。
因此,术语“全局串行顺序”是由系统实现的内存一致性模型(简称内存模型)的结果,在非正式场合中以“强”和“弱”来定义。内存模型与单处理器的指令集架构(ISA)有关,ISA定义了编译器和硬件之间的操作约定。
ISA为多处理器系统(一般称为多线程系统)定义了程序员和内存系统之间的操作约定。因此,Java等多线程语言也明确给出了内存模型。在本文,大多数的“多处理”都可以用“多线程”代替。
顺序一致性(SC)、总体存储顺序(TSO)和处理器一致性(PC)是一些常用的机器级内存模型(从强到弱)。模型更强,意味着在并行内存系统的实现器中加入了更多约束,从而简化了由并行中间件或系统库写入器执行的任务。
但从单处理器的角度来看,SC却是内存一致性最弱的方式,因为它只提供合理的内存系统所必需的约束,而不再对内存操作进行限制。简言之,强的内存模型确保并行内存系统在“读出最新存储操作返回的值”的约束基础上,还提供其它约束,从而更有利于程序员编程。这些附加的约束通常可用于在线程或处理器之间形成高效的同步机制。
为实现一致性,系统必须具备几个基本特点。首先,在系统中的某一点处,向某个特定的内存位置写入信息的操作必须是串行化的。请注意,串行化是一个逻辑概念。对于一些探索性的高性能实现,串行化只是对于在提交(commit)阶段应如何返回事务给出了一个指导性方针,它类似于“无序”处理器,这种处理器保持一个临时状态和一个由提交点(commit point)分隔的“架构状态”。
一致性系统的另一个特点是“写入”传播,它表示“写入”操作需要最终传播到需要这个新值的所有代理程序(agent)。第三个重要特点是“写入”原子性,它是内存模型而不是一致性的结果,它表示在所有处理器被串行化后,需要将写入操作全部传播至系统中的所有处理器。
这里将只讨论一致性协议的常见分类方法。这种分类方式基于系统中缓存的稳定状态,常见的状态被称为“MOESI”,即修改、自有、互斥且干净、共享且干净,以及无效。这些术语的意义是自我解释的,详细解释很容易在教科书中找到。
基于状态的协议分类主要区分协议是基于“更新”还是基于“无效(invalidate)”。在基于“无效”的一致性协议中,系统中的一条缓存线仅有一个所有者,而在基于更新的系统中,所有缓存线的副本都是根据“写入”操作来更新的。串行化
许多较老的对称式多处理(SMP或非CMP)系统,以总线广播方式将事务广播给系统中所有的代理程序。因此,这些代理程序可以“窥探”它们的状态,然后采取适当的动作使数据项副本无效并对其进行更新。这种方式在一个事务的不同阶段之间的重叠是最小的,并被限制为有序串行化(管道化)。
由于受到带宽可扩展性、速度和总线可扩展性的限制,这些严格的监听总线机制逐渐演变成一些新的一致性机制。高端系统(仍与嵌入式CMP有关,尽管原因并不相同)常采用基于目录的机制。当已经存在低级别的多处理时,通常优先采纳监听“虚拟总线”机制。
监听虚拟总线串行化使用树型开关或层次环等专用的更高性能互连架构,特别是在事务的请求阶段。在这些系统中,互连负责建立全局串行顺序,同时从受限的、基于物理总线的互连转换到更高性能(如串行)的点到点信令链路。
另一方面,基于目录的机制在一个称为目录的新结构上完成串行化。这个目录通常驻留在内存模块中,用来存储系统中各种缓存行的状态。一般而言,这些系统与监听总线机制(虚拟或其它形式)相比,其在串行化和有序化方面对网络的依赖程度大大降低。由于目录机制不广播消息的数目,所以它们可用在非常大的系统中。
影响片上嵌入式多处理器一致性的另一个趋势是,为降低复杂性,带有多个处理器的下一代SoC将把通讯与计算分开。这种趋势已经促使了基于网络级芯片(NoC)的设计方法学的诞生,以及从电路交换NoC向分组交换NoC的转移。任何一种片上嵌入式多处理器的一致性机制都需要关注深亚微米SoC中的这个重要变化,并在分组交换网络底层上对一致性协议进行分层。
嵌入式SoC带来了成本、功耗、实时操作、知识产权(IP)所有权以及异质处理器等一系列问题,因此,选择嵌入式SoC的一致性机制与通用SoC有所不同。系统功耗低,系统成本就低,而系统成本是SoC的一个敏感因素。此外,如果SoC用于移动应用,低功耗要求的确是必需的。
正像缓存进入DSP领域需要一个过程一样(周期准确的处理器和系统仿真器是加快这个转变过程的关键工具),一致性设计也是如此。为将软件移植到实时系统中,一致性/SoC设计工程师必须确保有周期足够准确且快速的仿真器可用于应用程序/中间件端口。这个问题在高性能嵌入式SoC中更加严重,因为与通用多处理器相比,程序员需要更多地接触硬件。对于通用多处理器,仅是有限的“系统”(中间件、库和操作系统)程序员需要接触到这个接口。
IP所有权是嵌入式SoC的一个特点。大多数通用CMP供应商的设计,在内存级(与一致性相关的级别)未采用任何外部IP。但对嵌入式SoC的积分器来说,外部IP的使用非常普遍。甚至连许多高性能嵌入式SoC中的互连(如OCP-IP),也是外部IP供应商提供的一个IP模块。此外,高性能嵌入式SoC有时也会受益于以一致性方式共享相同内存的异质ISA内核,例如一个RISC内核和一个DSP。
从这些趋势来看,监听虚拟总线一致性机制与CMP的相关性是显而易见的:有限的可扩展性、大量的片上带宽、点到点信令、更低开销和更低延迟。但有趣的是,通常认为仅适用于大型服务器级机器的目录机制,经过适当修改后也适用于嵌入式SoC,这是因为目录机制可以与无序互连、异质ISA、低功率单播事务等协同工作。
第一代嵌入式CMP或许只能采用监听虚拟总线机制,但预计混合型监听目录机制可能成为实现嵌入式一致性的新趋势,这是因为设计工程师将开始意识到目录机制的模块化所带来的好处。
死锁/活锁
除了选择串行化方法和一致性协议的类型之外,在给定的有限资源/缓存情况下,缓存一致性协议设计工程师必须保证该协议是无死锁和无活锁的。对于基于互连的分组交换型一致性协议,这点尤其重要。
这里存在两类死锁,即互连死锁和协议死锁。这两种死锁通常都是由于分组交换互连中的缓冲区限制引起的。在设计一致性协议时,应该仔细考虑协议死锁(图3a)。防止死锁的常用机制包括:将事务的请求路径与回复/响应路径分开(图3b);保证在任何状态下缓存或内存代理程序都对请求给出响应。
如图3b所示,设计工程师通常使用虚拟通道来完成上述第一个机制。在任何虚拟通道中流动的事务都遵循先进先出(FIFO)顺序,而且信息流中的阻塞事件可引起一个能一直追溯到阻塞根源的背压(backpressure)流控。因此,只要(事务)接收器(sink)在向前移动(forward progress),系统就不会阻塞。[!--empirenews.page--]
如果在向前移动的过程中出现停顿,分布式系统将出现活锁现象。在处理器上,这将在没有向前发展的“载入/存储”的程序计数器中得到反映。当多个缓存试图获得缓存线的所有权失败时,这种情况常常发生。如果在该系统中适当地建立一个全局串行顺序,则每个代理程序就可以按照这个顺序来处理请求。必须按照公平方式来建立全局串行顺序,并且公平地将各种资源(端口、总线、缓冲器)分配给多线程/多处理器。
另一个与防止活锁有关的问题是流量控制。系统的流量控制将限制资源的分配。以ad-hoc方式实现的流量控制可能导致活锁,而常见的一种情况就是在响应请求的同时,过度地使用重试或否定应答(NACK)。
其它设计考虑
除了死锁和活锁之外,设计工程师还应该考虑以下的问题:
缓存层次和DMA:当事务穿过缓存层次时将产生死锁问题。通常,我们可以采纳在更广泛的协议中使用的相同机制,以便在单独的(虚拟或真实)通道/FIFO中保留请求和回复。
另一个问题是确定增强一致性的缓存级别(L1缓存、L2缓存或L3缓存),以及I/O应在哪个位置上从一致性域进入和提取缓存线。通常情况下,包含(inclusion)问题的相关解决机在很大程度上依赖于具体的应用或系统。通过在一致性系统的事务集合包含线索(hint),可一致性系统中使用线索来进行预取和数据放置。一个显而易见的例子就是路由。在路由系统中,需要把外来IP包的头文件与一个表进行匹配,以该IP包的目标缓冲器/接口。通过利用线索对事务进行分类(如读出/写入、命中/不命中策略),可以将这些头文件放在靠近较低缓存级别的位置。
同步和屏障(barrier)操作:许多ISA提供各种必须映射到一致性系统的原子语义(atomic primitive)。较弱的内存系统要求一种被称为屏障的安全网落,它可以在发送敏感代码序列期间,强迫发生某种行为(通常在处理器或线程发出的“存储”和“载入”操作之间)。这种屏障一般通过插入ISA支持的专用屏障指令来实现。一致性系统可能需要通过动态地停滞某些事务来对这些操作作出响应,以支持这些行为。