单芯片的一致多处理
随着SoC设计元件的出现,如MIPS32 1004K一致处理系统(CPS),单操作系统条件下的片上对称多处理(SMP)已经成为了一种真正的设计选择,而系统架构师也需要了解其优点和局限性。
任务越多,越需要并行
复杂的模块化多任务处理嵌入式软件系统经常表现出“偶然发现的”并发,如图1所示。该系统的总任务可能包括多任务操作,每个操作都有不同的职责,可满足一系列不同的输入需求。如果没有分时操作系统,这些任务中的每个都必须在独立的处理器上运行。在一个分时单处理器(uniprocessor)上,任务可以在交替的时间片段上运行。在一个采用SMP操作系统的多处理器上,任务可以并行地在许多可供使用的处理器上运行。
图1 并行的多任务处理
分布式处理
另一种形式的并行处理已经成为司空见惯的事情,以至于有时甚至不被认为是“并行”的,这就是分布式计算,它的网络客户机/服务器模型是迄今为止最常见的范例。客户机/服务器编程基本上是一种控制流分解的形式。一个程序任务将工作请求连接和发送给系统中的一个或多个专门任务,该系统被指定执行具体的工作,而不是由这个程序任务本身执行所有计算。客户机/服务器编程通常是在LAN和WAN上实现的,SMP SoC内的任务之间的通信也是遵循同一个范例。人们可以利用片上或无效“环回”网络接口通过TCP/IP进行未经修改的客户机/服务器的二进制通信,或者更加有效地利用在存储器中传递数据缓存的本地通信协议。
实际上,此类技术都可以单独使用,或者结合使用,以利用给定应用的基于SMP平台的能力。人们甚至可以构建一种分布式SMP服务器的数据并行阵列,其中每个阵列都可以执行一条控制流的流水线。但是,为了有效地实现这个方案,可能需要非常大的工作量和数据集。
系统软件的支持非常关键
在有些SoC系统中,有可能实现处理器静态物理分解任务的并行性(例如每个输入端口有一个处理器内核),在这样的SoC系统中,把并行的多个任务分配到不同的处理器去处理可以在硬件中完成。这将降低软件开销和占位面积,但是不能提供灵活性。
同样,如果嵌入式应用可以被静态地分解成客户端和服务器端程序,这些程序通过片上互连进行通信,那末系统连接所需的唯一的系统软件就是执行处理器间共用协议的信息传递代码。信息传递协议可提供某些抽象层,可以用来配置更多或更少的处理器来运行共用基础的应用代码,但是对于任何给定的配置,处理器间的负载平衡就像硬件分区一样无声无息。为了实现更加灵活的并行系统编程,需要在一个共享资源的多处理器系统上完成软件分布的任务。
SMP系统的灵活性和适应性
顾名思义,SMP操作系统有一个对系统“对称”的含义。所有处理器都可以发现相同的存储器、相同的I/O器件以及相同的全局操作系统的状态。这将使从一个处理器到另一个处理器的程序移植变得极其简单而有效,如图2所示的简单例子,也将使负载均衡更加容易。无须额外的编程或系统管理,一套采用时间分割的单个CPU上的多任务程序,将同时运行于一个SMP系统的可用CPU之上。如Linux调度程序的SMP调度程序将打开和关闭处理器的程序,一切都以一种公平的方式进行。
作为多处理运行的Linux应用不必为了发挥SMP的并行性而进行修改。在大多数情况下,无须重新进行编译;一个例外则是与非线程安全库静态连接的二进制码。
SMP Linux环境可以提供许多工具,有助于系统设计人员调节可用处理器的任务共享方式。这些任务可以让它们的优先级上升和下降,可以由运行在处理器上的任意子集加以限制。利用适当核的支持,它们可以请求使用不同的实时调度状态。
类UNIX操作系统总是允许应用程序对任务的相对调度优先级进行控制,即使是单处理器分时系统也是这样。随着能够对任务、任务组或系统具体用户的优先级进行操作的更复杂机制的出现,传统上优良的外壳命令(shell command)和系统调用已经增加到Linux当中,这对评判该操作系统的优劣应该是十分必要的。
此外,在多处理器配置方面,所有的Linux任务都有一个参数,定义了哪些处理器组(set of processor)可以对任务进行调度。根据默认,这个参数存在于系统中的整组处理器当中,但是,像优先级一样,这种CPU亲合力可以由taskset外壳命令,或者由显式(explicit system)调用来操作任务的“CPU亲合力”。
图2 多处理器资源上的SMP任务分布
实现SMP
一个SMP系统范例要求所有处理器在同一个地址看到所有的存储器。对于简单而低性能的处理器,这不是太难完成的事情。人们只要在一个共用存储器和I/O总线上放置所有处理器的指令提取和装载/存储流量就可以了。随着总线很快成为了一个性能瓶颈,这个非常简单的模型利用增加的处理器迅速而漂亮地解决了这个问题。甚至在单处理器系统中,高性能的嵌入式内核指令和数据的带宽需求要求在主存储器及处理器之间使用高速缓存。
采用独立每个处理器高速缓存的系统不再只是一个自然而然的SMP。当一个处理器的高速缓存包含了存储器中某一位置的最近保持值(most recent value)的唯一备份时,就会出现一种基本而危险的不对称。系统必须增加高速缓存一致协议以恢复这种对称性。在一个非常简单的系统中,所有处理器都连接到一条共用总线,它足以使所有高速缓存控制器监控总线,以发现哪个高速缓存拥有给定存储器位置的最新版本。在更先进的系统中,如MIPS32 1004K CPS,处理器与存储器的连接是采用点对点方式连接一个交换结构,而不是连接到一条总线。因此,高速缓存一致性需要更加复杂的支持。1004K一致管理器在存储器处理上加入了一个全局顺序(global order),并生成必要的干预信号,以保持多个1004K处理器内核的高速缓存的一致性。
因此,1004K处理器可以看到一个对称的存储器。像Linux的SMP操作系统可以自由地迁移任务并动态地平衡处理器负载。
在一个嵌入式SoC中,整个计算的大部分时间可能花在中断服务方面。这意味着需要控制良好的负载均衡和性能调节,这不仅有助于控制程序任务的运行地点,而且还可以控制执行中断服务的地点。Linux操作系统有一个“IRQ亲合力”控制界面,这个界面允许用户和程序指定哪个处理器用来服务一个给定的中断。为了便于使用,这个界面需要底层的系统硬件提供一种方法将中断有选择地发送给处理器。1004K全局中断控制器为1004K CPS提供了这种能力。
高速缓存一致基础架构非常有用,不仅是在对称多处理的处理器之间,而且在处理器和I/O DMA通道之间也是如此。虽然如MIPS32的RISC架构有支持基于软件的I/O一致的特性,但还是需要CPU在每个I/O DMA操作之前或之后对DMA缓冲器进行处理。该处理功能对I/O密集应用的性能有着显著的影响。在1004K CPS中,通过一个I/O一致单元将I/O DMA连接到存储器,有助于DMA流量的条理化和与一致装载/存储流的整合,从而消除了软件开销。
采用管道,得到回报
由于1004K处理器VPE对于软件来说看起来像成熟的处理器,大到有独立的中断输入,所以,管理多个内核的同一个SMP操作系统逻辑可以用来管理其构成VPE。在最高水平的系统管理方面,全部VPE功能都在运行的双核1004K系统是一个4路SMP系统的样子。为了利用SMP而编写或配置的软件能够自然而然地利用多线程,反之亦然。
虽然系统资源的想法仍然是对称的,但事实上,双线程争用一条处理器流水线将比双线程运行于独立的内核实现的性能更低。这种情况在服务器系统中已经存在了许多年,其多线程CPU的一致集群十分常见,而1004K的SMP Linux核的配备可以实现必要的负载平衡的优化。如果要优化功耗,调度程序可以每次在一个内核的虚拟处理器上加载运行(load work),从而使其他内核能够停留在一种低功耗状态。
如果是为了优化性能,可以首先在不同的内核上展开运行(spread work),一旦所有内核都有一个要运行的动态任务,只需在每个内核上加载多个VPE就可以了。
结语
片上多处理可以多种方式进行开发,从而实现高性能的SoC。通过输入数据或处理功能,可以实现非常高效的工作静态分解,但这也是非常不灵活的。SMP平台和软件可以提供一个非常灵活的高性能计算平台,以实现比单处理器更加显著的加速,通常这需要很少的甚至不需任何应用代码的修改。多线程是对SMP并行性的最好补充,可以最大限度地利用每个处理器中的流水线资源。MIPS32 1004K一致处理系统在一个单IP块中整合了MIPS多线程和一致SMP,以提供可扩展、高密度的嵌入式计算能力。
评论