Ollama GPU排障指南:完整可复现的CPU误用排查方法

2026-06-01阅读 0热度 0
GPU
好的,作为一位长期从事AI模型部署与GPU加速排障的工程师,我想分享一次针对Ollama的完整实战复盘。此文会保留所有事实细节与核心逻辑,但调整成一份来自一线运维的深度技术笔记——强调可复现的排查路径,而非枯燥的命令列表。

前段时间在 CentOS 8 上折腾 Ollama,目标明确:
拉取 qwen3.5:9b 模型,稳稳跑在 NVIDIA RTX 3060 上。

Ollama GPU 加速问题排查:模型为何默认使用 CPU 而非 NVIDIA 显卡?一份可复现的完整诊断流程

结果立刻遭遇当头一棒:

  • nvidia-smi 输出正常
  • 驱动版本看着没问题
  • Ollama 服务顺利启动
  • 模型也成功拉取
  • ollama ps 显示的却是:
PROCESSOR 100% CPU

模型完全没走GPU,全压在CPU上硬算。

这类问题最容易让人踩坑。很多人遇到“模型没用GPU”,第一反应是:

  • 显卡太旧不支持?
  • CUDA 装错了?
  • 模型太大放不下?
  • Ollama 本身有 bug?

但实际啃下来后,我发现排障的关键不是背几条命令,而是掌握一套结构化、可递进的排查思路。

这篇文章把这次完整过程掰开揉碎。我不只给最终答案,还会把每一步的判断逻辑也讲透。这正是我反复强调的“默会知识”:很多时候决定成败的不是某个标准语句,而是长期实战中积累的“优先看哪里、哪些线索最致命、怎样持续缩小范围”的直觉。

一、现象复现:模型能响应,但推理完全依赖 CPU

一开始,Ollama 装好,模型拉下来:

ollama run qwen3.5:9b

看起来一切如常,模型能正常对话,没有报错。

但一跑 ollama ps,看到的是:

NAME    ID      SIZE    PROCESSOR CONTEXT UNTIL
qwen3.5:9b xxxxxxxxxxxx 8.5 GB 100% CPU  4096   4 minutes from now

这条信息是排障的第一现场。很多人忽略 ollama ps,但它在判断 Ollama 是否真正使用 GPU 上,价值无可替代。

如果这里显示:

  • 100% GPU:模型完整占用 GPU
  • 100% CPU:完全跑在 CPU 上
  • xx% CPU / xx% GPU:部分层卸载到 GPU

所以,第一条经验:永远先查 ollama ps,而不是凭感觉猜测。

二、第一层:区分“显卡不可用”与“Ollama 没调用 GPU”

这个问题最容易让人一上来就陷入“重装 CUDA、重装驱动、重装系统”的深坑。

我当时先做了更基础的判断:

1. 先确认显卡驱动是否正常

nvidia-smi

机器返回正常,能看到两张 RTX 3060

+-----------------------------------------------------------------------------+
| NVIDIA-SMI 570.xxx.xx   Driver Version: 570.xxx.xx   CUDA Version: 12.8 |
| GPU  Name               ...                                               |
| 0  NVIDIA GeForce RTX 3060                                               |
| 1  NVIDIA GeForce RTX 3060                                               |
+-----------------------------------------------------------------------------+

这一步说明 Linux 内核已识别显卡,NVIDIA 驱动也正常安装。但只能说明“显卡没坏、驱动没坏”,不能说明“Ollama 一定能调用 GPU”。

这是排障中很重要的默会知识:“我有武器”和“我会使用武器”是两码事。

三、第二层:验证 Ollama 服务是否真的稳定运行

先确认客户端:

which ollama
ollama -v

返回类似:

/usr/local/bin/ollama
client version is 0.18.2

客户端安装成功。

但随后发现:

systemctl start ollama

报错:

Unit ollama.service not found

这说明安装脚本虽然把 ollama 命令装好了,但 systemd 服务文件没正确生成。

于是手工创建了 /etc/systemd/system/ollama.service

[Unit]
Description=Ollama Service
After=network-online.target

[Service]
ExecStart=/usr/local/bin/ollama serve
User=ollama
Group=ollama
Restart=always
RestartSec=3
Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
Environment="OLLAMA_MODELS=/home/ollama/models"

[Install]
WantedBy=multi-user.target

然后启动:

systemctl daemon-reload
systemctl enable --now ollama
systemctl status ollama --no-pager

这一步的意义:确保 Ollama 服务稳定运行,排除“只是命令行临时启动,服务环境与交互环境不一致”的问题。这也是关键经验:很多情况下,命令行前台运行与 systemd 后台运行的环境变量、权限、库路径都可能不同。

四、第三层:通过日志判断 Ollama 在哪一步失败

当模型仍然跑在 CPU 上时,我没有反复 run,而是开始看日志:

journalctl -u ollama -n 200 --no-pager | egrep -i 'cuda|gpu|runner|library|offload|vram'

日志里出现了几类非常关键的信息:

1. 看到了 GPU 发现阶段日志

discovering a vailable GPUs...

