跳到主要内容
推理优化

6.6 vLLM 分布式部署实战:从单卡到多机

一个完整的分布式部署演练:单卡基线 → 单节点 TP 扩展 → 多节点 TP+PP → MoE 的 EP+DP 组合,每一步的启动命令、预期日志、验证方法与常见坑

实战vLLM分布式部署性能验证启动参数

前五节把策略、原理、编排都讲完了,这一节做一次完整的部署演练——从单卡基线开始,逐步扩展到 8 卡 TP、多节点 TP+PP、以及 MoE 的 EP+DP 组合。每一步都给出:启动命令、你该看到什么怎么验证收益最常踩的坑。读完这一节,你应该能独立完成一次”模型装不下/不够快 → 分布式解决”的完整闭环。

📑 目录


1. 部署决策树:先想清楚再动手

动手前 30 秒做决策(对应 6.1 的选型):

Q1: 模型单卡装得下吗?(权重 + 激活 + KV Cache 预算)
├─ 装得下 → 不需要分布式
│     └─ Q2: 单卡吞吐够吗?
│           ├─ 够 → 直接部署(跳过本章)
│           └─ 不够 → DP 多副本 / 负载均衡(6.4)
└─ 装不下 → Q3: 单节点多卡装得下吗?
      ├─ 能 → TP(本节第 3 步)
      └─ 不能 → TP + PP(本节第 5 步)
补充:MoE 模型 → EP + DP(本节第 6 步)

先跑决策树,再敲命令——分布式部署 80% 的问题出在”没想清楚就加了参数”。


2. 第 0 步:单卡基线(所有对比的锚点)

先记录单卡(或单副本)的性能基线——没有基线,后面所有”扩展了 x 倍”都是空话

# 基线:单卡,max-model-len 按实际需求
vllm serve meta-llama/Llama-3.1-8B-Instruct \
    --max-model-len 8192 \
    --gpu-memory-utilization 0.9

用相同负载压测(这里用 vLLM benchmark 工具):

# 压测脚本(OpenAI 兼容接口)
python3 benchmark_serving.py \
    --model meta-llama/Llama-3.1-8B-Instruct \
    --endpoint /v1/completions \
    --num-prompts 1000 \
    --request-rate 20 \
    --max-concurrency 64

记录三组数:

指标单卡基线值说明
TTFT(P50 / P99)___ ms首 token 延迟
TPOT(P50 / P99)___ ms每 token 延迟
吞吐(Tokens/s)___系统总吞吐

💡 提示:基线要同负载、同参数——压测的并发数、请求长度分布必须固定,否则后续对比全是噪声。生产建议把基线数字写进部署文档,这是团队排查性能回退的参照系。


3. 第 1 步:单节点 TP 扩展(70B → 4×A100)

场景:70B 模型(FP16 权重 140GB)单卡装不下,节点有 4 张 A100-80G。

3.1 启动

vllm serve meta-llama/Llama-3.1-70B-Instruct \
    --tensor-parallel-size 4 \
    --max-model-len 8192 \
    --gpu-memory-utilization 0.9 \
    --enforce-eager          # 首次验证建议关闭 CUDA Graph,减少变量

📌 关键点:TP=4 后每卡权重 140/4 = 35GB,加 KV Cache 和激活,80G 卡绰绰有余。--enforce-eager 跑通功能,再去掉它开 CUDA Graph 测性能——分两步走,别让两个变量混在一起。

3.2 该看到的日志

INFO ... [parallel_config.py:...] Distributed init succeeded (backend=mp, world_size=4)
INFO ... [kv_cache_utils.py:775] GPU KV cache size: 643,232 tokens
  • Distributed init succeeded (backend=mp, world_size=4):4 个进程、单节点自动用 mp 后端
  • KV cache size 是4 卡合计——单卡约 160K tokens

3.3 功能验证

curl http://localhost:8000/v1/completions -H "Content-Type: application/json" \
  -d '{"model":"meta-llama/Llama-3.1-70B-Instruct","prompt":"Hello","max_tokens":64}'

顺带验证显存分布:

nvidia-smi
# 4 张卡显存应接近(35GB 权重 + 各自 KV Cache 预留)
# 某卡明显偏高 → 检查负载均衡或激活复制

4. 第 2 步:验证扩展收益(别只看”能跑”)

“能跑”不是成功,扩展收益达标才算成功。用第 0 步同样的压测参数跑 TP=4:

指标单卡基线TP=4 预期实测结论
TTFT P50基线接近 ÷4(通信开销后约 ÷3)___
TPOT P50基线接近 ÷4(同左)___
吞吐基线÷4 到 ×4 之间(并发足够时接近 ×4)___

收益不达标的排查顺序(按 6.5 的”算力 → 通信 → 负载均衡”):

  1. 算力:TP=4 每卡利用率是否都接近 100%?(nvidia-smi 反复采样)
  2. 通信:NVLink 域利用率是否异常?TP 的 AllReduce 是否走了 PCIe?(nvidia-smi 的 NVLink 计数 / ncu 分析)
  3. 负载:压测并发是否足够?(并发太低时分布式优势无法显现——单请求跑在 4 卡上,串行通信反而可能更慢)

💡 提示TP 小 batch 收益低是正常现象——Decode 场景 batch=1 时每卡算的矩阵很小,通信占比高。用 --max-num-seqs 把并发拉高再测,才是 TP 的真实收益。这也是为什么”压测必须固定并发”。


5. 第 3 步:多节点 TP+PP(单节点装不下时)

场景:700B 模型,2 节点 × 8 卡 A100/H100。单节点 8 卡(NVLink 域)装不下 → TP=8(节点内)+ PP=2(节点间)。

5.1 集群与启动(6.5 的完整流程)

# 节点 A(head)
ray start --head --port 6379 --num-gpus 8

# 节点 B
ray start --address <HEAD_IP>:6379 --num-gpus 8

# 验证
ray status        # 2 nodes, 16 GPUs

# 任一节点上启动(vLLM 自动跨节点拉起进程)
vllm serve <700b-model> \
    --tensor-parallel-size 8 \
    --pipeline-parallel-size 2 \
    --nnodes 2 \
    --distributed-executor-backend ray \
    --max-model-len 8192

5.2 该看到的日志与验证

INFO ... Distributed init succeeded (backend=ray, world_size=16)
  • world_size=16(8×2),Ray 后端
  • 节点 A 上 rank 0-7,节点 B 上 rank 8-15(TP 组内、PP 组间)

验证网络走对了(多节点最关键的检查):

# 节点间通信是否走 IB:
ibstat | grep -i state          # Active
# 或监控通信时的 IB 流量:
watch -n1 ibstat | grep -i rate

📌 关键点:多节点部署的验收标准 = 吞吐随节点数接近线性增长(2 节点 → 接近 2x)。如果吞吐只涨 30%,大概率是 PP 的 bubble(并发不够)或 NCCL 走了慢网络(6.5 的 NCCL 环境变量)。先确认网络,再调并发。


6. 第 4 步:MoE 的 EP+DP 组合(DeepSeek 类模型)

场景:DeepSeek-V3(671B 总参、37B 激活、256 专家),8 卡。决策树走到”MoE → EP + DP”。

6.1 启动(6.4 的四件套)

vllm serve deepseek-ai/DeepSeek-V3 \
    --tensor-parallel-size 2 \
    --data-parallel-size 4 \
    --enable-expert-parallel \
    --enable-eplb \
    --max-num-seqs 256 \
    --max-model-len 8192

拓扑解读(对照 6.4 第 7 节):

  • EP 自动 = TP×DP = 8:256 个专家分到 8 卡(每卡 32 个)
  • Attention 层:TP=2(4 个 DP 组各自张量并行)
  • EPLB:专家热点自动迁移均衡

6.2 该看到的日志与验证

INFO ... Distributed init succeeded (backend=mp, world_size=8)
INFO ... [moe_utils.py:...] Expert parallel size: 8

专家均衡验证(EP 部署的专属检查):

# 压测时观察每卡利用率
nvidia-smi dmon -s u -c 100
# 预期:8 卡利用率接近(±20% 内)
# 某卡长期 90%+ 其他 40% → 路由热点,检查 EPLB 是否生效

