多卡并行策略:张量并行、流水线并行、数据并行及其显存影响

核心原理:三种并行策略的切分维度

多卡部署大模型时,显存碎片治理不能脱离并行策略单独讨论。不同的并行方式决定了每张卡上张量的形状、生命周期和通信模式,进而直接影响显存分配与释放的粒度。理解三种基本并行策略的切分维度,是分析碎片问题的前提。

  • 数据并行(Data Parallelism, DP):将训练批次按卡数切分,每张卡持有完整的模型副本。梯度在反向传播后通过 AllReduce 聚合。显存中主要存在的是完整参数、梯度和优化器状态,各卡完全相同。
  • 张量并行(Tensor Parallelism, TP):将单个 Transformer 层的权重矩阵按行或列切分到多张卡上。每张卡只持有权重的一部分,但需要在前向/反向过程中通过 AllGather 和 ReduceScatter 通信来拼接中间结果。显存中保存的是分片权重和完整的激活值(或激活值分片)。
  • 流水线并行(Pipeline Parallelism, PP):按层切分模型,将不同层分配到不同卡上。每张卡只负责若干层的计算,中间激活值通过点对点通信传递。显存中保存的是本卡负责的层参数,以及流水线中暂存的微批次激活。

三种策略可以组合使用(如 3D 并行),但组合后显存分配模式会叠加,碎片风险也随之上升。下图展示了三种并行策略在 4 卡场景下的显存分布逻辑。

三种并行策略的显存分布逻辑(4卡示例) 数据并行 (DP) 卡0 卡1 卡2 卡3 每卡持有完整模型副本 梯度 AllReduce 聚合 张量并行 (TP) W 分片0 卡0 W 分片1 卡1 W 分片2 卡2 W 分片3 卡3 激活值 AllGather / ReduceScatter 通信 流水线并行 (PP) 层0-1 卡0 层2-3 卡1 层4-5 卡2 层6-7 卡3 点对点激活传递(FWD/BWD) 显存影响对比 维度 数据并行 张量并行 流水线并行 权重显存 完整副本 × 卡数 1/TP 大小 × 卡数 1/PP 层数 × 卡数 激活显存 完整激活(每卡) 分片或完整(需通信) 仅本卡层激活 碎片风险 低(分配规整) 中(通信缓冲频繁) 高(微批次切换) 通信模式 AllReduce(梯度) AllGather/ReduceScatter P2P(点对点)

方法流程:并行策略选择与显存配置

在实际部署中,选择并行策略需要结合模型规模、卡间带宽和显存容量。以下是推荐的决策流程:

  1. 评估单卡显存容量:计算模型权重、梯度、优化器状态和激活值所需的总显存。若单卡可容纳,优先使用数据并行,碎片风险最低。
  2. 判断是否启用张量并行:当单卡放不下完整模型时,优先考虑张量并行。TP 将权重切分到多卡,但需要高带宽的卡间通信(如 NVLink)。TP 的通信频率极高,每层前向/反向都要进行 AllGather 和 ReduceScatter,因此 TP 通常限制在单机内部。
  3. 引入流水线并行:当模型层数过多或 TP 规模受限时,使用 PP 按层切分。PP 通信量较小(仅传递激活值),但会产生流水线气泡(bubble),降低计算效率。PP 适合跨机部署。
  4. 组合并行策略:大模型通常采用 3D 并行(DP + TP + PP)。例如,8 卡场景可配置为 DP=2, TP=4, PP=1,或 DP=1, TP=4, PP=2。组合时需注意各并行维度的显存叠加效应。

在 vLLM 中,并行策略通过 --tensor-parallel-size 和 --pipeline-parallel-size 参数控制。数据并行在 vLLM 中通常由推理引擎自动处理(通过复制模型副本实现)。

# 示例:4卡张量并行启动 vLLM
python -m vllm.entrypoints.openai.api_server \
    --model meta-llama/Llama-3-8B-Instruct \
    --tensor-parallel-size 4 \
    --gpu-memory-utilization 0.90 \
    --max-num-seqs 32

