CPU 架构基础:NUMA 与 SMP 架构的区别、CPU 拓扑结构、LLC 缓存共享

在集群环境中,理解 CPU 架构是进行亲和性调度与性能校准的前提。现代服务器 CPU 主要采用 SMP(对称多处理) 和 NUMA(非统一内存访问) 两种架构。两者的核心区别在于内存访问延迟是否一致,这直接影响进程调度策略和缓存利用率。

1. SMP 与 NUMA 架构对比

特性 SMP(对称多处理) NUMA(非统一内存访问)
内存访问模型 所有 CPU 核心通过共享总线访问同一块物理内存,访问延迟一致 每个 CPU 节点拥有本地内存,访问本地内存快,访问远端内存慢
扩展性 受限于共享总线带宽,核心数增多时竞争加剧,扩展性差 节点间通过高速互联(如 Intel UPI、AMD Infinity Fabric)通信,扩展性好
适用场景 低核心数(2~8 核)桌面或轻量服务器 高核心数(16~128+ 核)数据中心、HPC 集群
延迟差异 Uniform(统一延迟) Non-Uniform(本地 vs 远端延迟差可达 1.5~3 倍)
亲和性要求 低,任意核心调度均可 高,必须优先绑定本地内存与核心
性能校准提示: 在 NUMA 架构下,跨节点内存访问会显著增加延迟并降低内存带宽。对于延迟敏感型应用(如高频交易、实时数据库),必须通过 CPU 亲和性绑定将进程锁定在同一个 NUMA 节点内。

2. CPU 拓扑结构:Socket / Core / Thread

CPU 拓扑是一个三层嵌套结构,从物理封装到逻辑执行单元逐层展开。理解这一结构是设置亲和性掩码(affinity mask)的基础。

  • Socket(物理插槽):主板上的物理 CPU 芯片,每个 Socket 包含多个 Core。在 NUMA 系统中,一个 Socket 通常对应一个 NUMA 节点。
  • Core(物理核心):独立的执行单元,拥有自己的 L1/L2 缓存。多个 Core 共享 Socket 内的 LLC(最后一级缓存)。
  • Thread(逻辑处理器 / 超线程):通过 SMT(同步多线程)技术,一个物理 Core 可模拟出 2 个逻辑处理器,共享 Core 内的执行资源与 L1/L2 缓存。
关键指标: 在 Linux 系统中,可通过 lscpu 命令查看拓扑信息。输出中的 CPU(s) 为逻辑处理器总数,Core(s) per socket 为每插槽物理核心数,Thread(s) per core 为每核心超线程数。
# 示例:查看 CPU 拓扑
$ lscpu
Architecture:        x86_64
CPU op-mode(s):      32-bit, 64-bit
CPU(s):              32
On-line CPU(s) list: 0-31
Thread(s) per core:  2
Core(s) per socket:  8
Socket(s):           2
NUMA node(s):        2
NUMA node0 CPU(s):   0-7,16-23
NUMA node1 CPU(s):   8-15,24-31

上述输出表示:2 个 Socket(NUMA 节点),每个 Socket 8 个物理核心,每核心 2 个超线程,总计 32 个逻辑处理器。NUMA node0 包含 CPU 0-7 和 16-23(即 Socket0 的所有物理核心及其超线程)。

3. LLC 缓存共享与拓扑关系

LLC(Last Level Cache,最后一级缓存) 是 CPU 缓存层次中的最大共享缓存。在 Intel 平台上通常为 L3 缓存,在 AMD Zen 架构中为 L3 缓存(每个 CCD 内共享)。LLC 的共享范围直接定义了哪些 CPU 核心之间的数据交换延迟最低。

缓存层级 容量 共享范围 延迟(典型)
L1(指令/数据) 32KB ~ 64KB 单个物理核心(私有) ~1ns
L2 256KB ~ 1MB 单个物理核心(私有) ~3-5ns
L3(LLC) 8MB ~ 64MB 同一 Socket 内所有 Core 共享 ~10-20ns
性能陷阱: 如果两个频繁通信的进程被调度到不同 Socket 的核心上,即使它们共享 LLC,实际访问的是远端 LLC(跨 Socket 的 L3 片),延迟会显著增加。在 NUMA 系统中,跨 Socket 的 LLC 访问延迟通常比本地 Socket 高 30%~100%。

4. NUMA 架构下的内存访问拓扑

下图展示了双 Socket NUMA 系统的典型拓扑结构,包括 Socket、Core、LLC 以及内存控制器的连接关系。

双 Socket NUMA 系统拓扑结构 Socket 0 (NUMA Node 0) Core 0 L1/L2 私有缓存 Core 1 L1/L2 私有缓存 Core 2 L1/L2 私有缓存 Core 3 L1/L2 私有缓存 LLC (L3 缓存) — 所有 Core 共享 本地内存控制器 → 本地内存 Socket 1 (NUMA Node 1) Core 4 L1/L2 私有缓存 Core 5 L1/L2 私有缓存 Core 6 L1/L2 私有缓存 Core 7 L1/L2 私有缓存 LLC (L3 缓存) — 所有 Core 共享 本地内存控制器 → 本地内存 UPI / Infinity Fabric 远端内存访问(高延迟) 本地内存访问(低延迟) 图例: ■ Socket ■ Core (L1/L2) ■ LLC 共享缓存 ■ 内存控制器 → 远端访问 → 本地访问

5. 跨 Socket 通信与缓存一致性协议

在多 Socket 系统中,每个 Socket 拥有独立的 LLC 片。当 Core 0(Socket 0)修改了一个缓存行,而 Core 4(Socket 1)需要读取该数据时,必须通过 缓存一致性协议(如 Intel 的 MESIF、AMD 的 MOESI)进行跨 Socket 同步。这一过程涉及以下步骤:

  1. 本地 LLC 命中检查:Core 4 首先检查 Socket 1 的本地 LLC。
  2. 目录协议查询:如果本地 LLC 未命中,通过片上目录(Directory)定位数据所在的远端 Socket。
  3. 跨 Socket 请求:通过 UPI/Infinity Fabric 发送缓存行请求到 Socket 0。
  4. 数据响应与状态更新:Socket 0 返回数据并更新缓存行状态(如从 Modified 转为 Shared)。
性能校准指标: 跨 Socket 缓存行同步的延迟通常为本地 LLC 命中的 2~4 倍。在 perf stat 中,可通过 LLC-load-misses 和 remote-node-accesses 事件量化跨 Socket 访问频率。如果 remote-node-accesses 占比超过 10%,说明亲和性绑定策略需要优化。

6. 拓扑感知的亲和性调度原则

基于上述架构特征,在集群节点上进行 CPU 亲和性调度时应遵循以下优先级:

优先级 调度策略 原理 适用场景
1(最高) 同一物理核心的不同线程 共享 L1/L2 缓存,数据交换延迟最低 细粒度并行线程(如 OpenMP 循环)
2 同一 Socket 内的不同核心 共享 LLC,跨核心通信延迟可控 进程间频繁通信(如 MPI 节点内通信)
3 同一 NUMA 节点内的不同 Socket 共享本地内存,避免远端内存访问 内存密集型应用(如大数据处理)
4(最低) 跨 NUMA 节点调度 远端内存访问 + 跨 Socket LLC 同步,延迟最高 仅当本地资源不足时使用
常见误区: 不要将超线程视为独立核心。两个超线程共享同一个物理核心的执行单元,如果同时运行计算密集型任务,会导致资源争抢(端口竞争),性能反而下降。建议将超线程用于 I/O 等待型任务或作为备用逻辑处理器。