Ollama 探测不到 GPU,全跑在 CPU

Ollama 启动后模型在 CPU 上运行,生成极慢。读懂 inference-compute 日志,定位驱动、CUDA、ROCm 不匹配,强制开启 GPU 卸载。

你拉取了一个小模型,比如 mistral:7b,结果生成速度只有 2-5 token/s,而一张较新的 GPU 本应跑到 40-120 token/s。ollama ps 的 PROCESSOR 列显示 100% CPUnvidia-smi 利用率始终为 0%,即便模型完全装得进显存、驱动看起来也是新的。Ollama 会自动探测 NVIDIA、AMD、Apple 以及(从 0.12.11 起)Vulkan GPU,一旦探测失败就会静默回退到 CPU——没有报错,只是变慢。十有八九问题出在驱动 / 运行时这一层,而不是 Ollama 本身。

最快的定位办法:停掉服务,用前台 + 调试日志启动 Ollama,那一行 msg="inference compute" 会直接告诉你 Ollama 探测到了哪块设备(或者根本没探测到),一句话省掉所有猜测:

sudo systemctl stop ollama 2>/dev/null || true
OLLAMA_DEBUG=1 ollama serve 2>&1 | grep -iE 'inference compute|no compatible|cuda|rocm|metal|error'

如果看到带 library=cuda(或 rocm/metal)并写明你显卡名字的那一行,说明 GPU 已经被探测到了,问题在显存 / 卸载,而非探测。如果看到 no compatible GPUs were discovered,就按下面的原因逐个排查。

先对号入座

调试日志 / nvidia-smi 的现象最可能的原因跳到
nvidia-smi 本身报错,或驱动版本过旧驱动太旧 / 未安装原因 1
没有 inference compute 那行,CUDA_VISIBLE_DEVICES""-1环境变量遮蔽了 GPU原因 2
手动跑能用,systemd 服务下不行服务看不到驱动 / 设备节点原因 3
rocm-smi 能看到卡,但 Ollama 报 amdgpu is not supportedAMD gfx 版本未覆盖 / ROCm 太旧原因 4
在 WSL2 里 nvidia-smi 为空,或 /dev/dxg 不存在Windows 侧驱动 / 直通问题原因 5
Snap 或 Flatpak 安装,/dev/nvidia* 无法访问沙箱挡住了设备节点原因 6
Apple Silicon,有 Metal 却很慢OLLAMA_GPU / no-GPU 覆盖,或内存吃紧原因 7

常见原因

1. NVIDIA 驱动太旧(或根本没装 CUDA)

截至 2026 年 6 月,Ollama 要求 NVIDIA 驱动 531 或更高(CUDA 12.3+)。计算能力 5.0-6.2 的显卡(Maxwell / Pascal,如 GTX 10 系、Tesla P40)需要 驱动 570 或更高。再旧的驱动会被判为不兼容,直接回退 CPU。注意显示驱动和 CUDA 工具包是两回事:Ollama 自带 CUDA 运行时,但仍然需要 nvidia-smi 能用、并且系统驱动里的 libcuda.so.1 能被加载到。

怎么判断nvidia-smi --query-gpu=driver_version --format=csv,noheader。若报 command not found,或版本低于 531(旧卡低于 570),就是这个原因。再跑 ldconfig -p | grep libcuda——若没有任何输出,说明驱动库不在加载器路径上。

2. CUDA_VISIBLE_DEVICES 被设为空或 -1

某些 conda 环境、Docker 镜像、IDE 插件会在激活时把 CUDA_VISIBLE_DEVICES 设成 ""-1,结果对所有 CUDA 应用隐藏掉全部 GPU。Ollama 找不到设备,只能用 CPU。

怎么判断echo "[$CUDA_VISIBLE_DEVICES]"。若打印出 [](空)或 [-1],就是它。同时检查 ~/.bashrc~/.zshrc 以及 conda 的 activate.d/ 脚本里有没有遗留的 export

3. Ollama 跑在 systemd 下,却够不到驱动或设备节点