这说明 Ollama 至少进入了 GPU 探测阶段。

2. 但推理后端仍然是 CPU

inference compute id=cpu library=cpu

这一句,就是“定性证据”。它说明在真正选择推理后端时,Ollama 并没有走 CUDA 路径,而是选了 CPU library。

3. 模型层没有卸载到 GPU

GPULayers:[]
offloading 0 repeating layers to GPU
offloaded 0/33 layers to GPU
runner.vram="0 B"

这几句连起来看,结论就很明确了:Ollama 尝试进入模型加载阶段,但一个层都没放到 GPU,最终 VRAM 视角下使用量为 0。

这个阶段我形成了一个重要判断:问题很可能不在“显存不够”,而在“CUDA 后端根本没被加载”。 因为如果只是“模型太大”,通常更容易看到的是“部分层上 GPU,部分层在 CPU”,而不是 0 层上 GPU。

这也是排障中一个非常重要的经验判断:现象本身,已经在告诉你下一步该去哪里找答案了。

五、第四层:环境变量是否干扰了 GPU 路径

最开始我为了让 Ollama 使用两张显卡,在服务里加过:

Environment="CUDA_VISIBLE_DEVICES=0,1"

看起来很合理,但日志里反而出现了:

user overrode visible devices
if GPUs are not correctly discovered, unset and try again

这句话让我意识到:这个变量不一定有益,在某些环境里反而可能干扰自动探测。

于是我先做了一个“减法”动作:去掉 CUDA_VISIBLE_DEVICES,让 Ollama 自己探测。

这一步的结果很有价值:

  • 去掉后,日志里不再出现 CUDA_VISIBLE_DEVICES=0,1
  • 但仍然显示 library=cpu
  • 仍然 offloaded 0/33 layers to GPU

这说明问题已经被进一步缩小:跟环境变量无关,是更底层的东西出了问题。

这就是默会知识在排障里的作用。不是每一步都能直接解决问题,但每一步都要能“缩小问题范围”。

六、第五层:权限是否构成障碍

接下来我查了服务用户和设备权限:

id ollama
ls -l /dev/nvidia*

看到:

  • ollama 用户已经在 videorender 组里
  • /dev/nvidia0/dev/nvidia1/dev/nvidiactl/dev/nvidia-uvm 都存在
  • 权限看起来也正常

这一步排除了另一个常见误区。很多时候一看到 GPU 不工作,大家就习惯性去改 chmod 777 /dev/nvidia*,甚至改一堆组权限。但这次的现象更像是:设备文件没问题,显卡驱动没问题,Ollama 也能发现“有 GPU 这回事”,只是最后没有找到自己的 GPU 运行库。

这一步再次缩小了范围。问题的靶心越来越清晰了。

七、第六层:真正的根因——不在显卡,而在 Ollama 自己的运行库目录

后面我查了两个目录:

ls -lah /usr/local/lib/ollama
find /usr/local/lib/ollama -type f

结果发现:/usr/local/lib/ollama 居然是空目录。

而日志里明明显示 Ollama 启动时使用的是:

LD_LIBRARY_PATH=/usr/local/lib/ollama
OLLAMA_LIBRARY_PATH=/usr/local/lib/ollama

也就是说:Ollama 运行时去 /usr/local/lib/ollama 找自己的运行库,但这个目录是空的。所以它根本加载不到 CUDA 后端,最后自然只能回退到 CPU。

这一下就把整件事解释通了。

这是这次排障里最核心的结论:不是你显卡不行,是你程序找不到自己的“弹药库”。

随后我又查了另一个目录:

ls -lah /usr/lib/ollama
find /usr/lib/ollama -type f | egrep -i 'cuda|ggml|runner|llama'

结果发现 /usr/lib/ollama 里其实是有内容的,里面有 CUDA 相关运行库。

也就是说,这次安装属于一种“半成功状态”:可执行文件装到了 /usr/local/bin/ollama,但运行库没有同步到 /usr/local/lib/ollama。结果程序能启动,模型也能拉,但 GPU 后端不可用。

这类问题特别容易误导人,因为它不是“装不上”,而是“能用,但用得不对”。

八、最终修复:将正确的运行库补到 Ollama 实际查找的目录

既然 /usr/lib/ollama 里有完整内容,而 /usr/local/lib/ollama 是空的,那最快的修法就是把两者接起来。

最后采用了这种方式:

systemctl stop ollama
rm -rf /usr/local/lib/ollama
ln -s /usr/lib/ollama /usr/local/lib/ollama
ldconfig
systemctl start ollama

这么做的好处显而易见:不需要重新拉模型,不需要重装驱动,不需要重装系统,只是把运行库路径纠正过来。

修复后再次执行:

ollama run qwen3.5:9b
ollama ps

结果就变成了:

PROCESSOR 100% GPU

同时 nvidia-smi 也能看到显存和 GPU 利用率的变化。问题到此彻底解决。

九、这次排障里最重要的几个“默会知识”

最后把这次的经验总结成几条,供以后快速判断。

1. 不要先重装,先定性

