本地大模型从14到159 tok/s:量化与投机解码调优实战

📅 发布时间:2026/10/17 8:22:28
本地大模型从14到159 tok/s:量化与投机解码调优实战
如果你也折腾过本地大模型大概率对这样的场景不陌生模型加载完了提示词也打出去了然后终端里的光标就那么慢悠悠地往前爬。我第一次把这套东西跑起来时面前是一个叫 Qwen3.8-27B 的本地模型屏幕上跳出来 14 tok/s。我当时盯着这个数字看了半天一度以为量化出了问题或者显卡没接上电。后来经过一整轮配置排查和投机解码调优同一个模型在同一台机器上跑出了 159 tok/s速度翻了十倍以上。这篇就是完整的实测记录我从哪里开始测的、中间换了哪些配置、投机解码的收益到底是怎么算出来的以及那些文档里不会写清楚的坑。如果你手头已经有 20GB 以上显存的显卡也想压榨本地模型的生成速度这篇应该能帮你少走不少弯路。1. 从14 tok/s开始这台机器和这个模型为什么这么慢1.1 开箱即跑的配置长什么样先说硬件环境方便你对号入座一台消费级工作站CPU 是 16 核 32 线程内存 64GB显卡 24GB 显存系统盘和模型盘都是 NVMe SSD。这个配置在本地跑 27B 级别模型属于“刚好摸到门槛”的状态也是社区里最常见的部署档位。模型方面直接用标题里的 Qwen3.8-27B最开始我拉的是 Q8 量化版本想着精度高一点总没错。当时我还特意确认了显存——24GB 放不下一个完整的 Q8 版 27B 模型于是走了一个最常规的妥协思路把一部分层留在 CPU 上其余层放进 GPU。结果就是这个“常规思路”让我的生成速度只有 14 tok/s。现在回头看这其实是一个非常典型的开箱配置模型精度高、显存放不下、CPU 承担了大量计算、GPU 和内存之间来回搬运权重。如果你也是这么跑起来的那 14 tok/s 真的一点都不意外。1.2 14 tok/s 是怎么测出来的在继续往下之前先交代一个容易踩坑的测量口径。跑本地模型时token/s 分两段预填充阶段的 tokens/s 和生成阶段的 tokens/s。预填充是处理你输入的那段提示词生成是逐个往外蹦回答词。很多新手拿一个总时间除以总 token 数结果把两个阶段混在一起数字高得离谱或者低得离谱。我这里说的 14 tok/s 是纯生成阶段的速度。测试方法很简单固定一段 20 行的提示词让模型生成 256 个 token用秒表记录总耗时再除以 256。为了减少波动我同一个配置跑了 5 次取中位数。实际上框架自带的基准工具会把 pp 和 tg 分开报建议直接用内置工具别自己写脚本计时否则会混进解析 prompt、加载上下文的开销。那段期间我还看了一眼系统资源GPU 利用率一会儿 40% 一会儿 5%内存保持在读取峰值。看到这个波形图基本就能判断瓶颈不在计算而在数据的搬运。1.3 慢的根源内存带宽和层搬运本地推理有个特别朴素的规律自回归生成一个 token约等于把整个模型权重从头到尾读一遍。所以极限生成速度约等于内存带宽除以模型大小。带宽越高、模型越小生成越快。Q8 版的 Qwen3.8-27B 接近 28GBDDR4 内存的实际带宽大约 40~60GB/sGPU 和内存之间还要走 PCIe。你算一下28GB 的模型权重加上反复搬运和 CPU 计算14 tok/s 基本上就是这套组合的物理上限——不是某个参数没调好是硬件状态决定的。这也是为什么很多人推荐本地跑大模型优先看“量化版 能完整塞进显存”的组合。如果模型不能完全进显存哪怕 GPU 再强也只能在 PCIe 带宽的瓶颈上干瞪眼。这个认知是整个调优过程的第一步先让模型在正确的位置上跑起来再去谈加速技巧。2. 投机解码在“投机”什么原理、公式与收益边界2.1 用实习生打草稿、专家终审来理解投机解码这个名字听起来很玄但核心思想特别朴素与其让那个 27B 的大模型一个字一个字地慢慢蹦不如先让一个小模型飞快地写出一串候选词然后让大模型一次性审核这串候选词把对的留下把错的改掉。我把这个过程类比成“实习生打草稿、专家终审”。实习生速度很快但质量不稳定专家看一眼草稿能一口气确认好几处没问题的地方只在不对的地方停下来重写。如果实习生靠谱专家原本要逐字逐句审十几次的工作一次能确认七八个词效率自然就上来了。实际操作上小模型逐个生成 γ 个候选 tokenγ 就是草稿长度然后把这一串 token 拼在一次前向计算里交给大模型。大模型用这些候选并行预测下一步逐位检查是否匹配。这个过程最反直觉的地方在于大模型同时验证多个 token 的耗时和验证单个 token 差不多因为自回归导致的串行依赖被打断了GPU 可以一次并行处理。2.2 理论加速比接受率与草稿长度的组合投机解码提速多少取决于两个核心变量草稿模型被接受的比率 r和每次送审的草稿长度 γ。如果每轮大模型验证 γ 个 token其中有 r 比例被接受理论上每轮能产出 (r × γ 1) 个有效 token那个 1 是大模型强制纠错补出的 token。理想情况下草稿模型耗时忽略不计加速比近似等于 r × γ 1。假设接受率 0.7、草稿长度 7理论加速就是 0.7 × 7 1 5.9 倍。这就是为什么公开发布的数据里投机解码跑出两三倍、三四倍加速是很正常的事情。我这次从 45 tok/s 跳到 159 tok/s大约 3.5 倍完全符合这个公式量级。但注意另一个关键现象是接受率会随草稿位置衰减第一个候选通常很容易被接受第三个、第五个的接受率就一路下滑。所以草稿长度不是越长越好长度太长时后面的候选大多是无效计算草稿模型反而成了新的瓶颈。这个坑我在后面调参的部分还会详细说。2.3 投机解码不适合的场景投机解码不是万灵药有三种场景它的收益会打折扣。第一种是模型回答的熵特别高的场景比如自由创作、头脑风暴式发散回答。大模型自己都不知道下一句要写多离谱小模型更难押中接受率会掉到 0.5 以下。第二种是短问答应用投机解码只加速生成阶段对预填充阶段基本没有帮助如果用户问一句你就答一句短的整个提速收益会被首 token 延迟稀释。第三种是模型本身已经跑到内存带宽上限且没有显存余量放草稿模型的情况硬上投机解码反而得不偿失。所以在动手调优之前先判断自己的场景适不适合。代码生成、数学题、表格填充、结构化输出这些低熵场景投机解码的收益最大文艺创作类的不如去优化采样参数。3. 重建基线量化选型、GPU卸载和上下文长度3.1 量化版本不是越低越好聊清楚原理之后我做的第一件事不是立刻上投机解码而是先把基础配置摸对。因为 159 tok/s 不是某一个技术单独带来的而是“整个配置从错误到正确”的综合结果投机解码只是其中最关键的一环。第一步是换量化。我一开始用 Q8 的原因是想保精度但代价是显存放不下只能搀着 CPU 一起跑。我后来换成了 Q4_K_M同样是 Qwen3.8-27B这个版本大概 17GB 左右24GB 显存完全放得下。Q4_K_M 和 Q8 的精度差异在实际推理任务里多数时候体现不出来但速度差异非常明显——因为整个模型能完全落进显存了。这里做一个粗略计算24GB 显卡的显存带宽在 300~500GB/s 区间17GB 的模型权重每生成一个 token 读一遍理论极限大约 20~30 tok/s远远好于之前靠 CPU 和内存搬运的 14 tok/s。如果你也卡在“模型太大、显存太小”这个坎上我的建议是优先选 4bit 量化并确保完整进显存不要贪 Q8。显存剩余空间可以用来放 KV cache也可以留给后面投机解码的草稿模型。3.2 GPU装得下多少层模型进显存之后还有一个容易被忽略的环节解析 prompt 阶段占用多少显存、KV cache 要预留多少。很多人在部署 27B 模型时把 max_model_len 直接拉到 32K结果模型刚加载完就 OOM或者稳定跑了一段时间后突然崩溃。我这次的显存账本大致是这样的Q4_K_M 模型约 17GBKV cache 在 4K 上下文下约 2~3GBCUDA 上下文和其他缓冲约 1~2GB。算下来 24GB 刚够。如果我把上下文长度从 4K 改到 16KKV cache 会成倍增长投机解码的草稿模型连站的地方都没有。所以这里的原则是先明确你到底需要多长的上下文再据此分配显存。只做普通对话和代码补全的话4K~8K 足够别为了“以防万一”把上下文拉满那是本地推理 OOM 的第一大原因。3.3 基线复测45 tok/s 是怎么来的配置调整完之后我重新用同一段提示词测了生成速度结果从 14 tok/s 直接跳到 45 tok/s 左右。这个跳跃基本全是“量化 完整进显存”带来的和投机解码没关系。我还顺手对比了 GPU 利用率曲线稳定在 95% 上下不再像之前那样忽高忽低。这个信号很重要——说明模型权重读取已经不再通过 PCIe 来回搬运瓶颈从“搬运”变成了“纯计算”。确认基线稳健之后才轮到投机解码上场。这一步我给出的实战建议是在你上任何投机技巧之前先保证基线配置能让 GPU 利用率稳定在 90% 以上。否则不加分析就开投机解码你可能根本分不清提速是投机解码带来的还是基础配置修复带来的。4. 投机解码落地草稿模型、γ参数与显存权衡4.1 草稿模型的三个选型标准投机解码的核心是草稿模型选得好不好直接决定接受率。我这次试了三个方向最后形成一个明确结论草稿模型的选型标准不是“越小越好”而是“同系列、小尺寸、量化适中”。首要标准是同系列。我用的是 Qwen 系列的一个小模型做草稿因为同一个系列的 tokenizer、语言习惯和对齐方式是一致的小模型更容易猜中大模型的下一步选择。跨系列的小模型哪怕整体能力看起来不差接受率也会明显下降因为它和大模型的“思维习惯”不一致。其次是尺寸。草稿模型如果太大虽然接受率高但草稿生成本身耗时太长节省的时间被抵消如果太小又猜不准。我实测下来0.6B 到 1.7B 这个区间最适合给 27B 大模型当草稿。第三是量化。草稿模型不需要特别高的精度Q8 版本就够了显存占用控制在 1~2GB 内既省显存推理速度也够快。4.2 关键参数怎么调不同本地推理框架对投机解码的命名不太一样有的叫 draft model有的叫 speculative decoding。下面这段示意命令只是展示参数结构具体名称以你用的框架文档为准# 示意通过本地推理服务加载主模型和草稿模型 serve Qwen3.8-27B-Q4_K_M.gguf \ --draft-model Qwen3-small-Q8_0.gguf \ --speculative-draft-length 7 \ --max-model-len 8192核心参数就三个草稿模型路径、草稿长度、最大上下文长度。最容易调反的地方是草稿长度——我一开始用 γ14想着草稿越长越好实际跑下来反而比 γ7 慢。原因就是前面说的接受率衰减第 10 个以后的基本都在做无用功草稿模型生成 14 个 token 的时间倒是实打实花出去了。4.3 草稿长度 γ 对速度的影响我把不同 γ 值跑了一轮完整测试生成同样 256 个 token结果如下表接受率约 0.7~0.75温度设为 0草稿长度 γ每轮平均产出 token 数实测生成速度33.1102 tok/s54.5128 tok/s75.9152 tok/s108.0159 tok/s1410.2148 tok/s可以看到γ10 的时候速度到了 159 tok/sγ14 反而掉回 148 tok/s。这组数据特别能说明问题草稿长度不是越大越好每台机器、每个模型组合都有自己的最优区间。我最后保留在 γ10这个值在长文本测试下最稳定。4.4 显存账本模型、草稿与 KV cache 的三角博弈投机解码落地还有一个容易翻车的地方——显存。很多人只算了主模型占多大忘了草稿模型也要额外吃显存而且草稿模型本身也会产生 KV cache。我当时的显存大致是这样主模型 Q4_K_M 约 17GB草稿模型 Q8 约 1.2GB主模型 KV cache8K 上下文约 4GB草稿模型 KV cache 约 0.5GB加起来已经非常接近 24GB 上限。如果我在这一步还用 16K 上下文KV cache 直接翻倍草稿模型就没地方放了。所以我的建议是先留足主模型和 KV cache 的空间再看剩余显存决定草稿模型的上限。宁可草稿模型小一点也不要为了它压缩 KV cache 导致长上下文全都崩掉。5. 从90到159采样参数和最后一公里的优化5.1 温度与接受率的关系投机解码落地之后我已经能稳定跑到 120~150 tok/s 了。但很快我发现一个有意思的现象采样参数对投机解码的接受率影响极大而这恰恰是很多教程不会提的细节。原理并不复杂投机解码的接受率本质上是“草稿模型和大模型的采样分布有多接近”。当温度调低时模型倾向于选择概率最高的那个 token两个模型的最高概率选择很容易一致接受率自然高。温度调高时模型会去抽那些概率没有那么高的 token草稿模型和大模型的选择更容易分叉接受率掉得很快。我实测了一组数据同一份代码生成任务、同样的硬件采样温度典型接受率实测生成速度0.00.82152 tok/s0.60.73138 tok/s1.20.61117 tok/s如果你的应用允许把温度调低比如代码补全、结构化输出那投机解码的收益会非常明显。反过来如果你必须用高温度做创意生成可能要接受加速比缩水的事实别被低温柔和场景下的数据冲昏头脑。5.2 长文本测试中 token/s 的波动跑到 159 tok/s 之后我一开始还挺兴奋但冷静下来发现这个数字是在理想条件下测的——短提示词、短生成、固定任务。真要评估稳定性得用长文本连续生成来测。我把测试改成这样生成 1024 个 token每 128 个 token 记录一次实时速度。结果很有意思前 256 个 token 的速度能稳定在 150 tok/s中间偶尔跌到 140 左右接近结尾时又回到 155 上下。整体波动在合理范围内说明这套配置的稳定性是过关的。这里值得提醒一点token/s 波动有可能是投机解码的接受率随文本分布变化的正常现象。代码里有一大段重复模板时小模型很容易猜中速度会冲高到了需要逻辑转折的地方接受率下降速度就下来了。不要因为某一段掉到 130 就觉得配置坏了这是投机解码的天然属性。5.3 首token延迟和API开销是两个被忽略的指标最后我想专门泼一盆冷水159 tok/s 是模型生成循环里的速度不是你在应用里感受到的全部速度。投机解码对首 token 延迟TTFT的改善基本为零因为首 token 的瓶颈在于预填充阶段投机解码只作用于生成阶段。如果你的业务是“短问题 短回答”你会发现整体响应速度的提升远没有 3.5 倍那么多。另外如果你通过 HTTP 接口调用模型还要算上网络传输、请求排队、框架调度的开销。我实际压测下来纯推理端是 159 tok/s走 HTTP 接口后吞吐大概掉到 120~130 tok/s。所以评估投机解码收益时一定要把测量点放在你的真实调用链路上而不是只看终端里的数字。6. 同一模型、不同配置的实测数据汇总6.1 完整对比表把整个调优过程串一遍就是下面这张表。同样一个 Qwen3.8-27B不同配置的差别非常大配置描述生成阶段速度关键瓶颈Q8 量化部分层在 CPU内存搬运14 tok/sPCIe/内存带宽Q4_K_M完整进显存自回归45 tok/s显存带宽Q4_K_M 投机解码 γ7152 tok/s草稿模型质量Q4_K_M 投机解码 γ10159 tok/s接受率衰减Q4_K_M γ10 温度 1.2117 tok/s采样熵过高这组数据最值得记住的信息是从 45 到 159 的加速是投机解码的核心贡献从 14 到 45 的加速和投机解码无关纯粹是基础配置修正的结果。所以如果别人跟你吹“投机解码从 14 提到 159”大概率是含糊了中间那一步——先让模型正确地跑起来再谈投机技巧。6.2 数据口径说明这些数字都是在同一台机器、同一个模型文件、同一个长文本测试任务下得到的。换显卡、换内存、换驱动绝对数值都会变但趋势和比例是可信的量化进显存解决“能不能快”的问题投机解码解决“快上加快”的问题采样参数解决“快多少”的问题。另外我在测试时把 GPU 驱动和推理框架都升级到了当前稳定版本。遇到过旧版框架的投机解码实现有显存泄漏问题跑 20 分钟后速度骤降升级之后恢复正常。如果你发现投机解码越跑越慢第一反应应该是查框架版本而不是急着改参数。7. 这次折腾过后我的一些经验判断7.1 投机解码值不值得上我的判断是如果你的显存有富余、场景是代码或者结构化输出、而且你对延迟有要求那投机解码是目前本地推理里最值得做的单项优化。它不会改变模型本身的输出质量只是让生成变快属于典型的“白捡性能”。反过来如果你的模型已经贴着显存上限跑了一点多余显存都没有或者你的场景是高温度的自由创作那投机解码的性价比就一般。强行上会导致显存 OOM或者因为接受率太低而没快多少还多了一份调参负担。7.2 几个值得记住的坑整个调优过程中我踩过的坑汇总起来就这么几条第一量化和显存适配是前提模型不全进显存任何投机技巧都白搭第二草稿长度要实际测试不要拍脑袋选最大第三采样温度是投机解码的隐形开关低温场景收益远大于高温场景第四KV cache 和草稿模型都在抢显存上下文长度别盲目拉满第五token/s 的测试口径一定要统一别把预填充和生成阶段混在一起。7.3 还能怎么继续压榨最后分享两个我觉得可以继续深挖的方向。一个是多级投机解码用更小的模型给草稿模型当草稿理论上能进一步压低草稿生成时间但调度复杂度和显存开销都会上升。另一个是接受率诊断通过框架日志观察每轮接受率如果发现自己场景的接受率长期低于 0.6那说明草稿模型选得不合适而不是参数没调好。这次调优给我最大的感受是本地推理从来不是单一技巧的胜利而是一个“先找对瓶颈、再逐个击破”的系统工程。从 14 到 159我在投机解码上花的时间其实只占一小半另外一大半都花在搞清楚“为什么慢”上。弄清楚这一点你手里的每一台机器都能榨出比自己想象中更高的吞吐量。