在 Ollama 或其他推理框架(如 vLLM、PyTorch)中,经常会看到一种现象:
请求结束了,但 GPU 显存还在被占用。
这其实不是异常,而是推理系统的设计策略。主要有 4 个原因。
1 模型权重仍然常驻 GPU(最主要原因)
当模型第一次被调用时:
- 模型权重从磁盘加载
- 权重拷贝到 GPU
- tokenizer、KV结构初始化
例如一个 7B 模型:
| 组件 | 显存 |
|---|---|
| 模型权重 | 6–8GB |
| KV cache 初始空间 | 1–2GB |
| CUDA context | 300–800MB |
合计大约:
8–10GB
推理结束后:
- 权重不会卸载
- 只会清空 KV cache
原因很简单:
如果每次请求都重新加载模型:
磁盘 → CPU → GPU
可能需要 5–20 秒。
因此推理系统一般会选择:
模型常驻 GPU,等待下一次请求。
2 CUDA Memory Pool(显存缓存机制)
底层框架(如 PyTorch)有一个机制:
显存不会立即归还给系统,而是进入缓存池。
流程是:
申请显存
→ 使用
→ 释放
→ 放入 CUDA memory pool
这样下一次分配显存时:
直接复用
而不是重新申请 GPU memory。
所以你会看到:
nvidia-smi
显存一直占着
但实际上:
这些显存是可复用的。
3 KV Cache 预分配
像 vLLM 这种高性能推理框架,会做:
KV Cache 预分配。
例如:
--max-model-len 8192
系统可能一次性申请:
10GB KV cache
哪怕当前请求只用 1GB。
好处是:
- 避免频繁 GPU malloc
- 提高吞吐量
- 支持并发请求
所以显存会保持高占用。
4 推理服务的“模型保活”
很多推理框架都会设置一个 keep-alive 时间。
例如 Ollama:
默认行为类似:
模型加载
→ 请求结束
→ 保持模型在 GPU 一段时间
→ 如果长时间没人用才卸载
目的也是减少冷启动。
如何确认显存到底被谁占着
看进程:
nvidia-smi
示例:
Processes:
GPU PID Process name GPU Memory
0 21567 ollama 10976MiB
再查进程:
ps -fp 21567
如果你想强制释放显存
有三种方式。
1 杀掉进程
最直接:
pkill ollama
或
pkill python
2 重置 GPU
(会杀死该 GPU 上所有进程)
nvidia-smi --gpu-reset -i 0
3 让框架卸载模型
例如 Ollama:
ollama stop 模型名
或重启服务:
systemctl restart ollama
一个很多人第一次做推理平台才发现的事实
在推理服务器里:
显存长期 80%~95% 是正常状态。
原因:
- 模型权重
- KV cache
- CUDA pool
都常驻显存。
真正判断 GPU 是否在工作,要看:
GPU Utilization
命令:
nvidia-smi dmon
如果:
sm = 0
说明只是 占显存,没有在算。
