跳到主要内容

单机多卡

单机多卡指在一台服务器内使用多张 GPU 协同训练或推理 LLM。

它看起来只是“多插几张卡”,实际要同时处理三件事:

  • 模型权重、激活和 KV Cache 如何切分。
  • GPU 之间如何通信。
  • 推理框架如何根据拓扑调度请求。

一句话总结:

单机多卡 = 显存扩容 + 吞吐扩展 + 通信开销管理

如果模型单卡放不下,多卡可以把模型切开;如果模型单卡能放下,多卡也可以用多副本提升吞吐。两种目标不同,对硬件和框架配置的要求也不同。

1. 为什么需要多卡

常见原因有三类。

1.1 单卡显存放不下

大模型推理至少需要放下:

权重显存 + KV Cache 显存 + 运行时 buffer + 冗余空间

例如 70B 级模型即使用 FP16 / BF16 权重,单卡通常也很难完整放下;即使用量化压缩权重,长上下文和高并发还会让 KV Cache 快速增长。

这时多卡主要用于“装下模型”,常用方式是 tensor parallel、pipeline parallel 或两者组合。

1.2 单卡吞吐不够

如果模型单卡能放下,但在线服务 QPS 或 tokens/s 不够,可以启动多个模型副本,让不同 GPU 处理不同请求。

这种方式更接近 data parallel 或多实例部署,优点是简单、稳定、跨卡通信少;缺点是每张卡都要放一份完整模型,显存利用率不一定最高。

1.3 需要更大的 batch 或更长上下文

推理服务的吞吐常常依赖 continuous batching、prefix cache、chunked prefill 等调度能力。

多卡可以提供更多显存给 KV Cache 和运行时调度,但并不保证线性扩展。长上下文场景下,瓶颈可能从权重显存转移到 KV Cache、跨卡通信或调度队列。

2. 常见并行方式

2.1 Tensor Parallel

Tensor parallel,简称 TP,会把同一层里的矩阵计算切到多张 GPU 上。

它的特点是:

  • 每一层都可能发生跨卡通信。
  • 对 GPU 互联带宽和延迟敏感。
  • 适合单卡放不下权重,或者希望把单层计算摊到多张卡上。
  • 在 NVLink / NVSwitch 环境中更容易获得收益。

推理框架里常见配置:

vllm serve /path/to/model --tensor-parallel-size 4

TP 的典型误区是“卡越多越快”。当模型不够大、batch 不够高,或者 GPU 之间只有较弱 PCIe 路径时,TP 通信开销可能抵消计算收益。

2.2 Pipeline Parallel

Pipeline parallel,简称 PP,会按层把模型切成多个 stage,不同 stage 放在不同 GPU 上。

它的特点是:

  • 通信主要发生在相邻 stage 之间。
  • 相比 TP,通信频率通常更低。
  • 会引入流水线气泡。
  • stage 负载不均衡时,慢 stage 会拖住整条流水线。

PP 更适合模型很深、单卡显存不足、且可以接受一定流水线调度开销的场景。推理中是否值得使用 PP,要结合 batch、并发、首 token 延迟和框架支持情况判断。

2.3 Data Parallel / 多副本

Data parallel 在训练中指每张 GPU 保存一份模型副本,处理不同 batch,并在反向传播时同步梯度。

在推理服务中,更常见的是多副本部署:

GPU0: 模型副本 A
GPU1: 模型副本 B
GPU2: 模型副本 C
GPU3: 模型副本 D

它的特点是:

  • 跨卡通信少。
  • 部署和排障简单。
  • 更适合单卡能放下模型的在线推理。
  • 吞吐扩展主要依赖负载均衡和请求调度。

如果模型单卡能放下,优先考虑多副本,通常比强行做 TP 更稳。

2.4 Expert Parallel

Expert parallel 常见于 MoE 模型,会把不同 expert 分布到不同 GPU 上。

它的特点是:

  • token 会被路由到不同 expert。
  • 常见通信模式是 all-to-all。
  • 对互联、路由均衡和 batch 规模敏感。
  • 激活参数少不等于通信开销低。

MoE 部署不能只看“激活参数量”。如果 expert 分散在多张卡上,token dispatch 和 combine 可能成为瓶颈。

3. 显存如何分布

多卡部署时,显存不是简单相加后随便使用。不同并行方式的显存分布不同。

