节点内互联(NVLink)
NVLink 技术演进
| 版本 |
产品 |
带宽(双向/GPU对) |
拓扑 |
| NVLink 1.0 |
P100 |
160 GB/s |
部分互联 |
| NVLink 2.0 |
V100 |
300 GB/s |
全互联(NVSwitch) |
| NVLink 3.0 |
A100 |
600 GB/s |
全互联(NVSwitch) |
| NVLink 4.0 |
H100 |
900 GB/s |
全互联(NVSwitch) |
NVSwitch 全互联
8 张 GPU + 6 个 NVSwitch 芯片实现全互联:任意两张 GPU 间带宽(A100):直连:600 GB/s经 NVSwitch:600 GB/s(无性能损失)对比 PCIe:PCIe 4.0 x16:64 GB/s(双向)NVLink 3.0:600 GB/s(快 9 倍以上)
验证 NVLink 状态
# 查看 NVLink 拓扑
nvidia-smi topo -m# 输出示例:
# GPU0 GPU1 GPU2 GPU3 GPU4 GPU5 GPU6 GPU7
# GPU0 X NV12 NV12 NV12 NV12 NV12 NV12 NV12
# GPU1 NV12 X NV12 NV12 NV12 NV12 NV12 NV12
# ...
# NV12 = NVLink 12 条链路连接# 测试 NVLink 带宽
/usr/local/cuda/samples/1_Utilities/p2pBandwidthLatencyTest/p2pBandwidthLatencyTest
节点间互联(InfiniBand)
InfiniBand 技术规格
| 规格 |
带宽 |
延迟 |
典型产品 |
| EDR(100Gbps) |
12.5 GB/s |
~600ns |
Mellanox ConnectX-5 |
| HDR(200Gbps) |
25 GB/s |
~600ns |
Mellanox ConnectX-6 |
| NDR(400Gbps) |
50 GB/s |
~500ns |
Mellanox ConnectX-7 |
| XDR(800Gbps) |
100 GB/s |
~500ns |
下一代(规划中) |
RDMA 通信原理
传统 TCP/IP 通信:应用 → 系统调用 → 内核协议栈 → 网卡驱动 → 网卡延迟:~10-100μs,CPU 参与全程RDMA 通信:应用 → 直接操作网卡(绕过内核)→ 网卡延迟:~600ns,CPU 几乎不参与RDMA 三种实现:InfiniBand:原生 RDMA,性能最好RoCE v2:以太网上的 RDMA,需无损网络iWARP:TCP 上的 RDMA,性能较差
InfiniBand 集群配置
# 安装 MLNX_OFED 驱动
./mlnxofedinstall --all --force# 验证 IB 网卡状态
ibstat
# 关注:State: Active,Physical state: LinkUp# 查看 IB 网络拓扑
ibnetdiscover | head -50# 测试 IB 带宽
# 服务端
ib_write_bw -d mlx5_0 -i 1# 客户端
ib_write_bw -d mlx5_0 -i 1 <server-ip># 测试 IB 延迟
ib_write_lat -d mlx5_0 -i 1 <server-ip>
分布式训练通信
NCCL(NVIDIA Collective Communications Library)
NCCL 是 GPU 集群分布式训练的核心通信库:
# PyTorch 分布式训练示例
import torch
import torch.distributed as dist
import torch.nn as nn
from torch.nn.parallel import DistributedDataParallel as DDPdef setup(rank, world_size):"""初始化分布式环境"""dist.init_process_group(backend='nccl', # 使用 NCCL 后端init_method='env://', # 通过环境变量初始化world_size=world_size,rank=rank)def train(rank, world_size):setup(rank, world_size)# 将模型移到对应 GPUdevice = torch.device(f'cuda:{rank}')model = MyModel().to(device)# 包装为 DDP 模型model = DDP(model, device_ids=[rank])optimizer = torch.optim.Adam(model.parameters(), lr=1e-4)for epoch in range(num_epochs):for batch in dataloader:inputs, labels = batchinputs, labels = inputs.to(device), labels.to(device)optimizer.zero_grad()outputs = model(inputs)loss = criterion(outputs, labels)loss.backward() # 自动 AllReduce 梯度optimizer.step()dist.destroy_process_group()# 启动(每台机器上运行)
# torchrun --nproc_per_node=8 --nnodes=8 \
# --node_rank=0 --master_addr=node0 --master_port=29500 \
# train.py
NCCL 集合通信操作
import torch
import torch.distributed as dist# AllReduce:所有节点的梯度求和,结果广播到所有节点
# 用于数据并行训练的梯度同步
tensor = torch.ones(1024).cuda()
dist.all_reduce(tensor, op=dist.ReduceOp.SUM)# AllGather:收集所有节点的数据
output = [torch.zeros(1024).cuda() for _ in range(world_size)]
dist.all_gather(output, tensor)# Broadcast:将 rank 0 的数据广播到所有节点
dist.broadcast(tensor, src=0)# Scatter:将数据分发到各节点
if rank == 0:scatter_list = [torch.ones(256).cuda() * i for i in range(world_size)]
else:scatter_list = None
output = torch.zeros(256).cuda()
dist.scatter(output, scatter_list, src=0)
NCCL 性能调优
# 设置 NCCL 环境变量
export NCCL_DEBUG=INFO # 开启调试日志
export NCCL_IB_DISABLE=0 # 启用 InfiniBand
export NCCL_IB_HCA=mlx5_0,mlx5_1 # 指定 IB 网卡
export NCCL_SOCKET_IFNAME=eth0 # 指定以太网接口
export NCCL_TREE_THRESHOLD=0 # 强制使用 Ring AllReduce# 测试 NCCL 性能
git clone https://github.com/NVIDIA/nccl-tests
cd nccl-tests && make MPI=1 MPI_HOME=/usr/local/mpi CUDA_HOME=/usr/local/cuda# 运行 AllReduce 测试
mpirun -np 16 -H node0:8,node1:8 \./build/all_reduce_perf -b 8 -e 8G -f 2 -g 1
网络性能基准
典型 8 节点(64 GPU)集群 AllReduce 带宽:消息大小 InfiniBand HDR RoCE 100GbE
1MB ~18 GB/s ~8 GB/s
100MB ~22 GB/s ~11 GB/s
1GB ~23 GB/s ~12 GB/s训练吞吐影响:通信效率 = 计算时间 / (计算时间 + 通信时间)目标:通信效率 > 90%(通信不成为瓶颈)