← 返回信息流
AI 资讯Hacker News·4 天前

NUMA架构:核心、内存与它们之间的距离

原标题:NUMA: Cores, memory, and the distance between them

速览

NUMA(非统一内存访问)架构是现代多处理器系统的核心设计,旨在解决多核环境下内存访问延迟不均的问题。该架构通过区分本地内存和远程内存,优化数据局部性以提升整体计算效率。理解核心、内存及它们之间的物理距离,对于优化高性能计算和AI训练任务至关重要。

AI 深度解读

NUMA:核心、内存以及它们之间的距离

背景

在现代高性能计算环境中,一个令人困惑的现象时常发生:在同一台宿主机上配置完全相同、运行相同工作负载的两个虚拟机,其中一个 consistently(持续地)比另一个慢 20%。既没有工作负载本身的缺陷,也没有宿主机的故障,更不存在来自其他租户的资源争用。罪魁祸首仅仅是因为运行该虚拟机的 CPU 与其内存位于互连(interconnect)的“错误”一侧,而 guest 内部没有任何参数可以修正这一问题。

这就是 Edera 公司近期发布的一系列变更所致力于解决的问题。他们推出了一套端到端感知 NUMA 的虚拟化栈,涵盖 guest 内部、半虚拟化 I/O 驱动、dom0 以及 Hypervisor 对主机硬件的视图。其中部分实现据称是全球首创。要理解这一切的重要性,我们必须从 NUMA(非统一内存访问)的本质讲起。

核心内容

从 UMA 到多插槽服务器的演变

NUMA 的全称是 Non-Uniform Memory Access(非统一内存访问)。其定义性特征正如名称所示:在 NUMA 机器上,内存访问成本并非均匀的。哪个 CPU 执行访问、数据存储在哪个物理内存 bank 中,以及这两者之间的关系,共同决定了访问成本。

NUMA 的历史对立面是 UMA(Uniform Memory Access,统一内存访问)。在 UMA 架构中,每个 CPU 通过同一个内存控制器以相同的成本访问内存的任何字节。UMA 是单插槽商用服务器和许多嵌入式系统的领域。它在概念上简单,但扩展性有限——极限大致是“你能在一个硅片上、通过一组内存通道容纳多少核心”。

当需要突破这一极限时会发生什么?UMA 的扩展直到停止,而“停止”有几个交织的原因:

  1. 电气迹线长度增加:信号端到端传播的时间变长。在现代内存总线运行的高数据速率下,较长的迹线迫使降低总线频率以保持信号完整性,从而在延迟上叠加延迟。(这与 L1/L2/L3 缓存层级的物理原理相同:L1 缓存较小,部分原因是因为保持缓存小而物理上靠近核心是保持其高速的关键。)
  2. 内存控制器瓶颈:单个内存控制器无法以全带宽供应任意数量的核心;封装上的引脚数量对连接到单个插槽的内存通道数量设置了硬性上限。
  3. 总线争用:当许多 CPU 同时尝试读取内存时,总线争用不再可以忽略。

行业的解决方案是赋予每个插槽(或芯片)自己的内存控制器,并停止将内存视为一个对称池。机器变成了 NUMA。每个节点拥有自己的 CPU 和自己的内存切片;CPU 仍然可以读取任何节点的数据,但访问远程节点必须穿过互连。虽然互连在绝对意义上很快,但相对于本地 DRAM 访问而言则较慢。

可以将互连想象为连接两个相邻城镇的桥梁。在道路空闲时,过桥速度仅略慢于本地交通;但在高峰时段,当每个人都试图同时使用同一座桥时,成本取决于队列的长度。我们将在讨论繁忙的生产工作负载与安静的微基准测试之间的区别时回到这一区别。

简短的时间线:

  • 1990年代:商业 NUMA 出现在面向少数需要比单总线更多核心的大型机系统中,如 SGI 的 Origin 系列、Sequent NUMA-Q 和 Compaq 的 AlphaServer GS 系列,均使用专有的节点间网络。
  • 2003年:NUMA 随 AMD Opteron 进入商用 x86 领域,每个插槽拥有自己的内存控制器,并通过 HyperTransport 连接插槽。
  • 2008年:Intel 通过 Nehalem 和 QuickPath Interconnect (QPI) 迎头赶上,此前 Intel 长期依赖真正 UMA 的前端总线芯片组。
  • 现在:Intel 使用 Ultra Path Interconnect (UPI,QPI 的后继者);AMD 使用 Infinity Fabric(HyperTransport 的后继者)。每一代都大幅提高了绝对带宽,但远程与本地 DRAM 访问成本的比率仍顽固地保持在大致相同的范围内。