方式权重KV Cache通信开销典型用途
多副本每张卡一份完整模型每个副本独立持有很少单卡能放下模型,扩吞吐
TP权重按张量分片通常按并行策略分布高频 all-reduce / all-gather单卡放不下或需要分摊计算
PP权重按层分片跟随 stage 分布stage 间传激活模型较深、显存不足
EPexpert 分布在多卡取决于框架实现all-to-all 明显MoE 模型

推理显存估算时至少要保守考虑:

  • 权重是否量化。
  • TP / PP 后每张卡的权重分片大小。
  • 最大上下文长度。
  • 最大并发请求数。
  • KV Cache 精度和布局。
  • CUDA graph、workspace、通信 buffer 等运行时开销。

更多显存估算方法可参考 模型占用显存估算显存

4. 多卡通信开销

多卡真正的成本来自通信。

常见通信模式包括:

通信模式说明常见场景
all-reduce多张卡聚合结果后再分发TP、数据并行训练
all-gather收集各卡分片组成完整结果TP、参数分片
reduce-scatter聚合后再按分片分发ZeRO、FSDP
all-to-all每张卡都和其他卡交换不同数据MoE expert parallel
point-to-point两张卡之间直接传递PP stage 间通信

通信开销会影响:

  • TTFT,也就是首 token 延迟。
  • decode 阶段 tokens/s。
  • 高并发下的排队时间。
  • 某些 GPU 利用率高、某些 GPU 等待的负载不均。

如果 GPU 之间只有 PCIe,TP 规模要谨慎扩大;如果是 NVLink / NVSwitch,TP 和混合并行的空间会更大。具体互联差异可参考 GPU互联

5. GPU 拓扑检查

部署前建议先看拓扑。

nvidia-smi topo -m

常见标记大致可以这样理解:

标记含义
NV#GPU 之间通过 NVLink 连接,# 通常表示链路数量或级别
PIX经过同一个 PCIe switch
PXB经过多个 PCIe bridge / switch
PHB经过 PCIe host bridge
SYS跨 NUMA 或跨 CPU socket,距离更远

经验判断:

  • TP group 尽量放在 NV# 或拓扑距离最近的 GPU 上。
  • PP 相邻 stage 尽量放在通信距离近的 GPU 上。
  • 多副本推理更关注每张卡是否均衡、CPU / NUMA / 网卡路径是否合理。
  • 多机训练或跨节点推理还要看 GPU 与网卡的亲和性。

还可以补充查看:

nvidia-smi topo -p2p r
lspci -tv
numactl --hardware

如果机器是双路 CPU,多卡可能分布在不同 socket 后面。跨 socket 通信会增加延迟,也可能影响 GPU 到网卡、GPU 到 NVMe 的路径。

6. 推理框架配置

6.1 vLLM

vLLM 中最常见的是 tensor parallel。

vllm serve /path/to/model \
--tensor-parallel-size 4 \
--max-model-len 32768 \
--gpu-memory-utilization 0.90

常见思路:

  • 单机 4 卡跑一个大模型:--tensor-parallel-size 4
  • 单机 8 卡跑两个副本:启动两个服务进程,每个进程使用 4 张卡。
  • 单卡能放下模型:优先多副本,而不是把 TP 拉大。
  • OOM 时先降低 --max-model-len、并发、--gpu-memory-utilization 或量化权重。

如果需要限制某个进程只看到部分 GPU,可以使用:

CUDA_VISIBLE_DEVICES=0,1,2,3 vllm serve /path/to/model --tensor-parallel-size 4

Windows PowerShell 写法不同:

$env:CUDA_VISIBLE_DEVICES="0,1,2,3"
vllm serve /path/to/model --tensor-parallel-size 4

6.2 TensorRT-LLM

TensorRT-LLM 通常需要在构建 engine 时确定 TP / PP 等并行配置。

简化理解:

构建阶段:确定模型切分方式和 engine
运行阶段:按对应 GPU 数量加载 engine 并启动服务

它适合追求较高性能、部署链路相对固定的生产场景。缺点是构建和调试成本通常高于直接用通用推理服务框架。

6.3 多进程多副本

多副本部署通常靠多个进程或多个容器实现。

示例:

进程 A: CUDA_VISIBLE_DEVICES=0,1  TP=2
进程 B: CUDA_VISIBLE_DEVICES=2,3 TP=2
进程 C: CUDA_VISIBLE_DEVICES=4,5 TP=2
进程 D: CUDA_VISIBLE_DEVICES=6,7 TP=2

前面再放一层 API 网关或负载均衡,把请求分发到不同副本。

