3. 多卡推理系统架构

3.1 多卡服务器的物理拓扑层次

多卡推理服务器的性能不仅取决于单张GPU的算力,更取决于GPU之间以及GPU与CPU之间的数据搬运能力。理解物理拓扑是定位负载不均问题的第一步。一台典型的8卡服务器(如NVIDIA DGX系列或主流AI服务器)内部存在三个层次的互连:CPU-GPU互连(PCIe或CXL)、GPU-GPU直接互连(NVLink/NVSwitch)、以及CPU-内存-网卡的系统互连。下图展示了一个典型的双路CPU + 8卡GPU的服务器拓扑结构:

CPU 0 PCIe Root Complex A CPU 1 PCIe Root Complex B UPI / QPI 互连(CPU间) DDR4/5 DDR4/5 DDR4/5 DDR4/5 PCIe Switch / PEX 交换芯片(PCIe Gen4/Gen5 总线) 上行:CPU Root Complex | 下行:GPU、NVMe、网卡 GPU 0 NVLink 端口 GPU 1 NVLink 端口 GPU 2 NVLink 端口 GPU 3 NVLink 端口 GPU 4 NVLink 端口 GPU 5 NVLink 端口 GPU 6 NVLink 端口 GPU 7 NVLink 端口 NVSwitch 全连接交换(600GB/s) NIC 网卡(200GbE) PCIe (32GB/s) NVLink (600GB/s) DDR 内存 以太网

从上图可以看到,GPU 0~3 挂在 CPU 0 的 PCIe 域下,GPU 4~7 挂在 CPU 1 的 PCIe 域下。所有 GPU 通过 NVLink 连接到 NVSwitch,形成全互联的 NVLink 域。这种拓扑决定了:同域内 GPU 通信走 PCIe 或 NVLink,跨域通信必须经过 CPU 间的 UPI/QPI 链路,延迟和带宽差异巨大。

3.2 三种互连方式的性能对比

理解三种互连方式的带宽和延迟差异,是判断推理负载是否受通信瓶颈制约的基础。下表给出了典型 8 卡 A100/H100 服务器上的实测参考值:

互连方式 单向带宽 延迟(P2P) 典型场景
PCIe Gen4 x16 32 GB/s ~1.5 μs CPU-GPU 数据传输、跨域 GPU 通信
NVLink 3.0(单链路) 50 GB/s ~0.5 μs 同域 GPU 点对点通信
NVSwitch 全互联 600 GB/s(聚合) ~0.8 μs 8 卡全对全通信(All-to-All)
关键判断:当你的推理模型使用张量并行(Tensor Parallelism)时,每层 Transformer 的 AllReduce 通信量约为 2× 模型隐藏层维度 × 层数。如果模型隐藏层为 8192、共 80 层,单次 AllReduce 通信量约为 1.3 MB。在 NVLink 上耗时约 2.6 μs,在 PCIe 上则需 40 μs——差距超过 15 倍。因此,张量并行组必须尽量落在同一个 NVSwitch 域内。

3.3 CPU-GPU 通信路径与 NUMA 感知

CPU 与 GPU 之间的通信路径并非对称。每个 GPU 在物理上更靠近某一个 CPU 的 PCIe Root Complex,这种亲缘关系称为 NUMA 节点亲和性。当 GPU 需要从 CPU 侧读取数据(如推理请求的输入张量、KV Cache 的初始值)时,数据路径如下:

  1. CPU 应用程序将输入数据写入 页锁定内存(Pinned Memory),避免操作系统换页导致 DMA 失败。
  2. 数据通过 PCIe 控制器从 CPU 内存搬运到 GPU 显存(H2D 拷贝)。
  3. GPU 完成推理后,结果通过反向路径写回 CPU 内存(D2H 拷贝)。

如果 GPU 与 CPU 不在同一 NUMA 节点,数据必须经过 UPI/QPI 跨 CPU 传输,额外增加约 200~400 ns 延迟,且占用 CPU 间带宽。在推理服务中,请求预处理(Tokenization、Padding)和后处理(Sampling、Logits 处理)通常由 CPU 完成,这些操作产生的数据搬运频率极高,NUMA 错配会显著拉长单次请求的端到端延迟。