“一个插槽即一个节点”模型的终结

你可能会倾向于认为每个插槽就是一个 NUMA 节点。在 Opteron 之后的十年里,这是正确的。操作员将 NUMA 理解为“拓扑镜像插槽”,因为当时每个插槽的核心数量较少,单个内存控制器可以轻松供应整个插槽。

这一情况在 2010 年代末发生了变化:

  • AMD EPYC:基于 Zen 架构的 EPYC 将每插槽核心数量推高,使得制造单一巨大单片芯片的权衡变得不具吸引力。封装转向由几个芯片(chiplets)组成的小星座:一个插槽内有多个核心复杂度 Die (CCD),每个 CCD 拥有自己的 L3 缓存切片和内存控制器切片,由 Infinity Fabric 粘合。关键在于,Infinity Fabric 现在不仅用于插槽之间,也用于插槽内 CCD 之间。因此,单个 EPYC 插槽可以向操作系统呈现多个 NUMA 节点,具体取决于部件和 BIOS 配置(即“每插槽节点数” NPS 旋钮,当前代支持 NPS1 到 NPS4)。
  • Intel Xeon:类似的概念是子 NUMA 聚类 (Sub-NUMA Clustering, SNC)。在最近的 Xeon 部件的 BIOS 中默认关闭但可用,SNC 将片上内存控制器网格分区,并将结果呈现为每个插槽的多个 NUMA 节点。

“一个插槽,一个节点”曾是一个有用的初步近似,但在几年前就不再适用于商用硬件。除了专业利基市场外,超过两个插槽的 x86 服务器已变得罕见;现代系统上有趣的 NUMA 复杂性来自于单个双插槽机箱内部,其中四到八个节点现在已属常规。

“慢”的程度有多大?

精确的数字因平台而异,人们对精确的方法论也有争议,但一个有用的经验法则是:在现代服务器上,远程 DRAM 访问的成本大约是本地访问的 1.5 倍到 3 倍。带宽也较低,有时比例相似。这些数字是在空闲机器上进行微基准测试时测量得出的。

在实际工作负载中,差距通常更糟糕,因为互连是共享的。如果许多核心同时执行跨节点访问,它们会争用相同的互连带宽,导致每次请求的延迟上升。这是许多“为什么服务器在高负载下变慢”谜团的机制。微基准测试显示跨节点访问差 2 倍,而生产工作负载可能看到 4 倍或 5 倍的差距,因为每个人都在争夺同一根管道。

由此产生的推论值得注意:NUMA 效应不仅会使受影响的工作负载变慢,还会使其性能变得不可预测。同一个请求可能耗时 80 纳秒或 250 纳秒,取决于互连上此刻还有什么其他活动。平均延迟是一个有用的数字,但尾部延迟(tail latency)通常是 NUMA 痛苦首次出现的地方。

交织(Interleaving):牺牲峰值以换取底线

有一种众所周知的方法可以在不费力理解内存应该位于何处的情况下平坦化成本曲线:内存交织(memory interleaving)。无论请求任务位于哪个节点,都轮询方式在所有节点上分配页面。在 Linux 上,这通过 numactl --interleave=all 实现;一些数据库和 JVM 在其自己的分配器中做类似的事情;少数 Hypervisor 在缺乏更智能的回退方案时,隐式地对 guest 内存执行此操作。

BIOS 级别也存在相同概念的版本。大多数双插槽服务器固件都有一个“节点交织”或“跨节点内存交织”开关,它以缓存行或页面粒度将物理内存分布在插槽之间。开启后,操作系统会将内存视为一个巨大的 UMA 池,而不是 NUMA 拓扑,从而忽略 NUMA 感知代码可能带来的优化优势,换取配置的简单性和一致性。

关键要点

  • NUMA 的本质:内存访问成本取决于 CPU 与内存物理位置的相对关系。远程访问比本地访问慢,且成本不固定。
  • 架构演进:从 UMA(单控制器、单总线)到 NUMA(每插槽/每芯片独立控制器、互连通信),是为了解决电气延迟、带宽瓶颈和总线争用问题。
  • 拓扑复杂性增加:现代 CPU(AMD Zen EPYC 和 Intel Xeon SNC)使得单个插槽内部包含多个
查看原文 →edera.dev