Ollama 多显卡使用笔记:显存叠加、GPU 选择和常见误区

整理 Ollama 多显卡使用中的关键信息:什么时候会跨 GPU 加载模型、如何用 CUDA_VISIBLE_DEVICES / ROCR_VISIBLE_DEVICES 限制显卡、显存是否能叠加、不同 GPU 能不能混用,以及 Docker、PCIe 带宽和性能方面的常见误区。

折腾 Ollama 本地推理时,经常会遇到类似问题:我现在有一张显卡,主板还有空 PCIe 槽,再加几张 GPU 对 Ollama 有帮助吗?多显卡是否必须同型号?显存能不能叠加?会不会像训练框架那样多卡并行加速?

这篇整理一下 Ollama 多显卡的实际行为。重点先说结论:

  • Ollama 支持多 GPU。
  • 多 GPU 最大价值通常是让更大的模型放进总显存,而不是线性提升 token/s。
  • 默认策略下,如果模型能完整放进某一张 GPU,Ollama 倾向于放在单卡上。
  • 如果模型无法完整放进单张 GPU,Ollama 会把模型分布到可用 GPU 上。
  • 不同型号 GPU 可以被 Ollama 看到并使用,但性能和分配效果不一定理想。
  • 不需要 SLI / NVLink 才能用多卡。
  • 想限制 Ollama 使用哪些 GPU,需要用 CUDA_VISIBLE_DEVICESROCR_VISIBLE_DEVICESGGML_VK_VISIBLE_DEVICES

官方行为:先单卡,放不下再多卡

Ollama FAQ 里对多 GPU 加载逻辑说得比较直接:加载新模型时,Ollama 会估算模型所需 VRAM,并和当前可用显存比较。如果模型能完整放进某一张 GPU,它会加载到那张 GPU 上;如果单张 GPU 放不下,才会分布到所有可用 GPU 上。

这个策略的原因是性能。单卡加载通常能减少推理时跨 PCIe 总线的数据传输,因此往往更快。

所以不要把 Ollama 的多 GPU 理解成“有几张卡就自动几倍加速”。更准确的理解是:

  • 小模型能进单卡:通常单卡跑。
  • 大模型单卡放不下:跨多卡分层加载。
  • 显存仍不够:一部分会落到系统内存,速度会明显下降。

可以用下面命令确认模型到底加载到了哪里:

1
ollama ps

输出里的 PROCESSOR 会显示类似:

1
2
3
100% GPU
48%/52% CPU/GPU
100% CPU

如果看到 48%/52% CPU/GPU,说明已经有一部分在系统内存里了。此时多加 GPU 或换更大显存的卡,通常比继续依赖 CPU/RAM 更有意义。

多 GPU 不是简单叠算力

本地大模型推理和游戏里的 SLI 不是一回事。Ollama 多卡时,更常见的是把模型的不同层或张量放到不同设备上。这样可以用多张卡的显存装下更大的模型,但推理过程中仍然可能需要设备之间传递数据。

因此,多 GPU 带来的收益通常分两种:

  • 显存收益:更容易装下大模型,或者避免落到 CPU/RAM。
  • 性能收益:只有在原本单卡装不下或严重混 CPU 时,提升才会很明显。

如果一个 8B 或 14B 模型本来就能完整放进单张 3090,强行拆到两张卡不一定更快,甚至可能因为跨卡传输变慢。Ollama 官方默认“能单卡就单卡”的策略,就是为了避免这类不必要的跨 PCIe 开销。

Ollama 多 GPU 不依赖 SLI。多张普通 PCIe GPU 只要驱动和 Ollama 能识别,就可以被调度。

NVLink 或更高 PCIe 带宽可能对某些跨卡场景有帮助,但它不是 Ollama 多 GPU 的前提条件。很多二手 GPU 服务器或工作站,靠普通 PCIe 多卡也能跑。

真正要注意的是 PCIe 带宽。x1x4x8x16 的差异会影响模型加载到显存的速度;如果频繁切换大模型,PCIe 链路会更容易成为瓶颈。模型加载完成后,生成阶段受 PCIe 的影响通常会小一些,但跨卡分层仍然可能带来额外开销。

