Ollama 报 CUDA out of memory 或 cuda error out of memory,根因几乎都是同一件事:模型加载时需要的显存超过了 GPU 实际可用的那部分。Ollama 默认按接近 FP16 的精度加载模型,一个 7B 模型大约要占 14GB 显存,而市面上大量消费级显卡是 8GB 或 12GB,装好就跑,第一次跑大模型就 OOM 很常见。
先说结论:换更低的量化版本是性价比最高的一步,其次是把上下文窗口 num_ctx 从默认的 4096 降下来,再往后是调并行请求数和 KV 缓存量化。四步做完,8GB 显卡也能稳定跑 7B-9B 级别的量化模型。
一、先看占用:ollama ps 和 nvidia-smi
排查前先确认问题出在哪一层。
ollama ps # 看哪些模型正占着显存,处于 GPU/CPU/混合哪种状态
nvidia-smi # 看显卡实际剩余显存 (Windows/Linux 通用)
ollama ps 输出的 PROCESSOR 列如果显示 100% GPU,说明模型完全在显卡里;显示 CPU/GPU 混合,说明已经在做部分卸载,这时再加载新模型很容易触发 OOM。默认 OLLAMA_KEEP_ALIVE 是 5 分钟,模型用完不会立刻释放显存,如果你频繁切换模型,这一点经常被忽略。
二、四个排查方向,按性价比排序
| 方向 | 怎么改 | 效果 |
|---|---|---|
| 换量化版本 | 拉取 Q4_K_M 或更低的 tag,如 ollama pull llama3:8b-q4_K_M | 7B 模型从约 14GB(FP16) 降到约 4.5-5.5GB(Q4_K_M) |
降上下文 num_ctx | Modelfile 里加 PARAMETER num_ctx 2048,或 API 请求带 options.num_ctx | 上下文窗口是显存预分配的大头,不是按实际用量分配 |
降并行数 OLLAMA_NUM_PARALLEL | 环境变量设为 1(默认已是 1,多开时容易被调大) | 官方文档写明所需显存按 并行数 × 上下文长度 线性增长 |
| KV 缓存量化 | OLLAMA_KV_CACHE_TYPE=q8_0 或 q4_0,需配合 Flash Attention | q8_0 缓存减半,q4_0 缓存降到约三分之一 |
四步都做完仍然 OOM,说明模型本身的量化档位就超过了硬件上限,只能换更小的模型或加显卡。
三、只降 GPU 层数:num_gpu 手动卸载
如果不想换量化版本,还可以手动控制加载到 GPU 的层数,让剩余部分跑在 CPU 上(速度会变慢,但能跑起来):
curl http://localhost:11434/api/generate -d '{
"model": "llama3:8b",
"prompt": "test",
"options": { "num_gpu": 20 }
}'
从模型总层数开始往下试,每次减 5-10 层,直到不再报错。这是个笨办法,但在临时应急、不想重新下载模型时很好用。
四、Windows / Linux / Mac 三平台差异
- Windows:用
nvidia-smi看占用,注意有些游戏本会有独立显卡和核显混用的情况,确认 Ollama 真的调用的是独立显卡;某些驱动版本和 CUDA 13 系列有兼容性问题,报错信息里如果出现驱动相关字样,先更新 NVIDIA 驱动。 - Linux:容器化部署(Docker)最容易漏掉
--gpus all参数,漏了会导致 Ollama 完全跑在 CPU 上,报错反而不是 OOM 而是极慢;用 systemd 跑常驻服务的,环境变量要写进 service 文件而不是当前 shell,否则改了不生效。 - Mac:Apple Silicon 用 Metal 后端,不会报
CUDA out of memory(CUDA 是 NVIDIA 的技术栈),但会报内存不足或加载失败,底层逻辑完全一样:模型体积超过统一内存可用空间的 80% 阈值就会出问题。Mac 的优势是显存和系统内存是同一块(统一内存),128GB 内存的机型理论上能碰更大的量化档位,但要给系统和其他进程留够余量。
五、卸载重装能不能解决
不能,除非你怀疑是驱动或 CUDA 库本身损坏。显存不足是资源计算问题:模型体积摆在那,硬件上限摆在那,重装只是把同一个模型再装一遍,不会改变这个算式。真正需要重装的场景是升级 Ollama 版本后出现的兼容性报错,或者 CUDA Toolkit 版本冲突导致的加载失败,这类报错信息里通常会带驱动版本号或库文件路径,和纯粹的 OOM 报错能区分开。
我的判断
优先级排序: 先换量化版本, 再降 num_ctx, 最后才动 num_gpu 手动卸载。前两步几乎零成本, 不影响使用体验太多; 手动卸载层数会明显拖慢速度, 只适合临时应急。如果一台 8GB 显卡的机器天天要跑 13B 以上的模型, 与其反复调参数, 不如直接接云端 API 或换更大显存的显卡, 省下来的排查时间比硬件差价更值钱。