先回答一个问题:“显卡不可用”还是“Ollama 没用上显卡”?

方法很简单:看 nvidia-smi,看 ollama ps,看日志里的 library=cpu 还是 CUDA 相关信息。

2. ollama ps 是第一现场

不要只看模型会不会回答。会回答不代表用了 GPU。真正要看的是 ollama ps。这一步能最快避免“自以为跑在 GPU 上”的误判。

3. 日志里最关键的不是“有 GPU”,而是“用了哪个 library”

discovering a vailable GPUs... 这种日志,只能说明它在“找 GPU”。但真正决定胜负的是:inference compute id=cpu library=cpu。这说明最后真正用来推理的后端仍然是 CPU。

4. “0 层上 GPU”比“部分层上 GPU”更值得警惕

如果日志里看到 offloaded 0/33 layers to GPUrunner.vram="0 B",优先怀疑的不该是“显存不够”,而应该是:CUDA 后端没加载成功、运行库缺失、库路径不对。

5. 环境变量不是越多越好

CUDA_VISIBLE_DEVICES 这种变量,在某些时候有用,但也可能干扰自动探测。排障时一定要学会做减法:先去掉,看看效果。

6. 应用自己的运行库路径,往往比驱动本身更容易被忽略

这次最大的坑并不是 NVIDIA 驱动,而是 /usr/local/lib/ollama 是空目录。这类问题最难就难在它不显眼。命令能跑,模型能拉,服务能起,但 GPU 失效。如果没有顺着日志一路缩小问题范围,很容易永远怀疑错方向。

十、最终整理出来的一套 Ollama GPU 排障顺序

后面如果再遇到类似问题,会按这个顺序直接排。

第一步:确认显卡和驱动

nvidia-smi

第二步:确认 Ollama 是否真的在 GPU 上

ollama ps

第三步:看服务和日志

systemctl status ollama --no-pager
journalctl -u ollama -n 200 --no-pager | egrep -i 'cuda|gpu|runner|library|offload|vram'

第四步:判断是“GPU 没识别”还是“GPU 没被用上”

重点看:

  • library=cpu
  • offloaded 0/... layers to GPU
  • runner.vram="0 B"

第五步:排除环境变量干扰

检查服务文件和 override:

systemctl cat ollama
systemctl show ollama --property=Environment

第六步:排除权限问题

id ollama
ls -l /dev/nvidia*

第七步:检查 Ollama 自己的运行库目录

ls -lah /usr/local/lib/ollama
find /usr/local/lib/ollama -type f
ls -lah /usr/lib/ollama
find /usr/lib/ollama -type f | egrep -i 'cuda|ggml|runner|llama'

第八步:如果运行库在 /usr/lib/ollama,但 /usr/local/lib/ollama 是空的

直接修正:

systemctl stop ollama
rm -rf /usr/local/lib/ollama
ln -s /usr/lib/ollama /usr/local/lib/ollama
ldconfig
systemctl start ollama

第九步:重新验证

ollama run qwen3.5:9b
ollama ps
watch -n 1 nvidia-smi

十一、额外提醒:Dify 里接入 Ollama 报错,不一定是模型问题

这次 GPU 问题解决后,又遇到一个插曲:Dify 里添加 Ollama 模型失败,报的是 Connection refused

这个问题和 GPU 无关,而是监听地址的问题。默认情况下,Ollama 只监听 127.0.0.1:11434,如果 Dify 在另一台机器上,自然就连不上。

这时候要给 Ollama 增加:

Environment="OLLAMA_HOST=0.0.0.0:11434"

然后重启服务,再检查防火墙和端口放通。

这个小插曲也提醒我:不要把“模型没跑 GPU”和“Dify 接不通”混在一起排。前者是推理后端问题,后者是网络监听问题,属于两条完全不同的链路。

十二、结语:真正能解决问题的,往往不是命令,而是判断路径

这次 Ollama 排障给我最大的感受是:很多时候,真正决定能不能解决问题的,不是会不会查一条命令,而是有没有形成一套稳定的判断路径。

这正是我一直强调的默会知识:

  • 书上不会告诉我先怀疑库路径还是先怀疑驱动
  • 官方文档也不会完整复现我遇到的这个场景
  • 但通过一次次排障,会慢慢形成一种“看到什么现象,就该往哪个方向继续缩小范围”的能力

所以这次我真正收获的,不只是“怎么让 Ollama 跑到 GPU 上”,而是形成了这样一个习惯:每一次排障,都是在下一次为自己省下几个小时。

如果在本地部署 Ollama,也遇到了“模型明明能跑,但就是跑在 CPU 上”的问题,希望这篇文章能帮少走一些弯路。

免责声明

本网站新闻资讯均来自公开渠道,力求准确但不保证绝对无误,内容观点仅代表作者本人,与本站无关。若涉及侵权,请联系我们处理。本站保留对声明的修改权,最终解释权归本站所有。

相关阅读

更多
欢迎回来 登录或注册后,可保存提示词和历史记录
登录后可同步收藏、历史记录和常用模板
注册即表示同意服务条款与隐私政策