3. 负载均衡概念

3.1 负载均衡的定义

在多卡推理系统中,负载均衡(Load Balancing)指的是将推理请求、计算任务和显存资源在多个 GPU 之间进行合理分配,使得各 GPU 的计算负载、显存占用和通信开销尽可能接近,避免出现“忙闲不均”的状态。它不是一个单一的操作,而是一组策略、机制和调度逻辑的集合,贯穿于请求分发、张量并行、流水线并行和显存管理等多个层面。

从系统角度看,负载均衡需要同时关注三个维度的均衡:

  • 计算负载均衡:各 GPU 在单位时间内处理的 token 数、batch 大小或算子执行时间应大致相当,避免某个 GPU 成为计算热点。
  • 显存负载均衡:KV Cache、模型权重、中间激活值在各 GPU 上的占用应均匀,防止单卡显存溢出而其他卡大量空闲。
  • 通信负载均衡:All-to-All、AllReduce 等集合通信产生的数据量在各 GPU 间应均衡,避免某条通信链路成为瓶颈。

下图展示了理想均衡状态与典型不均衡状态的对比:

✅ 理想均衡状态 GPU 0 计算 70% · 显存 65% GPU 1 计算 68% · 显存 66% GPU 2 计算 65% ❌ 典型不均衡状态 GPU 0 计算 95% · 显存 92% GPU 1 计算 45% · 显存 40% GPU 2 计算 8% 负载均衡的目标:让所有 GPU 的工作量接近“理想均衡”状态,而非“忙闲不均”

3.2 负载均衡在多卡推理中的意义

多卡推理的负载均衡直接决定了系统的三个关键指标:吞吐量(Throughput)、延迟(Latency)和资源利用率(Utilization)。在 vLLM 这类高性能推理引擎中,负载均衡的意义可以拆解为以下四个层面:

  1. 提升整体吞吐量:当请求均匀分布时,所有 GPU 可以并行处理各自的任务,系统总吞吐量接近各卡吞吐量之和。若负载不均,整体吞吐量受限于最慢的 GPU(木桶效应),其他 GPU 的算力被白白浪费。
  2. 降低尾延迟(Tail Latency):在分布式推理中,一次请求往往需要多卡协同完成(如张量并行)。如果某张卡负载过高,该卡上的算子执行时间变长,整个请求的完成时间被拉长,表现为 P99 延迟显著恶化。
  3. 避免显存溢出(OOM):KV Cache 是显存消耗的大头。如果请求被不均匀地分配到各卡,某张卡的 KV Cache 可能迅速占满显存,导致 OOM 崩溃,而其他卡仍有大量空闲显存。负载均衡可以最大化利用集群总显存容量。
  4. 降低通信开销:在张量并行(TP)场景下,每层 forward 都需要 AllReduce 同步。如果各卡计算速度不一致,快的卡必须等待慢的卡,造成同步等待开销。均衡负载可以减少这种等待,让通信与计算重叠得更高效。

核心观点:负载均衡不是“平均主义”,而是“让每一张卡都处于其最佳工作区间”。不同 GPU 的算力、显存、NVLink 带宽可能不同,均衡策略需要感知这些差异,做到“按能力分配”。

3.3 常见负载不均衡现象

在实际生产环境中,负载不均衡的表现形式多种多样。以下是 vLLM 多卡部署中最常见的五类现象:

现象类型 典型表现 产生原因 可观测指标
请求分发不均 某卡 GPU 利用率 90%+,另一卡仅 20% 哈希路由策略不当、请求长度差异大 各卡每秒请求数(RPS)
KV Cache 倾斜 某卡显存占用 95%,其他卡 50% 长序列请求集中、cache 管理策略失效 各卡 KV Cache 占用率
流水线气泡 PP 阶段中某 stage 耗时明显高于其他 模型层数分配不均、微批次大小不当 各 stage 耗时占比
通信热点 某条 NVLink 链路带宽打满,其他空闲 TP 组内卡间拓扑不对称 NVLink 带宽利用率
显存碎片化 总显存充足但分配失败 KV Cache 预分配不均、碎片积累 显存碎片率

3.4 案例:一次典型的负载倾斜

假设我们使用 4 张 A100-80G 部署 vLLM,采用 TP=4 的张量并行策略。某次压测中,我们通过 nvidia-smi 和 vLLM 的 metrics 接口观察到以下现象:

# nvidia-smi 输出(简化)
GPU 0: 98%  | 显存 78.2G/80G  | 温度 82°C
GPU 1: 45%  | 显存 41.5G/80G  | 温度 61°C
GPU 2: 52%  | 显存 44.0G/80G  | 温度 63°C
GPU 3: 47%  | 显存 40.8G/80G  | 温度 60°C

# vLLM metrics 片段
vllm:num_requests_running{model="llama2-70b"} 32
vllm:num_requests_waiting{model="llama2-70b"} 156

从输出可以看到,GPU 0 的利用率和显存占用远高于其他三卡。进一步排查发现:

  • 请求路由使用了基于 request_id % num_gpus 的简单哈希,导致长序列请求集中落在 GPU 0 对应的 TP 组内。
  • 由于 TP=4 要求所有卡同步执行,GPU 0 成为瓶颈,其他三卡在大部分时间处于等待状态。
  • 整体吞吐量仅为理论峰值的 40% 左右,P99 延迟从预期的 200ms 恶化到 850ms。

这个案例说明,即使采用了 TP 并行,如果请求分发层没有做好负载均衡,整个系统的性能依然会被单卡拖垮。后续章节我们将介绍如何通过 --load-format、--max-num-seqs 等参数以及自定义调度策略来缓解此类问题。

3.5 误区与复盘

常见误区一:“只要用了 vLLM 的默认调度器,负载就是均衡的。”
实际上,vLLM 默认的连续批处理(Continuous Batching)只负责单卡内的请求调度,跨卡均衡需要依赖上层的路由策略或 Ray 集群调度器。默认配置下,如果请求长度分布极不均匀,依然会出现严重的负载倾斜。

常见误区二:“负载均衡只看 GPU 利用率(SM 占用)就够了。”
利用率高并不代表健康。某张卡可能因为等待通信而显示高利用率(自旋等待),实际计算效率很低。需要同时观察计算时间占比、通信等待时间和显存分配曲线才能准确判断。

复盘建议:在每次压测或上线前,至少记录以下基线数据:各卡 SM 利用率、显存占用、KV Cache 命中率、TP 通信耗时、请求排队长度。将这些数据绘制成时间序列图,可以快速定位负载不均衡的根因。