比较稳的建议是:

  • 能用 x16 / x8 就不要用矿卡 x1 转接。
  • 大模型频繁切换时,PCIe 带宽更重要。
  • 如果模型长期常驻显存,PCIe 带宽瓶颈会相对不明显。
  • 多卡机器要重点看主板 PCIe 拓扑和 CPU 直连通道。

如何限制 Ollama 使用哪些 NVIDIA GPU

NVIDIA 多卡环境下,用 CUDA_VISIBLE_DEVICES 控制 Ollama 能看到哪些卡。

临时运行:

1
CUDA_VISIBLE_DEVICES=0,1 ollama serve

只让 Ollama 用第二张卡:

1
CUDA_VISIBLE_DEVICES=1 ollama serve

强制不用 NVIDIA GPU,可以给一个无效 ID:

1
CUDA_VISIBLE_DEVICES=-1 ollama serve

官方文档提醒,数字 ID 的顺序可能变化,更可靠的是用 GPU UUID。先查看 UUID:

1
nvidia-smi -L

输出类似:

1
2
GPU 0: NVIDIA GeForce RTX 3090 (UUID: GPU-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
GPU 1: NVIDIA GeForce RTX 3070 (UUID: GPU-yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy)

然后指定 UUID:

1
CUDA_VISIBLE_DEVICES=GPU-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx ollama serve

如果 Ollama 是 Linux systemd 服务安装的,需要写到服务环境变量里:

1
sudo systemctl edit ollama.service

加入:

1
2
[Service]
Environment="CUDA_VISIBLE_DEVICES=0,1"

然后重载并重启:

1
2
sudo systemctl daemon-reload
sudo systemctl restart ollama

AMD 和 Vulkan 的选择变量

AMD ROCm 环境下,用 ROCR_VISIBLE_DEVICES 控制可见 GPU:

1
ROCR_VISIBLE_DEVICES=0,1 ollama serve

如果要强制不用 ROCm GPU,也可以用无效 ID:

1
ROCR_VISIBLE_DEVICES=-1 ollama serve

Ollama 官方 GPU 文档还提到,如果用实验性的 Vulkan 支持,可以通过 GGML_VK_VISIBLE_DEVICES 选择 Vulkan GPU:

1
OLLAMA_VULKAN=1 GGML_VK_VISIBLE_DEVICES=0 ollama serve

如果 Vulkan 设备有问题,可以禁用:

1
GGML_VK_VISIBLE_DEVICES=-1 ollama serve

AMD 多卡比 NVIDIA 更容易遇到驱动、ROCm 版本、GFX 版本支持的问题。官方文档中也提到 Linux 下 ROCm 驱动版本、HSA_OVERRIDE_GFX_VERSION 等兼容性处理。多张不同代 AMD 卡混用时,先确认每张卡是否单独可用,再考虑多卡。

Docker 里怎么暴露多张 GPU

如果用 Docker 跑 Ollama,NVIDIA 环境通常需要先安装 nvidia-container-toolkit,然后用 --gpus 暴露设备。

暴露全部 GPU:

1
2
3
4
5
6
docker run -d \
  --gpus=all \
  -v ollama:/root/.ollama \
  -p 11434:11434 \
  --name ollama \
  ollama/ollama

只暴露指定 GPU:

1
2
3
4
5
6
docker run -d \
  --gpus '"device=0,1"' \
  -v ollama:/root/.ollama \
  -p 11434:11434 \
  --name ollama \
  ollama/ollama

也可以结合环境变量:

1
2
3
4
5
6
7
docker run -d \
  --gpus=all \
  -e CUDA_VISIBLE_DEVICES=0,1 \
  -v ollama:/root/.ollama \
  -p 11434:11434 \
  --name ollama \
  ollama/ollama

如果容器里 nvidia-smi 看不到卡,Ollama 也不可能用到 GPU。先排查 Docker GPU passthrough,再排查 Ollama。

OLLAMA_SCHED_SPREAD 是什么

在一些多 GPU 配置讨论里,会看到 OLLAMA_SCHED_SPREAD=1OLLAMA_SCHED_SPREAD=true。它和 Ollama 的调度策略有关,常被用于希望模型或请求更分散地利用多张 GPU 的场景。

可以这样设置:

1
OLLAMA_SCHED_SPREAD=1 ollama serve

或者 systemd:

1
2
[Service]
Environment="OLLAMA_SCHED_SPREAD=true"

不过它不是万能开关。开启后并不等于 token/s 线性增长,也可能因为多个模型同时加载、显存估算、上下文长度和 KV cache 增长导致 OOM。官方 FAQ 的核心策略仍然是:如果单 GPU 能完整容纳模型,单 GPU 通常更高效;单 GPU 放不下时才跨多 GPU。

所以建议把 OLLAMA_SCHED_SPREAD 当成高级调度实验项,而不是多卡必开项。先理解默认行为,再根据实际 ollama ps、日志和 nvidia-smi 观察结果调整。

怎么观察多卡是否真的用上

常用观察命令:

1
ollama ps
1
watch -n 0.5 nvidia-smi

查看 Ollama 服务日志:

1
journalctl -u ollama -f

如果使用 Docker:

1
docker logs -f ollama

你需要关注:

  • Ollama 是否发现兼容 GPU。
  • 模型是否显示 100% GPU 或 CPU/GPU 混合。
  • 每张卡显存是否有占用。
  • 加载模型时是否多卡显存同时增长。
  • 生成时 token/s 是否比 CPU/RAM 混跑明显改善。
  • 是否频繁 OOM 或卸载模型。

如果只看 GPU 利用率,很容易误判。LLM 推理时 GPU 利用率不一定长期满载,尤其是多卡、低 batch、小上下文、慢 CPU 或慢 PCIe 环境下。

常见误区

误区 1:两张 12GB 显卡等于一张 24GB 显卡

不完全等价。多卡可以让模型跨设备放置,但跨卡访问有额外开销。它能解决“放不下”的问题,不一定等价于单张大显存卡的速度和稳定性。

误区 2:不同型号显卡不能混用

不一定。只要驱动、计算能力和运行库都支持,Ollama 可以看到多张 GPU。但混用时,速度通常受较慢卡、较小显存和 PCIe 拓扑影响。最稳的多卡配置仍然是同型号、同显存、同代驱动支持良好的卡。

误区 3:多卡一定比单卡快

不一定。如果模型能完整放进单张快卡,单卡可能更快。多卡主要适合大模型、长上下文、单卡显存不够的情况。

不需要。普通 PCIe 多卡也能被 Ollama 使用。NVLink 不是前提。

误区 5:加 GPU 后不用重启服务

不一定。Linux systemd 服务、Windows 后台应用、Docker 容器都可能需要重启,才能重新识别设备和环境变量。

选卡建议

如果目标是 Ollama 本地推理,优先级大致是:

  1. 单卡显存越大越省心。
  2. 同型号多卡比混合多卡更容易排错。
  3. PCIe 通道越完整,加载大模型越舒服。
  4. 老卡要先确认 CUDA compute capability 或 ROCm 支持。
  5. 多卡电源、散热和机箱风道要提前算清楚。

对于预算有限的二手平台:

  • 双 3090 仍然是很常见的大显存方案。
  • P40 / M40 这类老 Tesla 显存大,但功耗、散热、驱动和性能都要权衡。
  • 4070 / 4070 Ti 这类新卡能效好,但单卡显存容量限制更明显。
  • 多张 8GB 老卡能折腾,但不建议为了大模型长期使用。

小结

Ollama 多显卡支持可以理解成“显存扩展优先,性能加速其次”。如果模型能完整放进一张 GPU,默认单卡通常更快;如果单卡放不下,多卡可以把模型分布到多张 GPU 上,避免大量落到 CPU/RAM,从而让大模型变得可用。

实际配置时,先用 ollama ps 看模型加载位置,再用 nvidia-smi 或 ROCm 工具观察显存占用。需要限制 GPU 时,NVIDIA 用 CUDA_VISIBLE_DEVICES,AMD ROCm 用 ROCR_VISIBLE_DEVICES,Vulkan 用 GGML_VK_VISIBLE_DEVICES。如果在 Docker 中运行,先确保容器层面能看到 GPU。

多卡不是魔法。它能帮你装下更大的模型,但不保证线性加速。真正稳定好用的路线,仍然是尽量选大显存单卡或同型号多卡,并把驱动、PCIe、电源、散热和模型量化一起考虑。

参考链接

记录并分享
使用 Hugo 构建
主题 StackJimmy 设计