这种方式适合:

  • 单机 8 卡,但不想让一个模型实例吃满 8 卡。
  • 需要隔离不同业务或不同模型。
  • 希望滚动升级或灰度发布。

7. 常见部署组合

场景推荐起点说明
7B / 14B 单卡能放下多副本简单稳定,吞吐扩展直接
32B / 70B 单卡放不下TP=2/4/8优先看互联和框架支持
超长上下文服务降低副本数,预留 KV Cache重点控制 max model len 和并发
MoE 模型TP + EP 或框架推荐配置关注 all-to-all 和 expert 负载均衡
低延迟在线服务小 TP 或多副本避免通信过多拉高首 token 延迟
离线批处理更大 batch + 合理 TP以 tokens/s 和成本为主

实践中建议从简单配置开始压测,而不是一开始就堆满所有并行方式。

8. 常见 OOM 问题

8.1 启动就 OOM

可能原因:

  • 权重本身放不下。
  • TP / PP 配置和 GPU 数量不匹配。
  • 量化方式未生效。
  • max_model_len 太大,框架预留了过多 KV Cache。
  • gpu_memory_utilization 设置过高,运行时没有冗余空间。

排查顺序:

  1. 确认实际加载精度和权重大小。
  2. 降低最大上下文长度。
  3. 降低 GPU 显存利用率上限。
  4. 减少并发或 batch。
  5. 再考虑增加 TP 或换更大显存 GPU。

8.2 运行一段时间后 OOM

可能原因:

  • 并发峰值超过预期。
  • 长上下文请求堆积。
  • KV Cache 碎片或调度策略不合适。
  • 多副本之间负载不均。
  • 某些请求没有正确限制输入长度或输出长度。

建议在线服务必须限制:

  • 最大输入 token。
  • 最大输出 token。
  • 最大并发。
  • 单用户或单队列的请求速率。
  • 超长请求的独立队列。

9. 常见性能问题

9.1 多卡比少卡还慢

常见原因:

  • TP 规模过大,通信开销超过计算收益。
  • GPU 拓扑不合理,跨了 SYS 或远端 NUMA。
  • batch 太小,无法摊薄通信成本。
  • 推理框架没有正确识别 P2P 或 NCCL 通信路径。

处理方式:

  • 降低 TP。
  • 改成多副本。
  • 调整 CUDA_VISIBLE_DEVICES 选择更近的 GPU。
  • 用真实业务请求重新压测,而不是只看空载 tokens/s。

9.2 GPU 利用率不均

常见原因:

  • PP stage 切分不均。
  • 某张卡承担了更多 KV Cache 或调度开销。
  • 多副本负载均衡不均。
  • CPU、NUMA 或网络路径导致某些卡等待数据。

排查时同时看:

  • 每张 GPU 的利用率。
  • 每张 GPU 的显存占用。
  • 每个模型副本的请求队列。
  • CPU 利用率和 tokenizer 开销。
  • 拓扑与网卡位置。

9.3 首 token 慢

首 token 延迟主要受 prefill 影响,长 prompt、高并发、TP 通信和队列等待都会放大 TTFT。

可尝试:

  • 控制最大输入长度。
  • 使用 prefix cache。
  • 给长 prompt 单独队列。
  • 减小 TP 或改多副本。
  • 调整 batching 策略。

10. 选型建议

单机多卡选型可以按这个顺序判断:

  1. 模型单卡能不能放下。
  2. 如果能放下,优先多副本扩吞吐。
  3. 如果放不下,先估算需要几张卡切权重。
  4. 检查 GPU 之间是 PCIe、NVLink 还是 NVSwitch。
  5. 根据互联选择 TP / PP / EP。
  6. 用真实上下文长度和并发压测。
  7. 最后再调整框架参数和部署副本数。

不要只按 GPU 数量做决策。4 张强互联 GPU 和 8 张弱互联 GPU,在 TP 场景下可能完全不是一个体验。

11. 总结

单机多卡的核心不是“把卡用满”,而是让并行方式、显存分布和 GPU 拓扑匹配业务目标。

如果目标是吞吐,单卡能放下时优先多副本;如果目标是放下大模型,再考虑 TP、PP 或混合并行;如果是 MoE,还要额外关注 expert 路由和 all-to-all 通信。

最终判断标准应来自压测:

目标模型 + 目标上下文 + 目标并发 + 真实请求分布
-> 显存占用、TTFT、tokens/s、稳定性
-> 决定单机多卡部署方式