强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

vLLM 高性能推理部署指南 / 09 - 分布式推理

09 - 分布式推理

当单卡显存不足以容纳模型时,分布式推理是唯一的解决方案。本章详解 vLLM 的并行策略。


9.1 分布式推理概述

9.1.1 为什么需要分布式?

模型FP16 权重大小最少 GPU 数(A100 80GB)
7B14 GB1
13B26 GB1
34B68 GB1
70B140 GB2
110B220 GB3
405B810 GB11

注意:以上仅为模型权重的大小,还需要为 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.032 GB/s中等可用但有瓶颈
PCIe 5.064 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(单卡,量化)45120ms95%
TP=27885ms88%
TP=410565ms82%
TP=2 + PP=29290ms78%

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 - 性能调优