最近在一台 CentOS 8 服务器上部署 Ollama,原本目标很明确:
将 qwen3.5:9b 模型下载并成功运行在 NVIDIA RTX 3060 显卡上。

结果,现实立刻给了个下马威:
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 未调用显卡”
这个问题最容易让人一上来就陷入“重装 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 路径带偏
最初,为了使用两张显卡,我曾在服务配置中加入:
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用户已在video、render组中/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 GPU 和 runner.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=cpuoffloaded 0/... layers to GPUrunner.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 上”的问题,希望这篇文章能帮你少走一些弯路。
