3. 压测工具选型

说到压测工具选型,我见过不少团队一上来就选最火的工具,结果跑起来才发现水土不服。其实说白了,没有万能工具,只有最合适的组合。今天我就把几个主流工具掰开揉碎讲清楚,帮你少走弯路。

3.1 主流工具速览

目前业界常用的GPU集群压测工具,我按使用场景分成了四类:

工具 核心定位 我推荐的使用场景
NCCL Tests 通信原语基准测试 网络带宽、延迟、拓扑验证
DeepSpeed 分布式训练框架 ZeRO优化、大模型训练压测
Megatron-LM 模型并行训练框架 张量/流水线并行压测
MLPerf 行业标准基准 横向对比、合规性验证
自定义脚本 灵活定制 特定场景、故障注入

3.2 NCCL Tests:通信层面的“听诊器”

我个人习惯,拿到一个新集群,第一件事就是跑NCCL Tests。为什么?因为它能直接暴露网络问题。

NCCL Tests主要测这几个东西:

  • all_reduce:最常用的集合通信操作
  • all_gather:数据收集性能
  • reduce_scatter:数据分发性能
  • broadcast:广播延迟

关键指标:带宽利用率(理想值>90%)、延迟抖动(<10us)

举个例子,跑个8卡all_reduce测试:

# 单节点8卡测试
mpirun -np 8 \
  -host localhost:8 \
  /path/to/nccl-tests/build/all_reduce_perf \
  -b 8 -e 128M -f 2 -g 1

# 跨节点测试(4节点,每节点8卡)
mpirun -np 32 \
  -host node1:8,node2:8,node3:8,node4:8 \
  /path/to/nccl-tests/build/all_reduce_perf \
  -b 8 -e 128M -f 2 -g 1

我在项目中遇到过,某次跨节点测试带宽只有理论值的60%。排查了半天,发现是网卡中断绑定没做好。嗯,这种问题NCCL Tests一跑就现原形。

3.3 DeepSpeed:ZeRO优化的“试金石”

DeepSpeed是微软开源的分布式训练框架,它的压测价值在于验证ZeRO系列优化是否生效。

我个人建议重点关注:

  • ZeRO-1:优化器状态分片,适合小规模集群
  • ZeRO-2:梯度分片,中等规模集群首选
  • ZeRO-3:参数分片,大模型必备

我的经验:ZeRO-3虽然省显存,但通信开销大。如果网络带宽不够,反而比ZeRO-2慢。建议先跑NCCL Tests确认网络没问题,再上ZeRO-3。

跑个简单的压测脚本:

# deepspeed 压测示例
deepspeed --num_gpus=8 \
  --num_nodes=4 \
  train.py \
  --model_name -large \
  --batch_size 16 \
  --zero_stage 3 \
  --gradient_accumulation_steps 4

3.4 Megatron-LM:模型并行的“压力锅”

Megatron是NVIDIA的模型并行框架,专门压测张量并行和流水线并行。说实话,这个工具对网络要求极高。

核心压测维度:

  • 张量并行(TP):单节点内GPU间通信,依赖NVLink
  • 流水线并行(PP):跨节点通信,依赖RDMA网络
  • 数据并行(DP):梯度同步,依赖all_reduce

注意:Megatron的配置非常复杂。我曾经因为TP和PP的通信重叠没处理好,导致GPU利用率只有40%。建议先用小模型验证配置正确性。

一个典型的压测命令:

# Megatron 压测示例
python pretrain_ \
  --tensor-model-parallel-size 4 \
  --pipeline-model-parallel-size 4 \
  --num-layers 40 \
  --hidden-size 5120 \
  --num-attention-heads 32 \
  --micro-batch-size 4 \
  --global-batch-size 1024

3.5 MLPerf:行业标准的“裁判员”

MLPerf是MLCommons推出的行业基准。如果你需要向客户或领导证明集群性能,MLPerf是最有说服力的。

它包含多个基准:

  • 训练(Training):BERT、ResNet、等模型
  • 推理(Inference):在线/离线场景
  • 存储(Storage):数据加载性能

我的建议:MLPerf适合做最终验收,不适合日常调试。因为跑一次要几个小时,而且结果受很多因素影响。

3.6 自定义脚本:最后的“杀手锏”

当现成工具满足不了需求时,就得自己动手了。我经常写自定义脚本做这几件事:

  • 故障注入:模拟网卡故障、GPU掉卡
  • 混合负载:同时跑训练和推理
  • 长时间稳定性:跑72小时以上看有没有内存泄漏

一个简单的自定义压测脚本框架:

import torch
import torch.distributed as dist
import time

def custom_benchmark():
    dist.init_process_group("nccl")
    rank = dist.get_rank()
    world_size = dist.get_world_size()
    
    # 自定义通信模式
    tensor = torch.randn(1024, 1024).cuda()
    
    # 模拟混合精度训练
    for i in range(1000):
        # all_reduce
        dist.all_reduce(tensor)
        
        # 模拟计算
        torch.mm(tensor, tensor)
        
        if rank == 0 and i % 100 == 0:
            print(f"Iter {i}: bandwidth = {measure_bandwidth()}")
    
    dist.destroy_process_group()

3.7 选型策略:场景决定工具

说了这么多,到底怎么选?我总结了一个简单的决策树:

压测目标是什么? 通信性能验证 训练吞吐压测 行业基准对比 NCCL Tests DeepSpeed (ZeRO) Megatron (TP/PP) 自定义脚本 MLPerf 我的推荐组合 日常调试:NCCL Tests + 自定义脚本 大模型训练:DeepSpeed + Megatron 最终验收:MLPerf + 自定义脚本 (三者结合,覆盖通信、训练、基准三个维度)

3.8 避坑指南

最后分享几个我踩过的坑:

我曾经...只用MLPerf做压测,结果发现网络有瓶颈但MLPerf没暴露出来。后来才知道MLPerf的通信模式比较固定,有些问题测不到。所以我现在都是NCCL Tests先扫一遍,再用MLPerf做最终验证。

另一个教训:自定义脚本虽然灵活,但别重复造轮子。我见过有人花两周写了个all_reduce测试,结果NCCL Tests一行命令就搞定了。先看看现成工具能不能满足需求,再决定要不要自己写。

嗯,工具选型就聊到这儿。记住一个原则:先通信,再训练,最后基准。按这个顺序来,基本不会出大问题。