当 Ollama 以 ollama systemd 服务运行时,有两件事会卡住 GPU 访问:(a) 服务可能在 NVIDIA 内核模块加载之前就启动了,于是把”无 GPU”缓存了一整个进程周期;(b) 服务账户可能不在 render / video 用户组,无法打开 /dev/dri/*(AMD)或 /dev/nvidia*

怎么判断:对比 systemctl status ollama 的启动时间和 dmesg | grep -i nvidia 的模块加载时间;再看 journalctl -u ollama -n 100 | grep -iE 'permission|denied|no compatible'。如果一句 sudo systemctl restart ollama 就让 GPU 突然出现,基本可以坐实是启动时序竞争。

4. AMD 显卡:ROCm 太旧,或 gfx 版本未覆盖

AMD 这边,Ollama 现在面向 ROCm v7(Linux 与 Windows 均是)。ROCm 后端只接受一份固定的 GPU 家族清单。如果 OLLAMA_DEBUG=1 日志里出现 amdgpu is not supported (supported types:[gfx1030 gfx1100 gfx1101 gfx1102 gfx900 gfx906 gfx908 gfx90a gfx940 gfx941 gfx942]),说明你的卡的 gfx ID 不在清单里,得用 HSA_OVERRIDE_GFX_VERSION 把它别名到一个受支持的家族。

怎么判断rocm-smi 能看到卡,rocminfo | grep gfx 能打印出它的 gfx ID,但 ollama run 仍然在 CPU 上。调试日志里那行 “supported types” 就是线索。

5. WSL2:GPU 没从 Windows 直通进来

在 Windows 11 + WSL2 里,GPU 是由 Windows 侧驱动暴露出来的——你绝不能在 WSL2 内部再装一套 Linux NVIDIA 驱动(那会破坏直通)。你需要的是 Windows 端 NVIDIA 驱动 531+,以及发行版里存在 /dev/dxg 设备。

怎么判断:在 WSL2 里跑 nvidia-smi(应能列出显卡)和 ls /dev/dxg(必须存在)。若 nvidia-smi 为空或 /dev/dxg 缺失,就是直通问题。AMD ROCm 在 WSL2 里基本不可靠,因为 WSL2 暴露的是 /dev/dxg,而不是 ROCm 需要的 /dev/kfd

6. Snap / Flatpak 安装,GPU 访问被沙箱限制

Snap 和 Flatpak 会把进程放进沙箱,默认限制 /dev/nvidia*,于是即便驱动正确,沙箱里的 Ollama 也打不开设备节点。

怎么判断snap connections ollama | grep -i hardware(Flatpak 则看权限列表)。若 GPU 相关接口没有 connected,就是这个原因。

7. Apple Silicon:被某个覆盖项强制走了 CPU,或模型超出统一内存

在 Apple Silicon 上 Ollama 会自动用 Metal——根本没有 CUDA。如果有人 export OLLAMA_NO_GPU=1(或类似开关),Metal 就被关掉了,而且报错不明显。另一种常见情况是:量化模型大于空闲的统一内存,部分层被推到 CPU 上。

怎么判断env | grep -i ollama 看有没有遗留覆盖项;system_profiler SPDisplaysDataType | grep -i metal 确认 Metal 支持。在 Mac 上设任何 CUDA_* 变量都没意义,还可能引发怪异行为。

最短修复路径

Step 1:先读懂 inference-compute 日志

sudo systemctl stop ollama 2>/dev/null || true
OLLAMA_DEBUG=1 ollama serve 2>&1 | grep -iE 'inference compute|no compatible|cuda|rocm|metal'

一条健康的 NVIDIA 日志大致长这样:

msg="inference compute" id=GPU-xxxx library=cuda compute=8.9 driver=12.x name="NVIDIA GeForce RTX 4090" total="23.6 GiB" available="23.2 GiB"

如果这行写明了你的显卡,直接跳到 Step 7(这是显存 / 卸载问题,不是探测问题)。如果看到 no compatible GPUs were discovered,继续往下。

Step 2:确认操作系统能看到 GPU 和驱动

# NVIDIA
nvidia-smi --query-gpu=name,driver_version,memory.total --format=csv
# 驱动需 >= 531(计算能力 5.0-6.2 的卡需 >= 570)

# AMD
rocm-smi
rocminfo | grep -i gfx   # 记下那个 gfxNNNN 的 ID

# Apple Silicon
system_profiler SPDisplaysDataType | grep -i "metal\|chipset"

Step 3:清掉遮蔽 GPU 的环境变量

unset CUDA_VISIBLE_DEVICES   # NVIDIA
unset ROCR_VISIBLE_DEVICES   # AMD 设备选择器
unset OLLAMA_NO_GPU

# 带计时重测
ollama run llama3.2:3b "say hello" --verbose
# 看 "eval rate" 那一行——走 GPU 时应远高于 30 token/s

Step 4:升级 NVIDIA 驱动(Linux),然后重启 Ollama

# Ubuntu 22.04 / 24.04
ubuntu-drivers devices
sudo ubuntu-drivers autoinstall
sudo reboot

# 重启后确认版本,并重启服务(Ollama 在启动时缓存设备列表)
nvidia-smi --query-gpu=driver_version --format=csv,noheader
sudo systemctl restart ollama

Step 5:指定正确的 GPU,并给服务设备访问权限

如果你既有一块显示用 GPU、又有一块计算用 GPU,把计算卡固定下来,免得 Ollama 挑了那块小的:

nvidia-smi -L
# GPU 0: NVIDIA GeForce GT 730 (UUID: GPU-...)   <- 显示用,2 GB
# GPU 1: NVIDIA GeForce RTX 3090 (UUID: GPU-...)  <- 计算用,24 GB
export CUDA_VISIBLE_DEVICES=1   # 或填 GPU-UUID 更稳

写进 unit 文件持久化,并授予设备节点访问权:

sudo systemctl edit ollama
# 在 [Service] 下添加:
#   Environment="CUDA_VISIBLE_DEVICES=1"
#   SupplementaryGroups=render video
#   After=nvidia-persistenced.service

sudo systemctl daemon-reload && sudo systemctl restart ollama

Step 6:仅限 AMD——设置 gfx 覆盖

如果调试日志打印了 “supported types” 那条警告,把你的卡别名到最接近的受支持家族:

# RX 6xxx(gfx103x)-> 别名到 gfx1030
export HSA_OVERRIDE_GFX_VERSION=10.3.0
# RX 7xxx(gfx110x)-> 别名到 gfx1100
export HSA_OVERRIDE_GFX_VERSION=11.0.0
# 多张 AMD 卡:用按设备的形式
# export HSA_OVERRIDE_GFX_VERSION_0=10.3.0

ollama run llama3.2:3b "say hello" --verbose

注意:对一张 gfx 本来就受支持的卡强行设覆盖,可能让推理崩溃(SIGSEGV)——只在日志明确说你的类型不受支持时才设。

Step 7:确认 GPU 卸载确实生效了

ollama run llama3.2:3b "say hello"   # 先把模型加载起来
ollama ps
# PROCESSOR 应显示 100% GPU(部分拆分时类似 "30%/70% CPU/GPU")

# NVIDIA:确认显存被占用,且生成时利用率会飙升
watch -n 1 nvidia-smi

如果 ollama ps 显示 CPU/GPU 拆分,说明模型超出显存、部分层溢出到了 CPU——见下方 FAQ 里关于卸载的那条。

预防建议

  • 任何驱动更新之后,跑一次 sudo systemctl restart ollama——Ollama 只在启动时探测一次设备并缓存结果。
  • 在 systemd unit 里固定 CUDA_VISIBLE_DEVICES(用 GPU UUID 而不是序号),确保每次开机都选对卡。
  • ollama.service 加上 After=nvidia-persistenced.service,让驱动先于 Ollama 探测加载好。
  • conda/venv 激活脚本里绝不要无差别 unset 或清空 CUDA_VISIBLE_DEVICES,改成固定一个具体 ID。
  • WSL2 下锁定 Windows 侧 NVIDIA 驱动版本,且绝不在发行版内部安装 Linux NVIDIA 驱动。
  • 遇到 Snap/Flatpak 的麻烦,改用官方安装脚本:curl -fsSL https://ollama.com/install.sh | sh
  • OLLAMA_DEBUG=1 写进服务的 EnvironmentFile,需要时日志里总有那行 inference compute
  • 加载完模型马上 ollama ps,在跑长任务前先确认是 GPU 还是 CPU。

常见问答 (FAQ)

Q:ollama ps 显示 GPU,但 nvidia-smi 利用率是 0%,GPU 到底用上没有? A:多半用上了。PROCESSOR 列反映的是权重放在哪里,而 GPU 利用率只在前向计算时才飙升。发一个 prompt,同时 watch -n 1 nvidia-smi,生成过程中能看到利用率跳起来。如果显存被占了但利用率从不动,那才是确实没有东西在 GPU 上跑。

Q:模型装不进显存,能不能 GPU 和 CPU 拆着跑? A:能——Ollama 会自动这么做:尽量把更多 Transformer 层放到 GPU,剩下的在 CPU 上跑。ollama ps 的 PROCESSOR 列会显示拆分比例。想让模型降到显存之下,拉一个更小的量化版(比如用 llama3.1:8b-instruct-q4_K_M 替代 q8_0)。负载下遇到显存不足时,可以设 OLLAMA_GPU_OVERHEAD 预留一点显存余量。

Q:我的 NVIDIA 驱动多旧算太旧? A:截至 2026 年 6 月,低于驱动 531 完全用不了;计算能力 5.0-6.2 的卡(GTX 10 系、Tesla P40 等)需要 570+。用 nvidia-smi --query-gpu=driver_version --format=csv,noheader 查。

Q:终端里 Ollama 正常,但 Docker 里却走 CPU,缺了什么? A:docker run 要加 --gpus all,并在宿主机装好 nvidia-container-toolkit。先用 docker run --rm --gpus all nvidia/cuda:12.3.0-base-ubuntu22.04 nvidia-smi 验证容器内 GPU 可见,再起 Ollama 容器。

Q:AMD 卡在 rocm-smi 里能看到,但 Ollama 还是走 CPU。 A:在 OLLAMA_DEBUG=1 日志里找 amdgpu is not supported (supported types:[...])。如果你的 gfx ID 不在列表里,用 HSA_OVERRIDE_GFX_VERSION 别名(RX 6xxx 用 10.3.0,RX 7xxx 用 11.0.0)。同时确认你用的是 ROCm v7。

Q:Ollama 能用多张 GPU 跑同一个模型吗? A:能。把所有卡都设为 CUDA 可见,Ollama 会把 Transformer 层分布到各卡上。如果只用了 GPU 0,参考多 GPU 那篇文章做拆分验证。

相关阅读

标签: #local-llm #ollama #排查