1. NUMA 架构概述

1.1 什么是 NUMA

NUMA(Non-Uniform Memory Access,非统一内存访问) 是一种为多处理器系统设计的内存架构。在 NUMA 系统中,每个处理器核心(或一组核心)被分配到一个称为 NUMA 节点 的本地域中,每个节点拥有自己的本地内存控制器和物理内存。

核心特性:处理器访问 本地内存(属于同一 NUMA 节点的内存)的速度远快于访问 远程内存(属于其他 NUMA 节点的内存)。这种访问延迟的不对称性,是 NUMA 架构性能优化的根本出发点。

关键洞察: NUMA 的“非统一”特指内存访问延迟的不统一。现代服务器 CPU 通常集成了内存控制器,因此每个物理 CPU 插槽天然就是一个 NUMA 节点。

1.2 UMA 与 NUMA 对比

UMA(Uniform Memory Access,统一内存访问) 是 NUMA 之前的传统对称多处理(SMP)架构。所有处理器通过共享总线访问同一块物理内存,访问延迟对所有处理器都是相同的。

对比维度 UMA(对称多处理 SMP) NUMA(非统一内存访问)
内存访问延迟 统一,所有 CPU 访问内存延迟相同 非统一,本地快、远程慢
内存控制器位置 位于北桥芯片,所有 CPU 共享 集成在 CPU 内部,每个节点独立
系统总线 共享前端总线(FSB),易成瓶颈 点对点互联(如 QPI/UPI),带宽可扩展
可扩展性 差,通常 ≤ 8 个 CPU 优秀,可支持数百个 CPU 核心
编程模型 简单,无需感知内存拓扑 复杂,需考虑数据本地性(Locality)
典型应用 桌面 PC、低端服务器 高端服务器、数据中心、HPC
性能代价: 在 NUMA 系统中,远程内存访问的延迟通常是本地访问的 1.5 到 3 倍,带宽也可能下降 30%~50%。如果 Linux 内核调度器将进程调度到远离其内存所在节点的 CPU 上,将导致显著的性能损失。
UMA 架构 vs NUMA 架构 UMA(统一内存访问) CPU 0 CPU 1 CPU 2 CPU 3 共享前端总线(FSB) 物理内存 延迟:统一(相等) NUMA(非统一内存访问) NUMA Node 0 CPU CPU 本地内存 NUMA Node 1 CPU CPU 本地内存 QPI/UPI 远程访问延迟 > 本地访问延迟(非统一)

1.3 NUMA 的拓扑结构

NUMA 系统的拓扑结构描述了 CPU 核心、缓存、内存控制器以及节点间互联的物理布局。理解拓扑是进行内核调度优化的前提。

1.3.1 物理拓扑层次

  • Socket(物理插槽): 一个物理 CPU 芯片,通常对应一个 NUMA 节点。
  • Core(核心): Socket 内的独立计算单元,拥有私有 L1/L2 缓存。
  • Thread(线程/超线程): 一个核心内的逻辑处理器,共享核心的 L1/L2 缓存。
  • NUMA Node(NUMA 节点): 由一个或多个 Socket(或 Socket 内的内存控制器)及其直接连接的本地内存组成。
  • 互联网络: 连接不同 NUMA 节点的点对点链路,如 Intel 的 QPI(QuickPath Interconnect)或 UPI(Ultra Path Interconnect),AMD 的 Infinity Fabric。

1.3.2 典型 2-Socket NUMA 拓扑

以下是一个双路服务器的典型 NUMA 拓扑结构,展示了两个 NUMA 节点通过互联链路通信的布局。

典型 2-Socket NUMA 拓扑结构 Socket 0 (NUMA Node 0) Core 0 L1/L2 Cache Core 1 L1/L2 Cache L3 Cache(共享) 内存控制器 本地内存 Socket 1 (NUMA Node 1) Core 2 L1/L2 Cache Core 3 L1/L2 Cache L3 Cache(共享) 内存控制器 本地内存 QPI/UPI 点对点互联 远程内存访问路径(跨 QPI)

1.4 NUMA 节点与内存域

在 Linux 内核中,NUMA 拓扑被抽象为 节点(Node) 和 内存域(Zone) 两个核心概念,它们是内存管理子系统的基础数据结构。

1.4.1 NUMA 节点(pglist_data)

每个 NUMA 节点在内核中由一个 struct pglist_data 结构体表示,通常简称为 pg_data_t。该结构体包含了该节点上所有物理内存的管理信息。

// 内核源码: include/linux/mmzone.h
typedef struct pglist_data {
    // 节点编号
    int node_id;
    // 该节点包含的内存域数组
    struct zone node_zones[MAX_NR_ZONES];
    // 备用节点列表(用于跨节点内存分配)
    struct zonelist node_zonelists[MAX_ZONELISTS];
    // 节点上物理页框数量
    unsigned long node_start_pfn;
    unsigned long node_present_pages;
    unsigned long node_spanned_pages;
    // 等待队列、页面回收等管理字段
    wait_queue_head_t kswapd_wait;
    // ...
} pg_data_t;

1.4.2 内存域(Zone)

每个 NUMA 节点内的物理内存根据地址范围和用途被划分为多个 内存域(Zone)。Linux 内核定义了以下几种标准内存域:

内存域 宏定义 描述 典型范围
DMA ZONE_DMA 用于 ISA/DMA 设备的低端物理内存 0 - 16 MB
DMA32 ZONE_DMA32 用于 32 位设备 DMA 的内存(x86_64) 0 - 4 GB
Normal ZONE_NORMAL 常规内存,内核和用户态直接映射 16 MB - 896 MB(32位)
HighMem ZONE_HIGHMEM 高端内存,仅 32 位系统使用 > 896 MB(32位)
Movable ZONE_MOVABLE 可迁移页面,用于内存规整和热插拔 动态范围
注意: 在 64 位系统(如 x86_64)上,由于虚拟地址空间足够大,ZONE_HIGHMEM 不再使用。所有物理内存都可以被直接映射,因此 ZONE_NORMAL 是主要的内存域。

1.4.3 节点与内存域的关系

每个 NUMA 节点包含一组完整的内存域。内核在进行内存分配时,首先尝试从当前 CPU 所在节点的本地内存域分配;如果本地内存不足,则根据 备用节点列表(zonelist) 的优先级顺序,依次尝试其他节点的内存域。

NUMA 节点与内存域层次结构 系统(System) NUMA Node 0 (pglist_data) NUMA Node 1 (pglist_data) ZONE_DMA ZONE_DMA32 ZONE_NORMAL ZONE_DMA ZONE_DMA32 ZONE_NORMAL 备用节点列表(Zonelist):Node 0 → Node 1 → ... 跨节点备用分配

1.5 本章小结

  • NUMA 是一种非统一内存访问架构,处理器访问本地内存和远程内存的延迟不同。
  • UMA vs NUMA: UMA 延迟统一但扩展性差,NUMA 延迟非统一但扩展性强,是现代多核服务器的标准架构。
  • 拓扑结构: 由 Socket、Core、Thread、NUMA 节点和点对点互联链路组成,理解拓扑是调度优化的基础。
  • 节点与内存域: Linux 内核通过 pglist_data 管理每个 NUMA 节点,每个节点内包含 ZONE_DMA、ZONE_NORMAL 等内存域,并通过备用节点列表实现跨节点内存分配。