# 示例:2路张量并行 + 2路流水线并行
python -m vllm.entrypoints.openai.api_server \
    --model meta-llama/Llama-3-70B-Instruct \
    --tensor-parallel-size 2 \
    --pipeline-parallel-size 2 \
    --gpu-memory-utilization 0.85

案例场景:Llama-3-70B 在 8×A100 上的显存分配

以 Llama-3-70B 为例,模型权重约 140GB(FP16)。单张 A100(80GB)无法容纳,必须使用多卡并行。假设采用 TP=4, PP=2 的配置:

并行维度 配置 每卡权重显存 每卡激活显存(估算) 碎片风险点
张量并行 TP=4 140GB / 4 = 35GB 约 8-12GB(取决于序列长度) 通信缓冲区的反复分配
流水线并行 PP=2 35GB / 2 ≈ 17.5GB 约 4-6GB(仅本卡层) 微批次切换时的激活释放
KV Cache — — 动态分配,可达 30-40GB 高碎片风险区域

在该配置下,每张卡的总显存占用约为 17.5GB(权重)+ 5GB(激活)+ 35GB(KV Cache)+ 通信缓冲 ≈ 60GB,剩余约 20GB 作为余量。KV Cache 的显存分配是碎片治理的重点——vLLM 通过 PagedAttention 将 KV Cache 划分为固定大小的块(block),每个 block 默认 16 个 token 的 KV 数据。这种分块机制显著减少了碎片,但块大小的选择会影响碎片率:块过小则管理开销大,块过大则内部碎片增多。

实践建议:在 vLLM 中,可通过 --block-size 参数调整 KV Cache 块大小(默认 16)。对于长序列场景,适当增大块大小(如 32)可减少块数量,降低管理开销;对于短序列高并发场景,保持默认或减小块大小可减少内部碎片。

误区与复盘:并行策略中的显存碎片陷阱

在实际部署中,以下误区容易导致显存碎片加剧或性能下降:

  • 误区一:TP 规模越大越好。TP 虽然能减少每卡权重显存,但通信开销随 TP 规模线性增长。当 TP=8 时,每层前向需要 8 次 AllGather,通信等待时间可能超过计算时间。此外,TP 的通信缓冲区(用于暂存分片数据)在每次迭代中反复分配释放,容易产生碎片。建议 TP 不超过单机 GPU 数量,且优先使用 NVLink 互联。
  • 误区二:忽略 PP 的微批次调度。PP 将训练批次拆分为多个微批次(micro-batch),逐层流水线执行。微批次切换时,前一微批次的激活值被释放,后一微批次的激活值被分配,这种高频分配/释放模式会在显存中留下大量不连续的空洞。若 PP 的微批次数量设置不当(如过多),碎片率会显著上升。
  • 误区三:KV Cache 与并行策略脱节。在 TP 场景下,KV Cache 通常按 TP 维度切分,每张卡只保存部分注意力头的 KV 数据。若 KV Cache 的块分配未与 TP 切分对齐,可能导致跨卡访问,增加通信开销并加剧碎片。vLLM 的 PagedAttention 已支持 TP 场景下的 KV Cache 分片,但需确保 --tensor-parallel-size 与注意力头数匹配(即头数能被 TP 整除)。
复盘案例:某团队在 8×A100 上部署 Llama-3-70B,初始配置 TP=8, PP=1。运行后发现显存碎片率高达 25%,且吞吐量低于预期。分析发现:TP=8 导致通信缓冲区频繁分配,且 KV Cache 块大小为默认 16,但实际序列长度集中在 2000-4000 token,块数量过多。优化方案:改为 TP=4, PP=2,并将 --block-size 调整为 32。调整后碎片率降至 8%,吞吐量提升 35%。

复盘要点:并行策略的选择直接影响显存分配模式。TP 减少权重显存但增加通信缓冲碎片;PP 减少激活显存但引入微批次切换碎片;DP 显存分配最规整但需要完整模型副本。实际部署中应结合模型规模、卡间拓扑和序列长度分布,综合权衡并行维度与 KV Cache 块大小,才能有效控制显存碎片,提升多卡推理性能。