作者:伯衡君
本地 AI 很慢?先别急着换显卡
概述
本地模型能跑,GPU 也亮着,回答却还是慢得像蜗牛。一个不起眼的小决定,可能正在把所有工作送上一条错误的通道。
你等的那段时间,其实是几只不同的表在走。第一字前的停顿、出字的速度、甚至模型重新加载,各有各的原因,各有各的解法。改错地方,一下午就白下了。
这篇拆一遍整条链路:怎么分清哪只表在慢、活儿到底是谁在干、模型和上下文各欠了多少账、哪些软件值得下、哪些纯属周末排障。
最后给一个五分钟就能跑完的诊断流程,和一套针对日常代码问答的配置建议。
机器很快,回答很慢,怪的是哪个决定
先说一个反常现象。同一个问题,云上的模型在你读完这句话之前已经答完了,本地这边按完回车,第一行字迟迟不来。
电脑不一定有问题。模型加载好了,显卡也在工作,整套东西看起来都正常,但它就是慢得离谱。
原因可能小得可笑:一个配置项把活儿送去了错误的通道。用 Ollama、LM Studio、Jan、llama.cpp,或者它们之上的任何应用,症状看起来都一样,但两段延迟背后的成因可能完全不是一回事。
还有一个坑更阴:加载最慢的模型,未必是回答最慢的。大模型启动慢,之后出字可能挺稳;小模型启动飞快,然后开始爬,因为它跑在了错误的硬件上。
机器没问题,是路走错了。
说实话,改错地方,你花一下午下载新模型,最后还是同一个糟糕体验。
所以得跟着这个 bug 报告走一遍,从按下回车到最后一个字出来,看时间到底花在哪。
把等待拆成两只表,先分清谁在慢
第一步永远是拆开。
第一是首字时间:从按下回车到看到答案开头的那段停顿。第二是生成速度:开头之后,剩下的字往外蹦得多快。
对我们那个 bug 报告,"问题在于"这句话之前那段长停顿,指向的是 prompt 处理。模型得先把你的问题、系统提示词、贴进去的代码全部读完,才能开口。
而第一行字之后的缓慢输出,更指向生成本身。模型是一个 token 一个 token 往外蹦的。
还有第三种等待,在这两只表开始走之前:加载。如果应用为了腾地方把模型卸了,它得把权重再搬回内存。这就是为什么第一次请求,明显比紧接着的第二次慢。
所以"感觉慢"没法用来诊断。
盯一下应用报的东西:模型是不是在加载?prefill 的 token 速度有没有单独显示?生成时 GPU 有没有在干活?有个大概数字,已经比瞎猜强。
如果应用什么都不显示,就用同一句短 prompt 连问两次。第一次可能带着加载和热身,第二次更能反映稳定生成。再来一句长 prompt 和一句短 prompt。短的快、代码评审那段静默特别久,说明你撞上的是另一个问题,不是出字慢。
先确认一件事:活儿到底是谁在干
改任何设置之前,先问一个更基础的问题:活儿到底是谁在干?
本地 AI 应用可以用你的显卡,可以用处理器,也可以混着用。后端也分好几条路:NVIDIA 卡走 CUDA,苹果硬件走 Metal,支持的 AMD 卡走 ROCm,还有些系统走 Vulkan。应用和模型格式,两边都得支持你期望的那条路。
假设你桌机上有 N 卡,但应用在用 CPU 推理。模型照样会回答,界面看着也正常。可那一堆并行算力全在那儿干瞪眼,处理器在拼命。
就像把搬家货车装满,然后自己一箱箱扛下楼。
去看应用的模型详情或启动日志,找选中的设备、GPU 层数、后端,以及任何 fallback 警告。Windows 上看任务管理器的 GPU 面板,但要选 compute 那类图表,别只盯 3D。macOS 的活动监视器能看到 GPU 活动,只是不太适合逐 token 排查。Linux 上边生成边看显卡利用率工具。
高占用,别当成成绩。
prompt 处理会瞬间把 GPU 打满,生成时的用法又完全不一样。
真正该问的是:你想用的那条后端,是不是真的在跑;权重是不是真的放在了那儿。llama.cpp 里的 GPU 层数设置,决定模型有多少层待在显存上,其他前端一般给你一个滑块或者自动选项。
最大的那个原因:模型本身选大了
接下来是最大的那个原因,也是最根本的原因:模型本身。
每个生成的 token,都要模型拿权重做一大坨计算。参数越大,通常吃显存越多,每个 token 的活儿也越重。量化就是把权重用更少的 bit 存下来,模型变小,更容易塞得下,很多时候还更快。代价是精度会漂,而速度收益取决于硬件和运行时。
回到那个 bug 报告:一个常规的 Python 报错,值意外取值,你要的是可能原因加修法。300 亿参数的模型能推理得很漂亮,但 70 亿或 80 亿可能已经完全够用了。
说白了,让大模型干每个小活,等于为了改一个变量名,把整条构建流水线开起来。
改一个变量名,开整条流水线。
看模型的真实文件大小,还有应用里的内存估算。下载包大小不等于运行时的全部开销:运行时还得给 KV cache、临时缓冲、系统本身留出空间。cache 存的是之前 token 的信息,让模型接着聊的时候不用把整段重读一遍。上下文越长,这块 cache 长得越快。
第一次实验怎么做?同一句 prompt 不动,换一个常见的 4 bit 量化的更小模型。GGUF 库里像 Q4_K_M 这类名字通常表示 4 bit 档,Q5、Q6 保留更多精度但吃更多显存。具体大小和速度随架构而变,别拿别人的数字当自己的。
上下文窗口有一笔内存账单
目标不是崇拜最小的模型,是用能胜任的最小那个。
现在看另一块:能让一个本来挺合适的模型变得更难用的东西——它要背的对话量。
那个"200 行的函数"未必是助手在读的全部。系统提示词、聊天历史、检索到的文件、贴进去的日志,全都算上下文。输入越长,模型在开口之前要干的活儿越多。而用来跟踪上下文的 cache,也在吃内存。
这就造成了两种不同的慢。长 prompt 会拖慢首字,因为模型得先把它处理完。大上下文还会挤掉留给模型权重的显存,逼着部分层溢出到慢速内存,或者直接 OOM。
那上下文该留多少?
如果你因为滑块允许,就把上下文限制设成 128K,可对话里其实只有 4K token——Ollama 的文档里,小于 24 GiB 显存的卡默认上下文就是 4K。
为 3% 的对话,预留了一大堆内存。
对我们那个 bug 报告:错误在单个函数里,就别把整个仓库贴进去。错误信息、那个函数、调用它的代码,够了。
如果应用有仓库检索,看看它实际加了什么。有的工具只取相关文件,有的悄悄塞进巨大块。这个功能能省时间,但一次噪音检索,会造出一个超长 prefill,还把关键代码埋了。
话说回来,这个不用换模型就能测:同一句话,带全量上下文跑一次,裁剪之后再跑一次,看首字时间差多少。
关掉你不需要的工作
还有一类"AI 很慢",跟模型一点关系都没有:应用在让模型干额外的活。
本地聊天应用可能同时加载多个模型:一个留给文档检索的 embedding 模型,一个留给看图的视觉模型,再加一个给另一个聊天窗口的语言模型。
多加载一个模型,到底图什么?
方便是方便,内存先崩了。
它们共享同一笔显存预算。主模型可能被挤下显卡,甚至根本装不进去。
关掉其他 AI 应用,卸载不用的模型。如果主模型变快了,内存压力就是其中一环。
Ollama 的文档里也提到,并发请求数和上下文长度都会影响所需内存,同时保留多个模型还得看塞不塞得下。换句话说,大上下文加上多个并发会话,能悄悄把一个内存问题变成三个。
再看按下回车之后发生了什么。带联网搜索、代码执行或文档索引的工具,会在你看到答案之前多跑好几步。这可能有价值,但那不是模型的裸速度。把工具关掉,用同一个请求再试一次,就能把助手的编排开销和模型响应时间分开。
还要看输出上限。说实话,如果它在一千 token 的长篇里给你回答,而你只要三句话,模型就在为你没要的字数花时间。要求简洁回答,界面允许就设一个合理的最大输出长度,别写那种让它复述整段输入的话术。
瓶颈不一定是显卡
那如果模型在正确的地方,prompt 也不长,它还是爬呢?
现在看硬件,以及软件能修到什么程度。
生成时,本地模型要反复读取自己的权重。所以显存带宽很重要。算力很多但显存不够的显卡,可能连模型都装不下。带统一内存的笔记本能把同一池内存给 CPU 和 GPU 共用,这让更大的模型变得可能,但它的内存并不比每块独显都快。
纯 CPU 机器上,核数也不是全部。内存带宽、支持的指令集、运行时的 CPU kernel,全都会影响速度。一颗核数更少但更新的处理芯,在某个具体模型上能赢过一颗老的多核芯片。所以别只拿核数比两台机器。
再确认系统有没有在换页到磁盘。整机发卡、磁盘忙碌、模型几乎不流式输出,这三样凑一起,基本就是物理内存不够了。关掉吃内存的应用,压低上下文,或者换更小的量化。
加内存能救一台一直在换页的机器,但它不会把一颗慢 CPU 变成一块快显卡。
笔记本电源设置也得管。省电模式会限 CPU 和 GPU。放在软垫上散热不畅,也会降频。插电、临时切到性能模式做对比,让出风口能喘气。
回头看,关键是分清:哪些是软件能修的,哪些是硬件天花板。
软件能修的修,修不动的认。
值得下的那些软件
聊聊大家常推荐的下载,有些是真捷径,有些是把周末排障伪装成捷径。
从最简单的开始:升级你已经在用的应用。新版本可能加模型支持、修显卡识别、改进 kernel。如果你当初误装了纯 CPU 版本,装对 GPU 版本可能比应用里任何设置都重要。
从官方项目拿,换运行时之前先看发布说明里对你硬件的说明。
装错的版本,比什么都耽误事。
NVIDIA 用户确认应用支持 CUDA,且驱动版本够得着它要求。苹果芯片用支持 Metal 的应用。AMD 的支持差异更大,跟操作系统、卡代数、运行时都相关,去看具体产品的兼容列表,别照着别人那张卡的教程走。
不支持你设备的下载,不是捷径,是折腾。
愿意用终端的人,llama.cpp 是个广泛使用的推理层,支持 CPU 和多种 GPU 后端,能暴露 GPU 层数、上下文大小、batch size、flash attention 这些旋钮。灵活性是好事,但错误的设置也能把事情弄得更糟。
想省事,现在的 Ollama 或 LM Studio 就能替你处理大部分后端设置。对比它们时,固定模型和 prompt,确认每个应用用的是同一个设备。
换一个模型文件,也可能是一次值得的下载:更小的参数量、或者更合适的量化档位。
五分钟诊断法
第一步,关掉其他本地模型和重型应用,重启同一个模型,同一句短问题问两次,写下延迟属于加载、首字时间,还是生成。
第二步,看运行时日志或模型面板,确认后端和设备。GPU 本该在跑却没在跑,先修这个。它在跑但几乎全部权重都在系统内存里,就换更小或更激进的量化。
顺带看系统内存和磁盘活动,别只盯 GPU 占用。
第三步,用一句短 prompt 和一句长 prompt 各跑一遍。首字延迟差别巨大,说明 prompt 或上下文该动刀:减聊天历史、压上下文上限、少检索几个文件。两次都慢在生成本身,就聚焦模型大小、内存后端和电源限制。
第四步,一次只改一个。
模型、运行时、上下文、GPU 设置一起换,你永远不知道是哪个起了作用。
留一张小笔记:模型名、量化档、上下文设置、首字时间和大概的出字速度。你不是要做基准测试,你是在找一套对这个任务感觉更好的配置。
还有一点:基准数字不是对每个 prompt 的承诺。公开测试用的 prompt、硬件、上下文、batch 和软件版本都可能不同。同样的每秒 token 数,换组条件就能变成另一个数。
回到开头那个问题:到底该怎么配
所以本地 AI 到底为什么慢?
最常见的四种:模型干的活比任务需要的多,模型或它的 cache 装不进快内存,运行时用错了后端,或者长 prompt 在生成开始之前就吃掉了时间。
解法取决于哪只表在慢。
第一个值得选的是:一个被广泛支持的 70 亿或 80 亿参数的模型,常见 4 bit 量化,走更新过的应用,在有显卡的时候让它在显卡上跑,上下文上限按你实际发送的代码量来定。
旁边留一个大模型,留给更难的推理、更长的文件,或者质量比速度更重要的时候。
这个推荐之所以成立,是因为它同时打掉了通常那几个瓶颈:每个 token 的工作量、装进快内存的概率、以及需要处理的无关 token 数量。
纯 CPU 机器,再往小一档走,配一个为 CPU 优化的运行时。日常任务真需要深推理,就上大模型,接受更慢的回答。当前模型已经装得下、后端也选对,就先动 prompt 长度和电源设置,别急着买新显卡。
下次助手在简单 bug 前卡住时,先别假设电脑太弱。
看看哪只表在慢,看看模型跑在哪,让请求配得上这台机器。那次意外的升级,可能是你终于不再要求一个模型干所有事。
篇后寄语
所谓“慢”并非单一的抽象概念,而是由加载耗时、首字响应延迟、内容生成速率三个独立维度共同构成的观测序列:调优的第一要务,是先精准定位当前拖慢链路的核心维度,再着手针对性调整。
性能优化的核心杠杆从来不在于硬件规格的堆叠,而在于模型规模与上下文窗口长度这两项核心配置——二者共同决定了单Token计算的负载量级与显存资源的消耗账单。
调优过程必须遵循单变量控制原则,每一次参数调整后都要留存完整的观测日志:若一次性修改四处参数后得到了提速效果,你永远无法定位真正生效的变量,下次遇到同类问题时依旧会陷入混沌。
伯衡君建议即刻按照第九节给出的标准化流程完成一次全链路测试:固定单条短平快的测试请求,分别记录加载、首字输出、内容生成三个阶段的延迟数据,再依次调整模型量化档位、上下文长度上限、推理后端选型三类参数。绝大多数场景下,你在第三步调整完成前就能精准锁定性能卡点。
若要进一步深究性能本质,可从三个核心模块切入:KV缓存的内存分配逻辑、GGUF各量化档位的精度与性能权衡逻辑、llama.cpp的GPU分层加载参数——彻底厘清这三块核心机制,你便能成为那个仅凭直觉就能定位推理链路瓶颈的核心玩家。
概念释义
- KV cache:模型记住对话历史的记账本。每生成一个 token 就往里记一笔,之后接着聊时不用把前面重读一遍。对话越长,这本账越大,显存吃得越凶。
- Q4_K_M 量化:把模型权重从高精度压缩成大约 4 个 bit 一份来存。模型变小、更容易塞进显存、通常还更快,代价是精度会有些漂。Q5、Q6 保留更多精度,但更吃显存。
- 首字时间:从你按下回车,到屏幕上蹦出第一个字的那段停顿。这段慢通常是模型在读你的输入,跟后面出字的速度是两回事。
以上,既然看到这里了,如果觉得不错,随手点个赞、收藏、转发三连吧,如果想第一时间收到最新黑科技,敬请关注行运设计师。
谢谢你看我的文章,我们,下次再见。
参考资料
- Ollama 官方文档:Context length 与显存档位对应的默认上下文说明
- llama.cpp 运行时参数文档(GPU 层数、上下文大小、batch size、flash attention)
- GGUF 格式与量化档位(Q4_K_M / Q5 / Q6)说明
- NVIDIA CUDA、Apple Metal、AMD ROCm 运行时的硬件兼容列表
热门跟贴