2. 硬件基础与网络拓扑

做分布式训练,说白了就是让一堆GPU一起干活。但怎么让它们高效协作,关键就看硬件怎么连的。我刚开始接触NCCL时,以为只要把网线插上就能跑,结果性能惨不忍睹。后来才明白——拓扑结构决定了通信的上限。

核心观点:NCCL的性能瓶颈,90%出在拓扑理解不到位。你想想看,数据从GPU A传到GPU B,中间经过了多少跳?PCIe、NVLink、网卡、交换机……每一跳都是延迟和带宽的损耗点。

一、GPU服务器内部拓扑

先看单机内部。一台8卡GPU服务器,GPU之间怎么互联?主要有两种方式:

1. NVLink/NVSwitch

NVLink是NVIDIA的高速互联技术。我习惯把它理解成GPU之间的“高速公路”。

  • NVLink 2.0:单条带宽50GB/s(双向),V100时代的产品
  • NVLink 3.0:单条带宽100GB/s(双向),A100开始支持
  • NVLink 4.0:单条带宽150GB/s(双向),H100的标配

NVSwitch则像个智能交换机,让所有GPU都能全互联。我记得第一次在DGX A100上跑测试,8卡之间all-reduce带宽直接拉满,那种感觉——嗯,很爽。

个人经验:我曾经在DGX-1(V100)上调试一个模型,发现GPU0和GPU3通信特别慢。查了半天,原来是它们之间没有直连NVLink,走了两跳。后来我把通信对重新映射,性能提升了30%。

2. PCIe拓扑

没有NVLink的服务器,GPU只能走PCIe。这里有个坑——PCIe的带宽是共享的。

举个例子:一台4卡服务器,如果所有GPU都挂在同一个PCIe Root Complex下,那么它们共享x16的带宽。你想想看,4个GPU同时通信,每个只能分到x4的带宽,不卡才怪。

PCIe版本 单通道带宽 x16带宽
PCIe 3.0 ~1 GB/s ~16 GB/s
PCIe 4.0 ~2 GB/s ~32 GB/s
PCIe 5.0 ~4 GB/s ~64 GB/s

避坑指南:我曾经遇到过一台服务器,4张卡插在同一个PCIe switch下,结果NCCL all-reduce性能只有理论值的1/4。后来用nvidia-smi topo -m一看,果然所有GPU都在同一个PCIe域里。解决方案?换主板,或者用NVLink桥接。

二、跨节点网络拓扑

单机搞定了,多机怎么办?跨节点通信靠网络,目前主流就两种:InfiniBand和RoCE。

1. InfiniBand(IB)

IB是高性能计算的标配。它有几个特点:

  • RDMA原生支持:数据直接从GPU到网卡,不经过CPU内存
  • 低延迟:微秒级,比TCP快一个数量级
  • 高带宽:HDR 200Gbps,NDR 400Gbps

我个人习惯用IB,因为稳定。在超算中心调过上百台IB集群,很少出幺蛾子。

2. RoCE(RDMA over Converged Ethernet)

RoCE是跑在以太网上的RDMA。说白了,就是拿普通网卡干IB的活。成本低,但配置麻烦。

RoCE v2是目前的主流,它把RDMA封装在UDP里。这里有个关键点——需要PFC(优先级流控)和ECN(显式拥塞通知)。没有这些,RoCE在丢包时性能会断崖式下跌。

我的经验:有一次客户用RoCE跑训练,性能时好时坏。我上去一看,交换机没开PFC。开了之后,性能稳定了,但延迟比IB高了20%。所以我的建议是:预算够就上IB,省钱就用RoCE,但要做好调优准备。

三、NUMA亲和性

NUMA(非统一内存访问)是个容易被忽略的点。简单说:CPU和内存不是对等的。

在双路服务器上,CPU0访问自己的内存快,访问CPU1的内存慢。GPU也是同理——GPU挂在哪个CPU的PCIe总线上,就优先用那个CPU的内存。

怎么查?用lstopo或者numactl --hardware。我习惯先画一张拓扑图:

# 查看GPU和CPU的亲和关系
nvidia-smi topo -m

# 输出示例:
#        GPU0    GPU1    GPU2    GPU3    CPU Affinity
# GPU0     X      NV1     NV2     NV3     0-15
# GPU1    NV1      X      NV2     NV3     0-15
# GPU2    NV2     NV2      X      NV1     16-31
# GPU3    NV3     NV3     NV1      X      16-31

看到没?GPU0和GPU1挂在CPU0上,GPU2和GPU3挂在CPU1上。跨NUMA通信会有额外延迟。

避坑指南:我曾经在调试时发现,NCCL all-reduce在跨NUMA节点时性能下降30%。后来用numactl --membind把进程绑定到对应NUMA节点,问题解决。记住:进程跑在哪个CPU,就让它用哪个CPU的内存和GPU。

四、知识体系总览

下面这张图,是我自己总结的拓扑知识体系。建议你保存下来,调优时对照着看:

GPU通信拓扑知识体系 单机内部拓扑 • NVLink:GPU直连,高带宽低延迟 • NVSwitch:全互联,NVLINK的交换机 • PCIe:共享带宽,注意Root Complex • NUMA:CPU-GPU亲和性绑定 跨节点网络拓扑 • InfiniBand:原生RDMA,稳定高效 • RoCE v2:以太网RDMA,成本低 • 需要PFC/ECN支持 • 拓扑:Fat-Tree / 环形 / 全互联 拓扑对通信的影响 • 带宽瓶颈:PCIe共享 vs NVLink直连,差距可达10倍 • 延迟累积:每多一跳,延迟增加1-5μs(跨节点更明显) 调优建议 • 使用 nvidia-smi topo -m 和 lstopo 绘制拓扑图 • NCCL拓扑感知:设置 NCCL_TOPO_FILE 或使用自动检测

这张图把整个知识体系串起来了。你想想看,从单机内部的NVLink、PCIe,到跨节点的IB、RoCE,再到NUMA亲和性——每一层都可能是瓶颈。

总结一下:理解拓扑,就是理解数据从哪来、到哪去、中间经过什么。我每次接手新集群,第一件事就是画拓扑图。画清楚了,调优就成功了一半。