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