本地跑模型时最常见的两难:全塞进显卡很快但显存不够,全靠 CPU 又慢得没法用。num_gpu 就是控制「多少层交给显卡」的开关。这篇不背参数,讲清它跟显存、层数、速度的关系,给一套从小往大试的顺序,以及什么时候该放弃调它换别的路子。
本地跑模型最常遇到的两难:全塞进显卡很快但显存不够,全靠 CPU 又慢得没法用。ollama 环境变量 num_gpu 就是控制「多少层交给显卡」的那个开关,它不改变模型精度,也不改变上下文长度,只决定有多少计算被搬到 GPU 上。
这篇不背参数表,讲清它跟显存、层数、速度三者的关系,给一套从小往大试的顺序,以及什么时候该放弃调它、换别的路子。所有跟层数和显存有关的临界值都随模型和量化档变化,文中提到数字的地方一律写成「去站内页面按自己的模型现算」。
num_gpu 到底在控制什么
它的作用是决定模型有多少层被放进显存跑,剩下的留给 CPU 和内存。层数越多,GPU 承担的计算越多,出字通常越快;但显存占用也同步上涨,一旦越过物理上限,驱动就会把数据挪到共享内存里,速度断崖式下跌,反而比少卸几层更慢。
- 层数需要跟模型结构对齐,填得超过总层数不会更快,可能直接报错或被忽略
- 填一个跟默认值等价的数字,效果和默认没差别,白白多一次调试
- 它只管卸载哪些层,不管上下文和并发,别指望靠它解决显存总账问题
- 凡是跟具体层数、显存数字有关的结论,都去 /tools/speed-test 按自己的模型和量化档核对当时的数字
| 现象 | 更可能的原因 | 先调哪里 |
|---|---|---|
| 首字等很久 | 上下文太长或预处理在 CPU | 先缩减上下文,再看卸载层数 |
| 出字速度慢 | GPU 层数偏少或显存被挤 | 逐步加 num_gpu,看显存曲线 |
| 速度忽快忽慢 | 显存吃紧被挪到共享内存 | 减少卸载层数或换小量化档 |
| 启动就报错 | 层数超出模型总层数 | 改回默认或按模型结构取值 |
怎么定层数:从一个能跑起来的起点往上加
- 先跑一次基线不设 num_gpu,让 ollama 自己判断,跑一次并记录显存占用、首字延迟、生成速度三个数,这就是你的起点。
- 每次只加一档手动逐步加层,一次只动一档,每次改完都重启服务,重复记录同样三个数,别只看速度这一个指标。
- 越界就退回出现显存吃紧、被系统挤到共享内存、速度反而掉下来,说明这一档越界了,退回上一档作为日常配置。
- 看场景决定要不要拉满只有显存余量明显富余、且同一时间只跑一路请求时,才适合把层数拉满;多路并发时拉满大概率互相挤爆。
这套流程的核心是「一次只动一个变量」。如果你同时改了量化档又改了层数,最后速度变了根本说不清是谁的功劳。把每一档的三个数字记在一张纸上,比凭感觉调要可靠得多。
调 num_gpu 不是找一个最优数字,而是找一个「显存够用且速度能接受」的区间。落到区间里就够了。
这几种情况调 num_gpu 收益有限
有些人花了半天加加减少,发现速度几乎没动,那是因为瓶颈根本不在卸载层数上。下面几种情况,继续折腾这个变量属于方向错了,先把注意力挪到别处。
- 模型本身太大,显存连一小部分层都放不下,调它只是从很慢变成稍微没那么慢,该考虑换更小的量化档或更小的模型
- 瓶颈在上下文长度或并发数时,卸载更多层也救不了,得回到显存总账上重算
- CPU 内存带宽本来就吃紧的机器,把层交给 CPU 反而更慢,这时候减少卸载层数才是对的方向
- 只看总耗时容易被误导,要把首字延迟和出字速度分开看,两者的解法完全不同
判断依据就是看时间花在哪。首字等太久,多半是预处理和上下文在拖;出字速度慢,才轮到 num_gpu 出场。分不清这两点,调参就成了碰运气。什么情况下这条建议不适用?当你只有一个固定模型、固定上下文、单并发的小场景,那随便试几档就能找到能用的值,不必上这套分析。
设置方法与改完怎么验证
环境变量有两种生效方式:随服务启动时传入,或写进系统级、用户级配置后重启服务。改完不重启等于没改,这是最常见的白忙一场。尤其是用后台服务方式跑 ollama 的场景,很多人改了配置文件却忘了重启进程。
| 验证点 | 看到什么算正常 | 不正常怎么办 |
|---|---|---|
| 启动日志 | 识别到 GPU 和卸载层数 | 没识别到就检查驱动和配置是否被读到 |
| 运行显存 | 占用稳定、不触顶 | 触顶就退回上一档 |
| 首字延迟 | 在可接受范围内 | 偏高等检查上下文长度 |
| 出字速度 | 比纯 CPU 明显提升 | 没提升甚至更慢说明卸载方向不对 |
把这套流程跟 /tools/speed-test 里的显存估算一起用,先算再试,比纯靠盲试省时间。估算是给你一个起点范围,实际还是要用运行数据校准。另外,同一台机器上多模型共存的场景,给每个模型留的显存预算要分开算,不能按单个模型的最优值配。
下一步想知道自己机器上这款模型大概能卸多少层、显存怎么分配,去站内按模型现算一遍再动手,比照抄别人的配置靠谱。→常见问题
设了 num_gpu 但速度没变化,是哪里不对?
先确认服务真的重启了,很多改动没重启就不生效;再看日志里有没有识别到显卡。如果显存占用和之前一模一样,说明这个值没被采纳,可能语义跟你想的不一样,或者当前模型结构不允许这样切分。
num_gpu 设得越大是不是一定越快?
不一定。它受显存容量限制,超过可用显存会退到共享内存,速度可能比少卸载几层还差。另外多路并发时显存要分摊,拉满容易互相挤。所以判断标准是「不触发显存回收的前提下尽量多卸载」,而不是越大越好。
显存很小的机器还值得调这个变量吗?
值得,但期望要放低。它能让一部分层跑在显卡上,比纯 CPU 快,但快不了数量级。如果目标是稳定可用,优先考虑换更小的模型或更低比特的量化档,调层数是最后一步微调。