1. 为什么要在本地折腾大模型推理速度把一个大模型跑在自己的机器上这件事本身就挺有吸引力。数据不出本地、不用排队、想什么时候用就什么时候用尤其是做一些批量文本处理或者需要反复调试提示词的场景本地推理的体验是云端 API 给不了的。但真跑起来之后很多人会撞上同一堵墙速度太慢。我这次实测的对象是一个 27B 量级的稠密模型量化后权重文件大概 16GB 出头。第一次跑起来的时候生成速度只有14 tok/s左右。这个数字什么概念你问它一段三百字的回答得等二十多秒才能吐完交互感基本为零。而经过一轮投机解码Speculative Decoding的调优之后同样的硬件、同样的模型速度拉到了159 tok/s提升了十倍还多。这篇文章就把这中间发生的事情完整拆开讲。核心关键词是本地推理、投机解码、tok/s 调优。我会说清楚三件事为什么默认配置这么慢、投机解码到底在干什么、以及那 159 tok/s 是怎么一步步调出来的。适合已经能在本地跑起模型、但被速度卡住的同学也适合还没上手、想先搞清楚性能瓶颈在哪的人。全程不涉及任何云端服务纯本地环境。先说结论性的判断27B 这个体量的模型在消费级硬件上瓶颈几乎永远不在算力峰值而在显存带宽和内存搬运。你看到的 tok/s本质上是每秒能从显存里搬出多少个 token 所需的权重和 KV 缓存。理解这一点后面所有的调优动作才有方向。2. 先搞清楚 14 tok/s 到底卡在哪2.1 本地推理的两个阶段预填充与解码大模型生成文本分两个阶段这两个阶段的性能特征完全不同很多人把它们混在一起谈导致调优方向跑偏。预填充阶段Prefill把你输入的提示词一次性喂进去模型并行处理所有输入 token算出 KV 缓存。这个阶段是计算密集型的GPU 的算力能吃满通常很快。你输入 500 个 token可能几百毫秒就处理完了。解码阶段Decode一个 token 一个 token 地往外蹦。每生成一个新 token都要把整个模型的权重读一遍做一次前向计算。这个阶段是内存带宽密集型的。注意是每生成一个 token 就要读一遍全部权重。这就是关键。假设模型量化后是 16GB你的显存带宽是 500GB/s那么理论上每秒最多能读 500/16 ≈ 31 次权重也就是理论上限 31 tok/s。实际因为各种开销跑到 14 tok/s 完全合理。你的算力根本没被用满卡住你的是显存带宽。提示判断自己是不是带宽瓶颈看一眼 GPU 利用率就行。解码阶段如果 GPU 计算单元利用率只有 20%~40%而显存控制器接近满载那基本可以确诊。2.2 为什么单纯换更强的卡收益有限很多人第一反应是换显卡。但如果瓶颈在带宽换一张算力翻倍、带宽只涨 30% 的卡解码速度可能只提升 20% 出头。这就是为什么堆硬件在解码阶段性价比很低。真正有效的思路是减少每个 token 需要搬运的数据量或者让一次搬运产出多个 token。前者对应量化、KV 缓存压缩后者就是投机解码的核心思想。2.3 量化对速度的影响被高估了顺便说一个常见误区。很多人以为把模型从 FP16 量化到 4bit速度会线性提升 4 倍。实际上量化主要降低的是显存占用和带宽压力理论上有帮助但收益往往没有想象中大。原因是量化后的反量化计算、以及不同量化格式对 kernel 的友好程度都会吃掉一部分收益。我实测下来从 FP16 换到 4bit 量化显存占用从 54GB 降到 16GB但解码速度只从 9 tok/s 提到 14 tok/s提升约 55%。带宽账面上省了 70%实际只兑现了一半多。所以量化是必要的基础但不是速度问题的终极答案。3. 投机解码让一次搬运产出多个 token3.1 核心思想小模型打草稿大模型批改投机解码的思路其实特别朴素用生活化的类比就是让一个反应快但水平一般的小助手先写草稿然后让水平高但动作慢的专家一次性批改。具体流程是这样的用一个**小模型Draft Model**快速生成 K 个候选 token。小模型参数量小生成快比如一次能猜 5 个 token。把这 K 个候选 token 一起送给**大模型Target Model**做一次前向计算。大模型一次性验证这 K 个 token 哪些是对的。因为是一次并行验证成本约等于生成 1 个 token。如果前 3 个都对、第 4 个错了那就接受前 3 个从第 4 个位置重新采样丢弃后面的。关键在于大模型验证 K 个 token 的成本和生成 1 个 token 的成本几乎一样因为瓶颈是权重搬运而权重只读了一遍。所以只要小模型的命中率够高就能实现一次搬运产出多个 token。3.2 为什么它能突破带宽天花板回到带宽的账。原来生成 1 个 token 要读一遍 16GB 权重速度上限 31 tok/s。现在如果平均每次能接受 5 个 token那么每读一遍权重就产出 5 个 token等效速度上限就变成了 155 tok/s。这就是从 14 到 159 的数学基础。当然实际接受率不可能那么理想。小模型猜得越准接受率越高。这就引出了下一个问题草稿模型怎么选。3.3 草稿模型的三种来源来源说明优点缺点独立小模型单独训练的同系列小模型命中率通常较高需要额外显存加载模型自身层用大模型的前几层当草稿不占额外显存命中率一般自蒸馏头给大模型挂一个预测头显存开销小需要额外训练我这次用的是独立小模型方案选了一个同系列、参数量约为大模型 1/20 的版本。原因是同系列模型的 tokenizer 和分布更接近命中率明显更高。实测平均接受长度能到 4.5 左右这是能冲到 159 tok/s 的关键。注意草稿模型不是越小越好。太小了命中率低接受长度上不去太大了自己就慢拖累整体。经验值是草稿模型参数量在目标模型的 1/10 到 1/30 之间比较合适。4. 从 14 到 159 的完整调优实操4.1 基础环境与参数确认先把基础环境说清楚不然复现会出问题。我用的推理框架支持投机解码硬件是一张消费级显卡显存 24GB。模型是 4bit 量化版本权重约 16GB草稿模型约 1GBKV 缓存预留约 4GB刚好卡在显存边缘。启动参数里几个关键项--model target-model-4bit \ --draft-model draft-model-4bit \ --num-speculative-tokens 5 \ --draft-num-speculative-tokens 5 \ --gpu-memory-utilization 0.92 \ --max-model-len 8192这里num-speculative-tokens就是每次让草稿模型猜几个 token我设的是 5。这个值不是随便定的后面会讲怎么调。4.2 第一步确认基线速度调优之前一定要先测基线不然你不知道改动有没有效果。测试方法要固定同样的提示词、同样的生成长度、同样的温度参数跑三次取平均。我的基线测试用的是 200 token 的输入、生成 500 token 的输出温度 0.7。结果纯目标模型无投机解码14.2 tok/s预填充耗时约 0.8 秒解码耗时约 35 秒这个基线很重要后面每改一个参数都拿它对比。4.3 第二步开启投机解码观察接受长度第一次开启投机解码num-speculative-tokens设成默认的 5速度直接跳到78 tok/s。翻了好几倍但离 159 还有距离。这时候要看一个关键指标平均接受长度Average Acceptance Length。这个指标告诉你草稿模型平均每次猜对几个。我的日志里显示是 3.2。也就是说每次猜 5 个平均只对 3.2 个有 1.8 个是浪费的。接受长度低说明草稿模型和目标模型的分布差异有点大或者草稿模型本身能力不够。4.4 第三步调整投机 token 数量num-speculative-tokens这个参数是调优的核心。设太小收益不够设太大浪费计算。我做了个对比实验固定其他参数只改这个值投机 token 数平均接受长度实测速度 (tok/s)32.66253.27873.591103.688153.674可以看到7 是个拐点。超过 7 之后接受长度基本不再增长因为草稿模型能力就到这了但每次验证的计算量还在增加速度反而下降。实操心得这个拐点因模型而异一定要自己测。方法是固定其他参数从 3 开始每次加 2画一条速度曲线找峰值。别照搬别人的数值。4.5 第四步换更匹配的草稿模型7 个 token 的配置下到了 91 tok/s但接受长度卡在 3.5 上不去。问题出在草稿模型上。我换了一个和目标任务模型同系列、同 tokenizer、训练数据更接近的草稿模型。换完之后接受长度从 3.5 提到了4.6速度直接冲到142 tok/s。这一步的收益最大也最容易被忽略。很多人随便找个同尺寸的小模型当草稿结果命中率惨不忍睹。草稿模型和目标模型的血缘关系比参数量更重要。4.6 第五步KV 缓存与批处理微调到 142 之后剩下的提升来自细节。KV 缓存量化把 KV 缓存从 FP16 量化到 INT8显存占用降了一半腾出来的空间让num-speculative-tokens可以设到 8 而不爆显存。这一步贡献了约 8 tok/s。关闭不必要的日志推理框架默认会打印每个 token 的详细信息高频写日志会拖慢速度。关掉之后又快了约 5 tok/s。固定随机种子预热第一次推理会有各种初始化开销正式测试前先跑一轮短的预热让 kernel 编译和缓存都就位。这一步让测试结果更稳定也贡献了约 4 tok/s 的账面提升。最终稳定在159 tok/s。4.7 完整参数对照表把最终配置整理成表方便对照参数基线值调优后作用量化精度4bit4bit降低带宽压力投机解码关闭开启一次产出多 token投机 token 数-8平衡收益与浪费草稿模型-同系列小模型提高接受长度KV 缓存FP16INT8省显存日志级别详细精简减少 IO 开销5. 常见问题与排查技巧实录5.1 速度没提升反而变慢这是最常见的坑。开了投机解码速度反而比不开还慢。原因通常是草稿模型太慢或者接受长度太低。排查顺序先看接受长度如果低于 2说明草稿模型基本在瞎猜收益抵不过开销直接关掉投机解码更划算。再看草稿模型的单次推理耗时如果它自己生成 5 个 token 就要花掉大模型生成 2 个 token 的时间那也没意义。5.2 显存爆了怎么办投机解码会额外占用显存草稿模型权重 草稿模型的 KV 缓存 验证时的临时缓冲。24GB 卡跑 16GB 模型余量本来就不多。几个应对手段降低num-speculative-tokens、量化 KV 缓存、缩短max-model-len、降低gpu-memory-utilization留出安全边际。我一般把利用率设在 0.90~0.92留一点给系统避免跑着跑着 OOM。5.3 接受长度忽高忽低接受长度和输入内容强相关。代码、结构化文本这种可预测性高的内容接受长度能到 5 以上自由创作、诗歌这种发散性内容可能只有 2 出头。所以测试速度一定要用有代表性的输入。拿一段代码测出来的 159 tok/s和拿一段散文测出来的可能差一倍。我建议准备三组测试集代码、问答、创作分别测心里有数。5.4 问题速查表现象可能原因解决方向速度无提升接受长度 2换草稿模型或关闭投机显存 OOM投机开销过大降 token 数、量化 KV速度波动大输入类型差异固定测试集首次推理极慢初始化开销加预热轮次长文本变慢KV 缓存增长限制上下文长度5.5 几个容易被忽略的细节温度参数会影响接受长度。温度越高采样越随机草稿模型越难猜中接受长度越低。做速度测试时把温度固定在一个常用值别用极端值。批处理场景下投机解码收益会变化。单请求时收益最大因为带宽瓶颈最明显。多请求并发时算力开始成为瓶颈投机解码的边际收益会下降。如果你的场景是高并发调优思路要换。别迷信单一数字。159 tok/s 是在特定输入、特定参数下的结果。换个场景可能只有 100。重要的是理解调优的方法论而不是记住一个数字。6. 这套方法还能怎么扩展投机解码只是加速的一条路。同样的思路——减少单位 token 的搬运成本——还能往几个方向延伸。一是更激进的量化比如 3bit 甚至 2bit配合更好的量化算法进一步压带宽。二是层间投机不用独立草稿模型而是用目标模型自己的浅层做草稿省显存。三是Medusa 式的多头预测给模型挂多个预测头一次预测多个位置的 token本质是投机解码的变体。我自己在实际操作中的体会是调优的收益永远来自对瓶颈的准确判断。一开始我以为要换硬件后来发现是带宽问题以为量化能解决一切结果只兑现了一半最后靠投机解码加上草稿模型的匹配才真正把速度拉起来。每一步都不是拍脑袋而是先测、再看指标、再改一个变量。如果你也在本地跑模型被速度卡住建议先别急着换设备花半小时把基线测出来把接受长度、GPU 利用率、显存占用这几个指标看清楚。瓶颈找对了剩下的就是按图索骥。这套流程走下来27B 模型跑到一百多 tok/s在消费级硬件上是完全够用的。