在配备 4 × RTX 4090 / 96 GB 总显存的工作站上运行 vLLM 0.4 服务 Llama-3-70B,nvidia-smi 显示 GPU 0 显存占用 24 GB(满载),其他三张卡显存占用 0 GB,生成速度只有单卡 70B 的水平。同样的问题在 llama.cpp 中也会出现:--n-gpu-layers 99 把所有层放到 GPU,但只有卡 0 被使用。这是因为多 GPU 分布需要显式配置张量并行(tensor parallel)或层分割(layer split),不会自动发生。
常见原因
1. vLLM 未设置 —tensor-parallel-size
vLLM 默认 --tensor-parallel-size 1,即只使用单 GPU。若不显式设置为 GPU 数量,服务只会使用第一张可见的 GPU,其余 GPU 完全空闲。
怎么判断:查看 vLLM 启动命令中是否有 --tensor-parallel-size;nvidia-smi 显示只有 GPU 0 有显存占用。
2. llama.cpp 未设置 —tensor-split 或使用了错误比例
llama.cpp 的多 GPU 分布通过 --tensor-split 参数控制,格式为各 GPU 的权重比例(如 1,1,1,1 表示均分到 4 卡)。不设置此参数时,所有层默认堆到 GPU 0(若 GPU 0 装不下,才会溢出到 CPU,而不是分布到其他 GPU)。
怎么判断:检查 llama.cpp 启动命令是否包含 --tensor-split;nvidia-smi 查看各卡显存分配。
3. CUDA_VISIBLE_DEVICES 只暴露了单个 GPU
环境中设置了 CUDA_VISIBLE_DEVICES=0,使应用只看到一块 GPU,即使物理上有 4 块。这在 conda 环境、Docker 容器或 CI 脚本中很常见。
怎么判断:echo $CUDA_VISIBLE_DEVICES;若输出 0 或任意单个数字,说明只有一块 GPU 可见。
4. Ollama 对多 GPU 的支持依赖 NCCL,但 NCCL 未正确安装
Ollama 0.4 的多 GPU 推理需要 NCCL(NVIDIA Collective Communications Library)支持。若系统没有安装 NCCL 或版本不兼容,Ollama 会静默回退到单 GPU 模式。
怎么判断:ollama serve 日志中搜索 nccl;ldconfig -p | grep nccl 检查 NCCL 是否已安装;若 Ollama 版本低于 0.3,可能不支持多 GPU。
5. GPU 间没有 NVLink,PCIe 带宽成为瓶颈导致分布性能反而变差
没有 NVLink 的多 GPU 配置(消费级 RTX 系列通常没有 NVLink)下,张量并行需要通过 PCIe 总线在 GPU 间传输激活值,对于 70B 模型每层前向传播需要约 30-50 MB 的通信量,PCIe x16 的带宽(16 GB/s)会成为瓶颈,导致实际吞吐量低于单 GPU。
怎么判断:nvidia-smi topo -m 查看 GPU 间拓扑,NV4/NV6/NV18 表示有 NVLink,PIX/PXB/PHB 表示只有 PCIe。若是 PCIe 连接,考虑使用 pipeline parallel 而非 tensor parallel。
6. 模型架构不支持张量并行
某些特殊架构(如 MoE 的 expert 层)对张量并行的支持有限。vLLM 和 llama.cpp 会在这类层上回退到单 GPU 处理,导致实际并行效率远低于预期。
怎么判断:检查 vLLM 日志中是否有 fallback to single GPU for layer 相关警告;对比多 GPU 和单 GPU 的实际吞吐量,若多 GPU 只快了 20-30%(而不是预期的接近线性加速),说明存在回退。
最短修复路径
Step 1:vLLM 明确设置 tensor parallel size
# 启动 4 GPU tensor parallel 服务
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Meta-Llama-3-70B-Instruct \
--tensor-parallel-size 4 \
--gpu-memory-utilization 0.90 \
--max-model-len 32768 \
--host 0.0.0.0 \
--port 8000
# 验证各卡显存占用
watch -n2 'nvidia-smi --query-gpu=index,memory.used --format=csv,noheader'
# 期望:4 张卡各占约 20 GB(70B Q8 需要约 80 GB 总显存)
Step 2:llama.cpp 配置 tensor-split
# 均分到 4 张 RTX 4090(各 24 GB)
./llama-server \
-m llama-3-70b-Q4_K_M.gguf \
--tensor-split 1,1,1,1 \
-ngl 999 \
--ctx-size 8192 \
--host 0.0.0.0 \
--port 8080
# 若 4 张卡显存不等(如 24GB + 24GB + 16GB + 16GB),按比例分配
./llama-server -m model.gguf --tensor-split 3,3,2,2 -ngl 999
# 验证多卡均在使用
nvidia-smi --query-gpu=index,utilization.gpu,memory.used --format=csv -l 2
Step 3:确保所有 GPU 对应用可见
# 设置所有 GPU 可见
export CUDA_VISIBLE_DEVICES=0,1,2,3
# 或使用 all 关键字
export CUDA_VISIBLE_DEVICES=all
# Docker 容器内
docker run --gpus all ...
# 或指定特定 GPU
docker run --gpus '"device=0,1,2,3"' ...
Step 4:Ollama 多 GPU 配置
# Ollama 0.4+ 会自动检测并使用所有可见 GPU
# 确保 CUDA_VISIBLE_DEVICES 未被限制
unset CUDA_VISIBLE_DEVICES
# 查看 Ollama 探测到的 GPU
OLLAMA_DEBUG=1 ollama serve 2>&1 | grep -i 'gpu\|cuda\|nccl'
# 期望看到类似:
# msg="inference compute" id=GPU-0 ... name="NVIDIA GeForce RTX 4090"
# msg="inference compute" id=GPU-1 ... name="NVIDIA GeForce RTX 4090"
# msg="inference compute" id=GPU-2 ... name="NVIDIA GeForce RTX 4090"
# msg="inference compute" id=GPU-3 ... name="NVIDIA GeForce RTX 4090"
Step 5:没有 NVLink 时改用 pipeline parallel(vLLM)
# 对于无 NVLink 的 PCIe 连接多 GPU,pipeline parallel 更合适
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Meta-Llama-3-70B-Instruct \
--pipeline-parallel-size 4 \
--gpu-memory-utilization 0.90 \
--host 0.0.0.0 \
--port 8000
# pipeline parallel 将不同层分配到不同 GPU
# 延迟比 tensor parallel 略高,但吞吐量在无 NVLink 时通常更好
预防建议
- 部署脚本中始终显式设置
--tensor-parallel-size或--tensor-split,不依赖自动推断。 - 启动后第一件事是运行
nvidia-smi验证各卡显存分配是否符合预期。 - 生产环境配置 Prometheus + nvidia-smi exporter 监控各 GPU 利用率,快速发现单卡过载。
nvidia-smi topo -m是判断多 GPU 配置最优策略的基础,NVLink 用 tensor parallel,PCIe 用 pipeline parallel。- 对于 4 × 24 GB 卡(96 GB 总显存),70B Q4_K_M(40 GB)完全可以装入单个大 GPU(如 A100 80GB)并获得更好的延迟;如果有 A100 可选,不一定要分布到多卡。
- 在 Docker 容器中运行时,确保
--gpus all而不是--gpus '"device=0"',很多问题来自容器只暴露了单卡。
常见问答 (FAQ)
Q: 4 × RTX 4090 的多 GPU tensor parallel 比单 A100 80GB 快吗? A: 取决于任务类型。吞吐量(tokens/s,高并发场景)4 × RTX 4090 通常更高;但单请求延迟(首 token 延迟)因为 PCIe 通信开销,不一定比单 A100 快。对于 TTFT 敏感的交互式场景,A100 可能更合适。
Q: Ollama 支持 pipeline parallel 吗? A: Ollama 0.4 主要实现了 tensor parallel(层内并行),pipeline parallel 支持有限。对于需要精确控制并行策略的生产场景,推荐使用 vLLM,灵活性更高。
Q: 两张不同型号的 GPU(如 RTX 4090 + RTX 3090)能做 tensor parallel 吗?
A: 可以,但需要调整 --tensor-split 比例匹配实际显存大小(24:24 vs 24:10 等)。混合型号会受到最慢 GPU 的性能限制(木桶效应),实际效果通常不理想。建议使用相同型号的 GPU。
Q: 多 GPU 运行时某一张卡出故障,会影响其他卡吗?
A: 是的,tensor parallel 和 pipeline parallel 都是紧耦合的,任何一张卡故障会导致整个推理进程崩溃。需要重启服务并在排除故障卡后重新配置(如将 --tensor-parallel-size 从 4 改为 3)。
相关阅读
- vLLM 报 context length exceeded
- vLLM 启动报 CUDA 版本不匹配
- Ollama 探测不到 GPU,全跑在 CPU
- LM Studio 加载模型时显存 OOM
- 本地模型冷启动后首 token 极慢
标签: #local-llm #vllm #排查