6.3 坑位提示

  • 依赖:高性能 EP 需要 DeepEP/DeepGEMM(6.4 第 7.3 节),不装也能跑但性能差
  • max-num-seqs 要调:MoE 的 prefill 是大矩阵,并发太低显不出 EP 优势
  • 长上下文:长 prefill 下 A2A 通信量大,--all2all-backend 可换 deepep_high_throughput(prefill 优先)

💡 提示:EP 部署的收益验证重点不是”延迟”,而是**“同样的显存下能装下更大的模型 + 更高的吞吐”**。对比基线是 TP-only 配置(无 --enable-expert-parallel),观察吞吐与显存效率的差异——这也是官方文档推荐的对照方式。


7. 全流程检查清单与坑位图

7.1 部署检查清单

决策阶段

  • 决策树走完:确认是”装不下”还是”不够快”
  • 单卡基线已记录(TTFT/TPOT/吞吐,固定压测参数)

单节点阶段

  • --enforce-eager 先跑通功能,再开 CUDA Graph
  • 日志确认 Distributed init succeeded、world_size 正确
  • nvidia-smi 确认显存分布均匀
  • 同参数压测,扩展收益达标(延迟 ÷3、吞吐 ×3~4)

多节点阶段

  • ray status 确认集群(节点数/GPU 数)
  • NCCL 网络配置(NCCL_SOCKET_IFNAME 等)
  • world_size = TP×PP,rank 分布符合拓扑图
  • IB 流量验证、吞吐随节点数线性增长

MoE 阶段

  • Expert parallel size: 8 日志确认 EP 生效
  • 每卡利用率均衡(EPLB 生效)
  • 与 TP-only 配置对比收益

7.2 坑位图(高频故障速查)

启动失败 ──┬─ Ray 没启动/版本不兼容 ──→ ray status / pip show ray
           ├─ GPU 资源不足 ──→ nvidia-smi 检查占用
           └─ 端口冲突 ──→ 换 --port / 检查监听

通信卡死 ──┬─ NCCL 网卡选错 ──→ NCCL_SOCKET_IFNAME
           ├─ 防火墙/安全组 ──→ 节点间端口测试
           └─ 驱动不一致 ──→ 各节点 nvidia-smi 对照

性能不达标 ──┬─ 并发不够 ──→ 调 --max-num-seqs 与压测并发
             ├─ 通信路径错误 ──→ NVLink/IB 利用率检查
             └─ 负载不均 ──→ 每卡利用率对比(EP 场景查 EPLB)

📌 关键点:全流程的核心纪律——每一步只改一个变量:先 eager 跑通(功能)→ 再开图模式(性能)→ 再加并发(饱和)→ 最后调并行参数(扩展)。分布式系统里”一次改三个参数”的调试,等于没调试。


📝 总结

  • 先决策树后命令:装不下 → TP/TP+PP/EP;不够快 → DP
  • 基线先行:固定压测参数记录单卡 TTFT/TPOT/吞吐
  • 单节点 TP--tensor-parallel-size 4,日志看 world_size、显存看均匀
  • 收益验证:延迟 ÷3、吞吐 ×3~4 才算达标;不达标按算力→通信→负载排查
  • 多节点:ray start → ray status → vllm serve(TP=8, PP=2, nnodes=2)
  • MoE:EP 四件套(—enable-expert-parallel + DP + EPLB + max-num-seqs),验证专家均衡
  • 纪律:一步一变量,先功能后性能

🎯 自我检验清单

  • 拿到一台 4×A100 和 70B 模型,写出完整启动命令与验证步骤
  • 从哪些日志/命令确认 TP 真的生效(而不是白加参数)?
  • TP=4 实测只快了 1.5x,按什么顺序排查?
  • 2 节点部署,写出 ray 集群搭建 + vllm 启动的完整命令
  • DeepSeek-V3 8 卡部署,四个参数各管什么?EP size 是多少?
  • “一步一变量”原则在你自己的部署流程里怎么落实?

📚 参考资料