vLLM 高性能推理部署指南 / 09 - 分布式推理
09 - 分布式推理
当单卡显存不足以容纳模型时,分布式推理是唯一的解决方案。本章详解 vLLM 的并行策略。
9.1 分布式推理概述
9.1.1 为什么需要分布式?
| 模型 | FP16 权重大小 | 最少 GPU 数(A100 80GB) |
|---|---|---|
| 7B | 14 GB | 1 |
| 13B | 26 GB | 1 |
| 34B | 68 GB | 1 |
| 70B | 140 GB | 2 |
| 110B | 220 GB | 3 |
| 405B | 810 GB | 11 |
注意:以上仅为模型权重的大小,还需要为 KV Cache 和运行时开销预留 20-30% 的显存。
9.1.2 并行策略概览
┌──────────────────────────┐
│ 分布式推理策略 │
└────────────┬─────────────┘
┌─────────────┼─────────────┐
▼ ▼
┌───────────────┐ ┌───────────────┐
│ 张量并行 │ │ 流水线并行 │
│ (Tensor │ │ (Pipeline │
│ Parallelism) │ │ Parallelism) │
│ │ │ │
│ 同一层内的 │ │ 不同层之间的 │
│ 水平切分 │ │ 垂直切分 │
│ │ │ │
│ 单机多卡 │ │ 跨节点 │
│ (高带宽) │ │ (低带宽可) │
└───────────────┘ └───────────────┘
9.2 张量并行(Tensor Parallelism)
9.2.1 原理
张量并行将每一层的权重矩阵水平切分到多个 GPU 上:
线性层 Y = X · W 的张量并行(TP=2):
GPU 0:
W_0 = W[:, :d/2] (左半部分)
Y_0 = X · W_0
GPU 1:
W_1 = W[:, d/2:] (右半部分)
Y_1 = X · W_1
合并: Y = concat(Y_0, Y_1)
或 Y = Y_0 + Y_1(取决于层类型)
9.2.2 Transformer 层的张量并行
Transformer 层结构:
输入 X
│
├─── Self-Attention ────┐
│ ┌──────────────┐ │
│ │ Q, K, V 投影 │ │ ← 按 head 切分到不同 GPU
│ │ (天然可并行) │ │
│ └──────────────┘ │
│ ┌──────────────┐ │
│ │ Attention │ │ ← 每个 GPU 计算自己的 head
│ └──────────────┘ │
│ ┌──────────────┐ │
│ │ Output 投影 │ │ ← AllReduce 合并结果
│ └──────────────┘ │
│ │ │
├─── Add & LayerNorm ───┘
│
├─── Feed-Forward ───────┐
│ ┌──────────────┐ │
│ │ Gate + Up │ │ ← 列并行(各 GPU 独立计算)
│ └──────────────┘ │
│ ┌──────────────┐ │
│ │ Down 投影 │ │ ← 行并行 + AllReduce
│ └──────────────┘ │
│ │ │
└─── Add & LayerNorm ────┘
通信操作: AllReduce(在每个子层之后)
9.2.3 使用张量并行
# 2 卡张量并行
vllm serve Qwen/Qwen2.5-72B-Instruct \
--tensor-parallel-size 2 \
--served-model-name qwen-72b-tp2
# 4 卡张量并行
vllm serve Qwen/Qwen2.5-72B-Instruct \
--tensor-parallel-size 4 \
--served-model-name qwen-72b-tp4
# 8 卡张量并行(单机 8 GPU)
vllm serve meta-llama/Llama-3.1-405B-Instruct \
--tensor-parallel-size 8
# Python API
from vllm import LLM
llm = LLM(
model="Qwen/Qwen2.5-72B-Instruct",
tensor_parallel_size=4, # 使用 4 张 GPU
)
9.2.4 张量并行通信
| GPU 连接方式 | 带宽 | TP 效率 | 适用场景 |
|---|---|---|---|
| NVLink(同机) | 600 GB/s(H100) | 极高 | 强烈推荐 |
| PCIe 4.0 | 32 GB/s | 中等 | 可用但有瓶颈 |
| PCIe 5.0 | 64 GB/s | 较好 | 较新服务器 |
| InfiniBand(跨机) | 400 Gb/s | 高 | 跨节点 TP |
重要:张量并行对通信带宽要求高。强烈推荐使用 NVLink 连接的 GPU 进行张量并行。
9.3 流水线并行(Pipeline Parallelism)
9.3.1 原理
流水线并行将模型的不同层分配到不同 GPU 上:
模型 80 层,PP=4(4 个 pipeline stage):
GPU 0: Layer 0-19 (Stage 0)
│ 输出传给 →
GPU 1: Layer 20-39 (Stage 1)
│ 输出传给 →
GPU 2: Layer 40-59 (Stage 2)
│ 输出传给 →
GPU 3: Layer 60-79 (Stage 3)
数据流:输入 → GPU0 → GPU1 → GPU2 → GPU3 → 输出
9.3.2 流水线调度
微批次流水线(Micro-batch Pipeline):
时间 →
Stage 0: [B1] [B2] [B3] [B4] [B1] [B2] [B3] [B4]
Stage 1: [B1] [B2] [B3] [B4] [B1] [B2] [B3] [B4]
Stage 2: [B1] [B2] [B3] [B4] [B1] [B2] [B3]
Stage 3: [B1] [B2] [B3] [B4] [B1] [B2]
B1-B4: 4 个微批次
各 stage 流水线执行,减少空闲时间
9.3.3 使用流水线并行
# 流水线并行
vllm serve meta-llama/Llama-3.1-405B-Instruct \
--pipeline-parallel-size 4 \
--tensor-parallel-size 2
# 8 GPU: 4 个 pipeline stage × 2 路张量并行
# Python API
llm = LLM(
model="meta-llama/Llama-3.1-405B-Instruct",
pipeline_parallel_size=4,
tensor_parallel_size=2,
)
9.4 张量并行 vs 流水线并行
| 维度 | 张量并行 (TP) | 流水线并行 (PP) |
|---|---|---|
| 切分方式 | 层内水平切分 | 层间垂直切分 |
| 通信频率 | 每层 2 次 AllReduce | 每层 1 次点对点 |
| 通信量 | 大 | 小 |
| 通信延迟敏感 | 非常敏感 | 较不敏感 |
| GPU 利用率 | 高 | 有气泡(bubble) |
| 推荐连接 | NVLink(必须) | PCIe/InfiniBand |
| 典型规模 | 2-8 GPU(单机) | 跨多节点 |
| 推荐场景 | 首选 | 超大模型 / 跨节点 |
9.4.1 混合并行策略
大模型最优策略:TP + PP 混合
示例:405B 模型,16 GPU 集群(2 节点 × 8 GPU)
配置:
- TP = 8(节点内,利用 NVLink)
- PP = 2(节点间,利用 InfiniBand)
节点 0 (GPU 0-7): Layer 0-79 (TP=8)
节点 1 (GPU 8-15): Layer 80-159 (TP=8)
命令:
vllm serve meta-llama/Llama-3.1-405B-Instruct \
--tensor-parallel-size 8 \
--pipeline-parallel-size 2
9.5 多节点部署
9.5.1 使用 Ray 进行多节点调度
vLLM 使用 Ray 框架进行分布式协调:
# 节点 1(Head 节点)
ray start --head --port=6379
# 节点 2(Worker 节点)
ray start --address="node1:6379"
# 在 Head 节点上启动 vLLM
vllm serve meta-llama/Llama-3.1-405B-Instruct \
--tensor-parallel-size 8 \
--pipeline-parallel-size 2 \
--distributed-executor-backend ray
9.5.2 Ray 集群配置
# cluster.yaml
cluster_name: vllm-cluster
provider:
type: aws # 或 gcp, azure, local
region: us-east-1
auth:
ssh_user: ubuntu
head_node:
InstanceType: p4d.24xlarge # 8x A100 80GB
ImageId: ami-xxxxxxxxx
worker_nodes:
InstanceType: p4d.24xlarge
ImageId: ami-xxxxxxxxx
min_workers: 1
max_workers: 3
setup_commands:
- pip install vllm ray[default]
head_start_ray_commands:
- ray start --head --port=6379
worker_start_ray_commands:
- ray start --address=$RAY_HEAD_IP:6379
9.5.3 多节点环境变量
# 所有节点都需要设置
# NCCL 配置(GPU 通信库)
export NCCL_IB_DISABLE=0 # 启用 InfiniBand
export NCCL_IB_HCA=mlx5_0 # InfiniBand 网卡
export NCCL_SOCKET_IFNAME=eth0 # 网络接口
export NCCL_DEBUG=INFO # 调试信息
# 网络配置
export GLOO_SOCKET_IFNAME=eth0 # Gloo 通信接口
# Ray 配置
export RAY_ADDRESS=node1:6379
9.6 通信优化
9.6.1 NCCL 通信优化
# InfiniBand 优化
export NCCL_IB_GID_INDEX=3
export NCCL_IB_TC=136
export NCCL_IB_SL=5
export NCCL_IB_TIMEOUT=22
# 共享内存优化
export NCCL_SHM_DISABLE=0
export NCCL_P2P_LEVEL=NVL # NVLink P2P
# 网络拓扑
export NCCL_TOPO_FILE=/etc/nccl/topo.xml
9.6.2 通信量估算
张量并行通信量(per token per layer):
AllReduce:
通信量 = 2 × hidden_size × dtype_size
LLaMA-70B: 2 × 8192 × 2 = 32 KB per token per layer
总通信量(per token per step):
= 2 × num_layers × hidden_size × dtype_size
= 2 × 80 × 8192 × 2 = 2.5 MB per token
对于 TP=4, batch_size=32:
每步通信量 = 2.5 MB × 32 tokens = 80 MB
NVLink 600 GB/s → 通信时间 ≈ 0.13 ms
PCIe 32 GB/s → 通信时间 ≈ 2.5 ms
9.7 大模型部署实战
9.7.1 LLaMA-3.1 70B(单机 4 GPU)
# 4x A100 80GB,TP=4
vllm serve meta-llama/Llama-3.1-70B-Instruct \
--tensor-parallel-size 4 \
--max-model-len 8192 \
--gpu-memory-utilization 0.9 \
--enable-prefix-caching \
--served-model-name llama-70b
9.7.2 LLaMA-3.1 405B(双节点 16 GPU)
# 2 个节点,每个 8x A100 80GB
# 节点 1(Head)
ray start --head --port=6379
vllm serve meta-llama/Llama-3.1-405B-Instruct \
--tensor-parallel-size 8 \
--pipeline-parallel-size 2 \
--max-model-len 4096 \
--gpu-memory-utilization 0.9 \
--distributed-executor-backend ray \
--served-model-name llama-405b
9.7.3 DeepSeek-V2(MoE 模型)
# DeepSeek-V2 236B(MoE,激活参数 21B)
vllm serve deepseek-ai/DeepSeek-V2-Chat \
--tensor-parallel-size 4 \
--max-model-len 4096 \
--trust-remote-code
9.8 性能对比
9.8.1 不同并行配置的性能
以 LLaMA-70B 为例,4x A100 80GB:
| 配置 | 吞吐量 (tok/s) | 延迟 (TTFT) | 显存效率 |
|---|---|---|---|
| TP=1(单卡,量化) | 45 | 120ms | 95% |
| TP=2 | 78 | 85ms | 88% |
| TP=4 | 105 | 65ms | 82% |
| TP=2 + PP=2 | 92 | 90ms | 78% |
TTFT:Time to First Token,首 token 延迟。
9.9 注意事项
GPU 通信:张量并行的性能严重依赖 GPU 间通信带宽。跨 PCIe 的 TP=2 可能不如单卡快。
PP 气泡:流水线并行存在 pipeline bubble(空闲期),batch size 越大 bubble 影响越小。
模型兼容性:不是所有模型都支持 PP。确认模型的层结构可以均匀分配到各 stage。
故障恢复:分布式部署中,单个 GPU 故障会导致整个服务不可用。建议配置健康检查和自动重启。
NVLink 拓扑:某些服务器的 NVLink 拓扑不是全连接的。使用
nvidia-smi topo -m检查。
9.10 扩展阅读
上一章:08 - 调度与批处理策略 | 下一章:10 - 性能调优