先说结论:什么时候用哪种并行
| 规模 | 推荐并行 | 原因 |
|---|---|---|
| < 30B | 单卡 | A100-80G / H100 单卡足够 |
| 30-80B | TP=2 或 4 | 量化后常常也能单卡,不必并行 |
| 70-180B FP16 | TP=4 或 8 | NVLink 内通信快,延迟友好 |
| 405B+ | TP=8 + PP=2(跨节点) | 单节点装不下,必须跨机 |
| MoE 大模型 | TP + Expert Parallel | 专家独立切到不同卡,见第 10 章 |
张量并行(Tensor Parallelism,TP)
每层的大矩阵乘法,把权重按列切到 N 张卡,每张卡只存一部分、只算一部分,最后 all-reduce 聚合输出。
原始 Linear: Y = X @ W (W: [d, d]) TP=2 切列: GPU0: W_0 = W[:, :d/2] → Y_0 = X @ W_0 (Y_0: [B, d/2]) GPU1: W_1 = W[:, d/2:] → Y_1 = X @ W_1 (Y_1: [B, d/2]) concat(Y_0, Y_1) = Y ← 每层末端 all-gather 或 all-reduce Attention 的 Q/K/V:按 head 切 32 头 → TP=4 → 每卡 8 头 attention 内部独立算,末端再聚合
vLLM 启动:
vllm serve meta-llama/Llama-3-70B-Instruct \
--tensor-parallel-size 4 \
--dtype bfloat16
没别的参数,vLLM 自动识别哪些层要切、哪里插 all-reduce。Llama-3-70B 在 4×A100-80G 上 TP=4,bf16 能直接跑,每卡占 ~35GB 模型 + KV。
TP 的通信代价
每层 forward 会触发一次 all-reduce(或 all-gather),尺寸 = batch × hidden_size × dtype。Llama-70B hidden=8192,batch=16,bf16:
单次 all-reduce: 16 × 8192 × 2 = 262KB 每 forward 层数: 80 层 × 2(attn + mlp) = 160 次 每 forward 总通信: 160 × 262KB = 42MB NVLink 4.0(600GB/s):42MB / 600GB/s = 0.07ms PCIe 4.0 (32GB/s): 42MB / 32GB/s = 1.3ms ← 20× 慢
没 NVLink 不要做 TP
如果你的服务器是 4 张 A100 通过 PCIe 连(没 NVSwitch),TP=4 会被通信严重拖累,单 forward 可能增加 100+ ms。这种机器要么单卡放量化模型,要么用 PP(流水并行通信代价低得多)。
如果你的服务器是 4 张 A100 通过 PCIe 连(没 NVSwitch),TP=4 会被通信严重拖累,单 forward 可能增加 100+ ms。这种机器要么单卡放量化模型,要么用 PP(流水并行通信代价低得多)。
查拓扑:nvidia-smi topo -m
nvidia-smi topo -m # 正确的 DGX 机器输出 GPU0 GPU1 GPU2 GPU3 GPU4 GPU5 GPU6 GPU7 GPU0 X NV12 NV12 NV12 NV12 NV12 NV12 NV12 GPU1 NV12 X NV12 NV12 ... # NV12 = NVLink 12 lanes,NVSwitch 全连通 # 有问题的机器 GPU0 GPU1 GPU2 GPU3 GPU0 X NV2 PHB PHB GPU1 NV2 X PHB PHB GPU2 PHB PHB X NV2 GPU3 PHB PHB NV2 X # PHB = 走 PCIe Host Bridge,通信慢 # 这种机器 TP=4 跨组会很慢,TP=2 在组内才有意义
看到全 NV# 就放心大胆 TP。看到 PHB / SYS,TP 的卡数要限制在同一 NVLink 域内。
流水并行(Pipeline Parallelism,PP)
把模型的不同层放在不同卡,数据像水流一样过:
Llama-3-70B,80 层,PP=4: GPU0: 层 0-19 GPU1: 层 20-39 GPU2: 层 40-59 GPU3: 层 60-79 Forward: GPU0 算完前 20 层 → activations 发给 GPU1 GPU1 算完 20-39 → 发给 GPU2 ... 通信:每 stage 边界传一次 activation 大小:batch × seq_len × hidden_size 次数:PP-1 次 比 TP 少几十倍
vLLM 启动:
vllm serve meta-llama/Llama-3-70B-Instruct \ --tensor-parallel-size 1 \ --pipeline-parallel-size 4
PP 通信少、能跨节点,但延迟高——输出第一个 token 要走完所有 stage,比单卡慢很多。PP 适合吞吐型、大 batch场景。
TP 和 PP 的组合
Llama-3.1-405B 在 H100 上的典型切法:
1 节点 8×H100: TP=8,FP8 量化 → 装得下,延迟友好 2 节点 16×H100: TP=8 + PP=2 → FP16 都能跑 4 节点 32×H100: TP=8 + PP=4 → 高吞吐生产
vllm serve meta-llama/Llama-3.1-405B-Instruct-FP8 \ --tensor-parallel-size 8 \ --pipeline-parallel-size 2 \ --quantization fp8 \ --distributed-executor-backend ray
黄金法则
TP 限制在节点内(走 NVLink / NVSwitch),PP 跨节点(走 InfiniBand / 以太网)。反过来——TP 跨节点——通信量直接把推理拖成 PPT。
TP 限制在节点内(走 NVLink / NVSwitch),PP 跨节点(走 InfiniBand / 以太网)。反过来——TP 跨节点——通信量直接把推理拖成 PPT。
多节点部署:Ray 集群
单机 vLLM 默认用 mp (multiprocess) 后端。跨节点要用 Ray:
# head 节点 ray start --head --port=6379 # worker 节点 ray start --address="head-node-ip:6379" # 启动 vLLM(在 head 节点) vllm serve meta-llama/Llama-3.1-405B-Instruct \ --tensor-parallel-size 8 \ --pipeline-parallel-size 2 \ --distributed-executor-backend ray
vLLM 会自动把 placement groups 分配到各节点,确保 TP 组内走 NVLink,PP 跨节点通信。
NCCL 常见问题
| 报错 | 原因 | 修复 |
|---|---|---|
NCCL timeout | 某张卡卡死,其他卡等它 | export NCCL_TIMEOUT=1800 临时救急,根治要查挂死原因 |
unhandled system error | Docker 没加 --ipc=host | 加上,或 --shm-size 32g |
| 跨节点极慢 | 走以太网没走 IB | NCCL_IB_DISABLE=0,NCCL_SOCKET_IFNAME=ib0 |
topo ERROR | GPU 不在同一 PCIe root | 调整 CUDA_VISIBLE_DEVICES 让 TP 组内卡在一起 |
| P2P 不可用 | 部分云厂商虚拟化限制 | NCCL_P2P_DISABLE=1(会慢,但能跑) |
调参速查
--tensor-parallel-size / -tp
TP 度数,需要整除模型 head 数。Llama 32 头 → TP 可为 1/2/4/8/16/32。
--pipeline-parallel-size / -pp
PP 度数,需要整除模型层数(或至少让每 stage 拿到整数层)。
--distributed-executor-backend
mp(单节点)/ ray(多节点)。跨节点必须 ray。NCCL_P2P_LEVEL=NVL
强制 NCCL 只在 NVLink 组内做 P2P。没 NVLink 会失败——反过来检测配置对不对。
VLLM_WORKER_MULTIPROC_METHOD=spawn
部分容器环境 fork 有问题,切 spawn。
TP 度数对吞吐的影响
Llama-3-70B 在 8×A100-80G NVSwitch 机器上,相同 QPS(30):
| 并行方案 | 单 token 延迟 | 吞吐 tok/s | 每请求显存 |
|---|---|---|---|
| TP=2, 4 副本 | 13ms | 4200 | 吃 2 张卡 KV |
| TP=4, 2 副本 | 10ms | 5800 | KV 分 4 张卡,更多并发 |
| TP=8, 1 副本 | 8ms | 4900 | all-reduce 成本占比上升 |
TP 不是越大越好——超过一定度数,通信占比压过计算。70B 在 NVSwitch 机器上 TP=4 是甜点,再大就开始亏。
本章小结
- TP 切列、按 head 分到多卡,每层 all-reduce 一次——适合节点内 NVLink
- PP 按层切、activations 流过去,通信少但延迟高——适合跨节点
- 大模型典型切法:单节点 TP=8,跨节点 TP=8 + PP=2
- 拓扑决定性能:
nvidia-smi topo -m看清 NVLink 还是 PCIe - vLLM 只暴露
--tensor-parallel-size/--pipeline-parallel-size,跨节点加--distributed-executor-backend ray - TP 度数选 head 整除值,PP 度数选层整除值,超过甜点点反而变慢