你拉取了一个小模型,比如 mistral:7b,结果生成速度只有 2-5 token/s,而一张较新的 GPU 本应跑到 40-120 token/s。ollama ps 的 PROCESSOR 列显示 100% CPU,nvidia-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 supported | AMD 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 #排查