2. AMD EPYC处理器架构与网络I/O特性

在服务器高速网络集成中,网卡能否跑满、延迟是否稳定,往往不取决于网卡本身,而取决于处理器如何把 PCIe 通道、内存带宽和跨 NUMA 节点的数据流组织起来。AMD EPYC 的设计特点,正是理解这一点的关键入口。

Zen 架构核心与 CCD/IOD 分离

现代 EPYC(以 Zen 3/Zen 4 为代表)采用小芯片(Chiplet)结构:每个 CCD(Core Complex Die)内含若干 Zen 核心与共享的 L3 缓存,多个 CCD 通过 Infinity Fabric 连接到一个中央 IOD(I/O Die)。IOD 承担内存控制器、PCIe 控制器和 Infinity Fabric 交换的职责。这种"计算与 I/O 分离"的布局意味着:核心访问本地 L3 很快,但跨 CCD 通信、访问内存、访问 PCIe 设备都要经过 IOD 和 Infinity Fabric,其带宽与延迟成为网络吞吐的隐性瓶颈。

对网络工程而言,关键推论是:网卡挂载位置与处理网络中断/收发包的核心之间的"距离",直接决定单流吞吐和时延抖动。如果网卡挂在 IOD 的某个 PCIe Root Complex 上,而处理软中断的核心位于远端 CCD,数据就要多走一段 Infinity Fabric,P99 延迟会明显上升。

PCIe 通道布局与网卡落位

EPYC 提供 128 条 PCIe 5.0 通道(单路),通常划分为多个 x16 插槽组,并分布在 IOD 的不同 Root Complex 上。以典型双路主板为例,CPU0 与 CPU1 各自引出若干 x16 插槽,靠近 CPU0 的插槽物理上归属 CPU0 的 PCIe 控制器。判断网卡归属,最直接的方法是查看 sysfs 中的 NUMA 节点:

# 查看网卡所在 PCIe 设备的 NUMA 节点
cat /sys/class/net/ens1f0/device/numa_node
# 输出 0 表示归属 CPU0 的 NUMA 节点

# 查看网卡与 CPU 的亲和关系
lscpu | grep NUMA
cat /sys/class/net/ens1f0/device/local_cpulist

若 numa_node 返回 0,则应把该网卡的中断亲和、收包队列和处理进程绑定到 NUMA 0 的核心上。反之,若把 100G 网卡的收包线程绑到 NUMA 1,跨节点流量会挤占 Infinity Fabric 带宽,实测中常见吞吐下降 15%~30%(示例量级,实际依平台而定)。

内存带宽与 NUMA 拓扑对吞吐的影响

EPYC 每路集成 12 通道 DDR5,双路可达 24 通道,理论内存带宽非常充裕。但网络收发包是"内存带宽敏感型"负载:每个报文都要经历 DMA 写入、协议栈读取、应用拷贝。若网卡与内存分属不同 NUMA 节点,DMA 数据要跨 Infinity Fabric 写入远端内存,带宽和延迟双重受损。

因此工程上的基本原则是"三对齐":网卡 PCIe 归属、内存分配节点、处理核心三者对齐到同一 NUMA 节点。可通过 numactl 强制内存与进程绑定:

# 将收包进程绑定到 NUMA 0 的核心与内存
numactl --cpunodebind=0 --membind=0 ./packet_forwarder

# 查看各 NUMA 节点的内存与 CPU 分布
numactl --hardware

下图展示了双路 EPYC 平台上,网卡、IOD、CCD 与内存之间的数据通路关系,以及"对齐"与"跨节点"两种路径的差异。

双路 EPYC 网络 I/O 数据通路与 NUMA 对齐 CPU0 / NUMA Node 0 CCD0 Zen 核心 + L3 CCD1 Zen 核心 + L3 IOD (I/O Die) 内存控制器 · PCIe RC · IF 交换 DDR5 通道 本地内存 网卡 ens1f0 PCIe x16 · NUMA0 CPU1 / NUMA Node 1 CCD2 Zen 核心 + L3 CCD3 Zen 核心 + L3 IOD (I/O Die) 内存控制器 · PCIe RC · IF 交换 DDR5 通道 本地内存 网卡 ens2f0 PCIe x16 · NUMA1 Infinity Fabric 跨节点 跨 NUMA 访问带宽/延迟受限 ✓ 对齐路径:网卡→IOD→本地CCD/内存 ✗ 跨节点路径:经 IF 访问远端资源

EPYC 型号选型与网络适配原则

选型时不能只看核心数。对高速网络场景,应重点关注三类参数:PCIe 通道数与版本、内存通道数与带宽、NUMA 节点数量(NPS 配置)。例如面向 2×100G 网卡转发,建议选择单路 32 核以上、支持 PCIe 5.0 x16 双插槽、12 通道 DDR5 的型号,如 EPYC 9004 系列中 9354/9454 一类;若追求极致单流性能,则优先高主频型号而非堆核。

另一个常被忽视的选项是 NPS(Nodes Per Socket)。BIOS 中可将单路 CPU 的内存划分为 NPS1、NPS2、NPS4。NPS1 把整颗 CPU 视为一个 NUMA 节点,跨 CCD 延迟较低但内存局部性弱;NPS4 把内存分成 4 个节点,局部性更好但跨节点访问增多。对网络转发这类需要大量内存带宽的负载,通常建议 NPS1 或 NPS2,并通过 numactl --hardware 确认实际拓扑后再绑定。

判断网卡是否"落对位置"的快速方法:查看 /sys/class/net/<iface>/device/numa_node 与 local_cpulist,若二者一致,说明 PCIe 归属与可用核心在同一节点,绑定后即可获得最优路径。
不要仅凭插槽物理位置判断 NUMA 归属。部分主板插槽走线经过 PCIe Switch 或跨 CPU 的链路,实际 numa_node 可能与外观不符,务必以 sysfs 输出为准。

综合来看,EPYC 的网络 I/O 性能不是单一参数决定的,而是"PCIe 落位—NUMA 归属—内存绑定—核心亲和"这条链路的整体结果。理解 Zen 架构的 CCD/IOD 分离与 Infinity Fabric 的跨节点代价,才能在选型和部署时做出正确判断,让高速网卡真正跑在设计带宽上。