那么两者之间的主要区别是什么呢? 总结下来有这么几点,
SMP和AMP的深入介绍很多经典文章书籍可参考,此处不再赘述。现今主流的x86多处理器服务器都是SMP架构的, 而很多嵌入式系统则是AMP架构的。
NUMA(Non-Uniform Memory Access)非均匀内存访问架构是指多处理器系统中,内存的访问时间是依赖于处理器和内存之间的相对位置的。 这种设计里存在和处理器相对近的内存,通常被称作本地内存;还有和处理器相对远的内存, 通常被称为非本地内存。
UMA(Uniform Memory Access)均匀内存访问架构则是与NUMA相反,所以处理器对共享内存的访问距离和时间是相同的。
由此可知,不论是NUMA还是UMA都是SMP架构的一种设计和实现上的选择。
阅读文档时,也常常能看到ccNUMA(Cache Coherent NUMA),即缓存一致性NUMA架构。 这种架构主要是在NUMA架构之上保证了多处理器之间的缓存一致性。降低了系统程序的编写难度。
x86多处理器发展历史上,早期的多核和多处理器系统都是UMA架构的。这种架构下, 多个CPU通过同一个北桥(North Bridge)芯片与内存链接。北桥芯片里集成了内存控制器(Memory Controller)。
下图是一个典型的早期 x86 UMA 系统,四路处理器通过 FSB (前端系统总线, Front Side Bus) 和主板上的内存控制器芯片 (MCH, Memory Controller Hub) 相连,DRAM 是以 UMA 方式组织的,延迟并无访问差异。
图:x86 UMA
注:PCH(Platform Controller Hub),Intel 于 2008 年起退出的一系列晶片组,用于取代以往的 I/O Controller Hub(ICH)
在 UMA 架构下,CPU 和内存控制器之间的前端总线 (FSB) 在系统 CPU 数量不断增加的前提下, 成为了系统性能的瓶颈。因此,AMD 在引入 64 位 x86 架构时,实现了 NUMA 架构。之后, Intel 也推出了 x64 的 Nehalem 架构,x86 终于全面进入到 NUMA 时代。x86 NUMA 目前的实现属于 ccNUMA。
从 Nehalem 架构开始,x86 开始转向 NUMA 架构,内存控制器芯片被集成到处理器内部,多个处理器通过 QPI 链路相连,从此 DRAM 有了远近之分。 而 Sandybridge 架构则更近一步,将片外的 IOH 芯片也集成到了处理器内部,至此,内存控制器和 PCIe Root Complex 全部在处理器内部了。 下图就是一个典型的 x86 的 NUMA 架构:
图:x86 典型NUMA架构
图:Intel处理器微架构路线
一个NUMA Node内部是由一个物理CPU和它所有的本地内存(Local Memory) 组成的。广义得讲, 一个NUMA Node内部还包含本地IO资源,对大多数Intel x86 NUMA平台来说,主要是PCIe总线资源。 ACPI规范就是这么抽象一个NUMA Node的。
一个CPU Socket里可以由多个CPU Core和一个Uncore部分组成。每个CPU Core内部又可以由两个CPU Thread组成。 每个CPU thread都是一个操作系统可见的逻辑CPU。对大多数操作系统来说,一个八核HT打开的CPU会被识别为16个CPU。 下面就说一说这里面相关的概念
在Intel x86平台上,所谓本地内存,就是CPU可以经过Uncore部件里的iMC访问到的内存。而那些非本地的, 远程内存(Remote Memory),则需要经过QPI的链路到该内存所在的本地CPU的iMC来访问。 曾经在Intel IvyBridge的NUMA平台上做的内存访问性能测试显示,远程内存访问的延时时本地内存的一倍。
可以假设,操作系统应该尽量利用本地内存的低访问延迟特性来优化应用和系统的性能。
如前所述,Intel自从SandyBridge处理器开始,已经把PCIe Root Complex集成到CPU里了。 正因为如此,从CPU直接引出PCIe Root Port的PCIe 3.0的链路可以直接与PCIe Switch或者PCIe Endpoint相连。 一个PCIe Endpoint就是一个PCIe外设。这就意味着,对某个PCIe外设来说,如果它直接于哪个CPU相连, 它就属于哪个CPU所在的NUMA Node。
与本地内存一样,所谓本地IO资源,就是CPU可以经过Uncore部件里的PCIe Root Complex直接访问到的IO资源。 如果是非本地IO资源,则需要经过QPI链路到该IO资源所属的CPU,再通过该CPU PCIe Root Complex访问。 如果同一个NUMA Node内的CPU和内存和另外一个NUMA Node的IO资源发生互操作,因为要跨越QPI链路, 会存在额外的访问延迟问题。
其它体系结构里,为降低外设访问延迟,也有将IB(Infiniband)总线集成到CPU里的。 这样IB设备也属于NUMA Node的一部分了。
可以假设,操作系统如果是NUMA Aware的话,应该会尽量针对本地IO资源低延迟的优点进行优化。
图:PCLe Root Complex Location
在Intel x86上,NUMA Node之间的互联是通过 QPI(QuickPath Interconnect) Link的。 CPU的Uncore部分有QPI的控制器来控制CPU到QPI的数据访问。
下图就是一个利用 QPI Switch 互联的 8 NUMA Node 的 x86 系统
NUMA Affinity(亲和性)是和NUMA Hierarchy(层级结构)直接相关的。对系统软件来说, 以下两个概念至关重要,
CPU NUMA的亲和性是指从CPU角度看,哪些内存访问更快,有更低的延迟。如前所述, 和该CPU直接相连的本地内存是更快的。操作系统如果可以根据任务所在CPU去分配本地内存, 就是基于CPU NUMA亲和性的考虑。因此,CPU NUMA亲和性就是要尽量让任务运行在本地的NUMA Node里。
设备NUMA亲和性是指从PCIe外设的角度看,如果和CPU和内存相关的IO活动都发生在外设所属的NUMA Node, 将会有更低延迟。这里有两种设备NUMA亲和性的问题,
1)DMA Buffer NUMA Affinity
大部分PCIe设备支持DMA功能的。也就是说,设备可以直接把数据写入到位于内存中的DMA缓冲区。 显然,如果DMA缓冲区在PCIe外设所属的NUMA Node里分配,那么将会有最低的延迟。 否则,外设的DMA操作要跨越QPI链接去读写另外一个NUMA Node里的DMA缓冲区。 因此,操作系统如果可以根据PCIe设备所属的NUMA node分配DMA缓冲区, 将会有最好的DMA操作的性能。
2)Interrupt NUMA Affinity
设备DMA操作完成后,需要在CPU上触发中断来通知驱动程序的中断处理例程(ISR)来读写DMA缓冲区。 很多时候,ISR触发下半部机制(SoftIRQ)来进入到协议栈相关(Network,Storage)的代码路径来传送数据。 对大部分操作系统来说,硬件中断(HardIRQ)和下半部机制的代码在同一个CPU上发生。 因此,DMA缓冲区的读写操作发生的位置和设备硬件中断(HardIRQ)密切相关。假设操作系统可以把设备的硬件中断绑定到自己所属的NUMA node, 那之后中断处理函数和协议栈代码对DMA缓冲区的读写将会有更低的延迟。
由于NUMA的亲和性对应用的性能非常重要,那么硬件平台就需要给操作系统提供接口机制来感知硬件的NUMA层级结构。 在x86平台,ACPI规范提供了以下接口来让操作系统来检测系统的NUMA层级结构。
ACPI 5.0a规范的第17章是有关NUMA的章节。ACPI规范里,NUMA Node被第9章定义的Module Device所描述。 ACPI规范里用Proximity Domain对NUMA Node做了抽象,两者的概念大多时候等同。
1、SRAT(System Resource Affinity Table)
主要描述了系统boot时的CPU和内存都属于哪个Proximity Domain(NUMA Node)。 这个表格里的信息时静态的,如果是启动后热插拔,需要用OSPM的_PXM方法去获得相关信息。
2、SLIT(System Locality Information Table)
提供CPU和内存之间的位置远近信息。在SRAT表格里,只能告诉给定的CPU和内存是否在一个NUMA Node。 对某个CPU来说,不在本NUMA Node里的内存,即远程内存们是否都是一样的访问延迟取决于NUMA的拓扑有多复杂(QPI的跳数)。 总之,对于不能简单用远近来描述的NUMA系统(QPI存在0,1,2等不同跳数), 需要SLIT表格给出进一步的说明。同样的,这个表格也是静态表格,热插拔需要使用OSPM的_SLI方法。
3、DSDT(Differentiated System Description Table)
从Device NUMA角度看,这个表格给出了系统boot时的外设都属于哪个Proximity Domain(NUMA Node)。
ACPI规范OSPM(Operating System-directed configuration and Power Management) 和OSPM各种方法就是操作系统里的ACPI驱动和ACPI firmware之间的一个互动的接口。 x86启动OS后,没有ACPI之前,firmware(BIOS)的代码是无法被执行了,除非通过SMI中断处理程序。 但有了ACPI,BIOS提前把ACPI的一些静态表格和AML的bytecode代码装载到内存, 然后ACPI驱动就会加载AML的解释器,这样OS就可以通过ACPI驱动调用预先装载的AML代码。 AML(ACPI Machine Language)是和Java类似的一种虚拟机解释型语言,所以不同操作系统的ACPI驱动, 只要有相同的虚拟机解释器,就可以直接从操作系统调用ACPI写好的AML的代码了。 所以,前文所述的所有热插拔的OSPM方法,其实就是对应ACPI firmware的AML的一段函数代码而已。 (关于ACPI的简单介绍,这里给出两篇延伸阅读:1和2。)
原文链接:https://houmin.cc/posts/b893097a/