# 检查 GPU 的 NUMA 亲和性(Linux)
# 查看每个 GPU 对应的 PCIe 总线地址
nvidia-smi --query-gpu=index,pci.bus_id --format=csv

# 查看 PCIe 设备所在的 NUMA 节点
cat /sys/bus/pci/devices/0000:3b:00.0/numa_node

# 推荐:使用 nvidia-smi 的拓扑矩阵
nvidia-smi topo -m

执行 nvidia-smi topo -m 后,输出矩阵中 NV# 表示 NVLink 连接,PIX 表示同一 PCIe 交换机下,PXB 表示经过 PCIe 桥,SYS 表示需要经过 CPU 间互连。例如:

        GPU0    GPU1    GPU2    GPU3    GPU4    GPU5    GPU6    GPU7
GPU0     X      NV1     NV1     NV2     SYS     SYS     SYS     SYS
GPU1    NV1      X      NV2     NV1     SYS     SYS     SYS     SYS
GPU2    NV1     NV2      X      NV1     SYS     SYS     SYS     SYS
GPU3    NV2     NV1     NV1      X      SYS     SYS     SYS     SYS
GPU4    SYS     SYS     SYS     SYS      X      NV1     NV1     NV2
GPU5    SYS     SYS     SYS     SYS     NV1      X      NV2     NV1
GPU6    SYS     SYS     SYS     SYS     NV1     NV2      X      NV1
GPU7    SYS     SYS     SYS     SYS     NV2     NV1     NV1      X

上例中,GPU0~3 与 GPU4~7 之间全部是 SYS,意味着跨组通信必须走 CPU 间的 UPI 链路,带宽骤降至 PCIe 水平且延迟翻倍。如果推理框架将张量并行组跨组放置,性能将严重劣化。

3.4 实际案例:8 卡服务器上的推理部署拓扑选择

假设我们要部署一个 70B 参数的 LLM,采用张量并行(TP=4)+ 流水线并行(PP=2)的混合并行策略。70B 模型权重约 140 GB(FP16),单张 A100 80GB 无法容纳,必须使用 TP=4 将权重切分到 4 张 GPU 上。此时有两种拓扑选择:

方案 A(推荐):TP 组内使用 NVLink 全互联的 4 张 GPU(如 GPU0~3),PP 组跨 NVSwitch 域(GPU0~3 与 GPU4~7 之间)。

方案 B(不推荐):TP 组跨域放置(如 GPU0、GPU1、GPU4、GPU5),PP 组在同域内。

方案 A 中,TP 组内每层 Transformer 的 AllReduce 走 NVLink,带宽 600 GB/s,通信耗时极短;PP 组之间传输的是激活值(每层约几 MB),频率低,即使走 PCIe 影响也可控。方案 B 中,TP 组内每次 AllReduce 都要经过 UPI 链路,通信耗时增加 10 倍以上,GPU 利用率将出现明显的“锯齿状”波动——计算等待通信,整体吞吐下降 30%~50%。

常见误区:很多工程师只关注 GPU 显存是否够用,而忽略了拓扑亲和性。在 8 卡服务器上,torch.distributed 默认按 GPU 序号分配 rank,如果直接使用 --nproc-per-node=8 启动 TP=4 的推理,框架可能将 rank 0~3 和 rank 4~7 分别作为两个 TP 组,这恰好是跨 NVSwitch 域的——性能反而不如同域内 TP=4 + 跨域 PP=2 的组合。务必通过 NCCL_P2P_LEVEL 和 NCCL_TOPO_DUMP_FILE 检查实际通信路径。

3.5 拓扑感知的部署检查清单

  • 第一步:运行 nvidia-smi topo -m 获取 GPU 间互连矩阵,标记 NVLink 域和 PCIe 域。
  • 第二步:确认每个 GPU 的 NUMA 亲和性,记录 numa_node 值。
  • 第三步:根据模型并行策略,将通信最频繁的并行组(TP 组)放置在 NVLink 域内。
  • 第四步:设置环境变量 NCCL_P2P_LEVEL=NV 强制 NCCL 仅使用 NVLink 做 P2P,避免意外走 PCIe。
  • 第五步:使用 nsys profile 或 ncu 抓取通信耗时,验证 AllReduce 是否达到 NVLink 带宽。