2. 多核CPU架构:SMP与NUMA架构简介、CPU拓扑结构(socket/core/thread)

在深入网卡队列与中断分布之前,必须理解现代多核CPU的物理架构。中断绑定策略的成败,直接取决于你对CPU拓扑(Socket / Core / Thread)以及内存访问模型(SMP vs NUMA)的认知深度。错误的绑定可能导致跨片内存访问延迟剧增,甚至引发性能回退。

2.1 SMP 与 NUMA 架构对比

对称多处理(SMP)与非统一内存访问(NUMA)是两种主流的多核CPU内存架构。它们的核心区别在于“所有CPU核心访问内存的成本是否一致”。

特性 SMP(对称多处理) NUMA(非统一内存访问)
内存访问模型 所有核心共享一个统一内存控制器,访问延迟一致 每个Socket拥有本地内存控制器,访问本地内存快,远端内存慢
物理拓扑 单颗CPU(单Socket)或多颗CPU通过FSB共享内存 多颗CPU(多Socket)通过高速互联链路(如UPI/CCX)连接
扩展性瓶颈 内存总线带宽成为瓶颈,核心数增多时竞争加剧 可扩展性更好,每个Socket拥有独立内存带宽
中断分布策略 中断可任意分配到任何核心,无需考虑距离 中断应尽量绑定到与网卡同Socket的核心,避免跨片访问
适用场景 低核心数(≤8核)、低延迟敏感型应用 高核心数(≥16核)、高性能计算、DPDK、NFV
实践要点: 在NUMA架构下,如果网卡中断被分配到远端Socket的核心,每次中断处理都需要跨UPI链路访问网卡DMA内存,延迟增加30%~50%。这是性能优化中最容易忽略的陷阱。

2.2 CPU拓扑结构:Socket / Core / Thread

Linux内核将CPU拓扑抽象为三级层次:Socket(物理插槽) → Core(物理核心) → Thread(超线程逻辑核)。理解这一层次是正确设置smp_affinity和irqbalance策略的前提。

  • Socket:物理CPU芯片,每个Socket拥有独立的内存控制器(NUMA节点)、L3缓存和互联接口。
  • Core:Socket内的独立物理执行单元,拥有私有L1/L2缓存。
  • Thread:通过超线程(Hyper-Threading)技术在一个Core上模拟出的两个逻辑核,共享Core的L1/L2缓存和执行资源。
关键指标: 在中断分布时,应优先将中断绑定到不同Socket的不同Core上,避免绑定到同一Core的两个Thread上,否则无法获得真正的并行处理能力。

2.3 CPU拓扑结构SVG图

下图展示了一个典型的双Socket NUMA系统,每个Socket包含4个Core,每个Core通过超线程提供2个Thread。网卡物理连接到Socket 0的PCIe控制器。

双Socket NUMA CPU拓扑与网卡连接 双Socket NUMA CPU拓扑与网卡连接 Socket 0 (NUMA Node 0) 本地内存: 64GB | L3缓存: 16MB Socket 1 (NUMA Node 1) 本地内存: 64GB | L3缓存: 16MB Core 0 Thread 0 Thread 1 Core 1 Thread 2 Thread 3 Core 2 Thread 4 Thread 5 Core 3 Thread 6 Thread 7 Core 4 Thread 8 Thread 9 Core 5 Thread 10 Thread 11 Core 6 Thread 12 Thread 13 Core 7 Thread 14 Thread 15 UPI NIC 网卡 (eth0) PCIe 连接到 Socket 0 PCIe ⚠ 中断分布原则: • 网卡中断应绑定到 Socket 0 的 Core 0~3(Thread 0~7),避免跨Socket访问。 • 同一Core的两个Thread不要同时处理中断,否则超线程争用导致吞吐量下降。

2.4 查看CPU拓扑的命令行工具

在Linux系统中,可以通过以下命令快速获取CPU拓扑信息,为中断绑定提供数据基础。

命令 输出内容 用途
lscpu Socket数、Core数、Thread数、NUMA节点数 快速概览CPU架构
lstopo 图形化拓扑图(含缓存层级) 可视化Socket/Core/Thread关系
cat /proc/cpuinfo 每个逻辑核的详细信息(physical id, core id, cpu cores) 确认每个Thread所属的Core和Socket
numactl --hardware NUMA节点分布、内存大小、节点距离 评估跨NUMA访问代价
常见误区: 不要将/proc/cpuinfo中的processor编号直接当作物理Core编号。在超线程开启时,processor是逻辑编号,需要通过core id和physical id字段映射到物理拓扑。

2.5 实战:解析CPU拓扑信息

以下是一个典型的双Socket、每Socket 4 Core、每Core 2 Thread的服务器输出示例。通过解析这些字段,你可以准确判断每个逻辑核的物理位置。

# lscpu 输出示例
Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                16
On-line CPU(s) list:   0-15
Thread(s) per core:    2
Core(s) per socket:    4
Socket(s):             2
NUMA node(s):          2
NUMA node0 CPU(s):     0-7
NUMA node1 CPU(s):     8-15
# cat /proc/cpuinfo | grep -E "processor|physical id|core id|cpu cores"
processor       : 0
physical id     : 0
core id         : 0
cpu cores       : 4

processor       : 1
physical id     : 0
core id         : 0
cpu cores       : 4

processor       : 2
physical id     : 0
core id         : 1
cpu cores       : 4

processor       : 8
physical id     : 1
core id         : 0
cpu cores       : 4
解读: 从lscpu可知,系统共16个逻辑核,2个Socket,每Socket 4个Core,每Core 2个Thread。NUMA node0包含CPU 0-7(Socket 0),NUMA node1包含CPU 8-15(Socket 1)。从/proc/cpuinfo可见,processor 0和1同属physical id 0、core id 0,说明它们是同一Core上的两个超线程。

2.6 中断分布与NUMA亲和性

在NUMA架构下,中断分布的核心原则是:将中断绑定到与网卡所在NUMA节点相同的CPU核心上。这可以通过以下步骤实现:

  1. 确定网卡所在NUMA节点:使用cat /sys/class/net/eth0/device/numa_node,输出0表示网卡在NUMA node0。
  2. 选择目标CPU核心:从该NUMA节点对应的CPU列表中选取核心(如NUMA node0的CPU 0-7)。
  3. 设置smp_affinity:将中断亲和性掩码设置为只包含目标核心的位图。
  4. 验证效果:通过cat /proc/interrupts观察中断是否均匀分布在目标核心上。
性能收益: 在双Socket服务器上,将网卡中断从远端Socket(跨NUMA)迁移到本地Socket后,网卡吞吐量可提升15%~25%,同时CPU利用率下降10%以上。这是成本最低、收益最明显的优化手段之一。