<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Speculative Decoding on Hypho - AI Agent 技术博客</title><link>https://blog.hypho.cn/tags/speculative-decoding/</link><description>Recent content in Speculative Decoding on Hypho - AI Agent 技术博客</description><image><title>Hypho - AI Agent 技术博客</title><url>https://blog.hypho.cn/papermod-cover.png</url><link>https://blog.hypho.cn/papermod-cover.png</link></image><generator>Hugo -- 0.148.2</generator><language>zh-cn</language><lastBuildDate>Wed, 10 Jun 2026 10:07:04 +0800</lastBuildDate><atom:link href="https://blog.hypho.cn/tags/speculative-decoding/index.xml" rel="self" type="application/rss+xml"/><item><title>1T 模型跑出 1000 tok/s：MiMo × TileRT 的模型-系统联合设计到底做了什么</title><link>https://blog.hypho.cn/posts/mimo-tilert-1000tps-trillion-parameter-inference/</link><pubDate>Wed, 10 Jun 2026 10:07:04 +0800</pubDate><guid>https://blog.hypho.cn/posts/mimo-tilert-1000tps-trillion-parameter-inference/</guid><description>小米 MiMo-V2.5-Pro 与 TileRT 合作，在 8 卡 GPU 节点上让 1T 参数 MoE 模型首次突破 1000 tokens/s 生成速度。本文拆解实现这一数字的三层技术栈：FP4 选择性量化、DFlash 块级投机解码、以及 TileRT 的 Tile-Based 持久执行引擎，并分析&amp;#34;模型-系统联合设计&amp;#34;这一新范式对推理基础设施的实际意义。</description><content:encoded><![CDATA[<p>一个万亿参数的模型，在 8 张消费级 GPU 上每秒吐出 1000 个 token——这件事本身并不新鲜，因为类似数字过去只在论文 demo 或特制硬件上见过。但小米 MiMo 团队和 TileRT 推出的 MiMo-V2.5-Pro-UltraSpeed，用的是商品化 GPU、开源推理框架、没有定制芯片。这就有意思了。</p>
<p>更关键的是，实现这个速度的路径不是&quot;把量化做狠一点&quot;或&quot;投机解码多猜几个 token&quot;这么简单。它触及了一个更根本的问题：<strong>当推理系统逼近硬件物理极限时，模型架构和推理引擎必须从设计阶段就开始同步进化，而不是各自优化完再拼到一起。</strong></p>
<p>这篇拆解 MiMo × TileRT 做了什么，以及&quot;Speed Scaling&quot;作为新范式到底意味着什么。</p>
<h2 id="万亿参数推理为什么特别难">万亿参数推理为什么特别难</h2>
<p>先说背景。MoE（Mixture of Experts）架构让万亿参数模型在训练端变得可行——每次前向传播只激活一小部分参数，推理时的计算量远低于密集模型。但推理端有一个不太一样的瓶颈：<strong>显存带宽</strong>。</p>
<p>一个 1T 参数的 MoE 模型，即使只激活几百亿参数，完整的权重还是得住在 GPU 显存里。用 FP16 加载需要 2TB 显存，8 张 80GB H100 只有 640GB，根本装不下。即使用 FP8（1TB），仍然超出单节点容量。</p>
<p>这意味着推理速度的瓶颈不在计算，而在<strong>数据搬运</strong>——每生成一个 token，GPU 都要从显存读取相关权重，读取速度直接决定生成速度。业界称之为&quot;Memory-Bound&quot;场景，token/s 的上限 = 显存带宽 / 每 token 需要读取的字节数。</p>
<p>所以，要让 1T 模型跑快，核心就两件事：<strong>减少每次搬运的数据量</strong>，和<strong>减少搬运次数</strong>。</p>
<h2 id="第一层fp4-选择性量化不是所有参数都值得用低精度">第一层：FP4 选择性量化——不是所有参数都值得用低精度</h2>
<p>减少数据量最直接的方法是量化。MiMo-V2.5-Pro 采用的是 OCP Microscaling (MXFP4) 格式——一种 <a href="https://arxiv.org/abs/2310.10537">Microsoft 主导的 FP4 标准</a>，在极低比特下保持数值稳定性。</p>
<p>但关键不是&quot;全模型 FP4&quot;。如果暴力把所有层都压到 4 bit，模型在复杂推理、代码生成等任务上会出现明显退化。MiMo 的做法是<strong>选择性量化</strong>：</p>
<ul>
<li><strong>MoE Expert 层</strong>：占总参数量的绝大部分，且对量化容忍度最高 → 用 FP4</li>
<li><strong>Router 和 Attention 层</strong>：参数量小但对精度敏感 → 保持 FP8</li>
</ul>
<p>用人话说就是：大部分&quot;搬运工&quot;（Expert）换成了轻装，但&quot;调度员&quot;（Router）和&quot;注意力核心&quot;保留重装。这不是一个拍脑袋的决定，而是 MiMo 团队和 TileRT 在 profiling 阶段反复测量每层的精度敏感度后得出的工程策略。</p>
<p>这种做法和我们之前拆解过的 <a href="https://blog.hypho.cn/posts/kvarn-vllm-kv-cache-quantization-production/">KVarN 用 KV Cache 量化减少推理显存</a> 有异曲同工之处——都是瞄准推理 pipeline 中的带宽瓶颈做定点优化。区别在于，KVarN 压缩的是 KV Cache 的存储，MiMo 压缩的是模型权重本身的搬运。</p>
<h2 id="第二层dflash不只是猜得快而是猜的形态变了">第二层：DFlash——不只是&quot;猜得快&quot;，而是&quot;猜的形态&quot;变了</h2>
<p>量化解决的是&quot;每次搬运多少&quot;的问题，投机解码解决的是&quot;搬运几次&quot;的问题。</p>
<p>传统投机解码（Speculative Decoding）的思路很直觉：用一个小模型快速&quot;猜&quot;若干后续 token，然后大模型一次性验证。如果猜对了，就省了好几轮自回归生成。问题在于，<strong>草稿本身仍然是自回归的</strong>——小模型每猜一个 token 也要一轮前向传播，瓶颈依然存在。</p>
<p>DFlash（来自 <a href="https://github.com/z-lab/dflash">z-lab 的 DFlash 项目</a>，GitHub 近 5000 星）的做法完全不同：它用<strong>块级掩码并行预测</strong>取代了自回归草稿。具体来说：</p>
<ol>
<li>选取一个 token 块（比如 8 个位置），把其中一部分位置 mask 掉</li>
<li>草稿模型<strong>一次性</strong>预测所有被 mask 的位置，不需要逐个生成</li>
<li>大模型验证整个块的正确性</li>
</ol>
<p>这种&quot;块扩散&quot;方式从根本上绕过了草稿阶段的串行约束。我们在 <a href="https://blog.hypho.cn/posts/dflash-ddtree-speculative-decoding-llm-inference/">之前拆解 DFlash + DDTree 的文章</a> 中详细介绍过这个机制——当时是在消费级 RTX 3090 上跑 Qwen3.5-27B，做到了 207 tok/s。</p>
<p>MiMo × TileRT 把同一个思路搬到了万亿参数场景，并做了针对 MoE 架构的定制优化：</p>
<ul>
<li>使用 Muon 二阶优化器和模型自蒸馏来训练草稿头，确保在 FP4 权重下仍有高接受率</li>
<li>块大小限制在 8 个 token，控制单次验证的计算开销</li>
<li>在代码生成场景实测平均接受长度 6.30，最高 7.14——意味着每轮验证大概能&quot;一口气&quot;确认 6-7 个 token</li>
</ul>
<p>这个数字很重要。接受率太低（比如只有 3-4），投机解码的收益就被验证开销吃掉了。6+ 的接受长度意味着大模型每做一次前向传播，实际产出 6-7 个有效 token，等效地把推理速度翻了 5-6 倍。</p>
<h2 id="第三层tilert-的-tile-based-持久执行引擎">第三层：TileRT 的 Tile-Based 持久执行引擎</h2>
<p>如果说量化和投机解码是&quot;减少工作量&quot;，TileRT 做的是&quot;减少工作的间隙&quot;。</p>
<p>传统的推理框架（vLLM、TensorRT-LLM 等）把模型拆成大量独立算子，每个算子有独立的 kernel launch。在常规速度下（几十 tok/s），每次 launch 的开销（host 端调度、硬件同步、全局内存往返）可以被密集计算掩盖。但在 1000 tok/s 的频率下，每个算子的生命周期被压缩到微秒级，这些开销突然变成了主要瓶颈。</p>
<p>TileRT 的解决方案是一个全新执行模型——<strong>Persistent Engine</strong>：</p>
<ul>
<li>不再逐算子 launch，而是把整个计算管线打包成一个持续运行在 GPU 上的持久化引擎</li>
<li>当一个 Tile（数据块）在 Compute Core 上处理时，下一个 Tile 的数据已经通过多级内存层次（Global → Shared → Register）开始预取</li>
<li>引入 <strong>Warp Specialization</strong>：不同的 Warp 组被分配到不同角色（计算、数据搬运、通信），打破传统&quot;所有 Warp 做同一件事&quot;的刚性执行模式</li>
<li><strong>Heterogeneous Workers</strong> 将这种专业化策略扩展到多个 SM，实现跨 GPU 执行域的协调</li>
</ul>
<p>用人话翻译：传统推理引擎像一个流水线上每个工位都独立接单、独立交付的工厂；TileRT 把它变成了一个连续流动的传送带，每个环节的衔接间隙被压到了接近零。</p>
<p>这解释了为什么 TileRT 能从&quot;几百 tok/s&quot;跨越到&quot;1000+ tok/s&quot;——后者不是前者的线性延伸，而是需要一个质变的执行范式。</p>
<p><a href="https://github.com/tile-ai/TileRT">TileRT 本身是开源项目</a>（1277 星），已经在 GLM-5.1-highspeed 等生产环境中上线，不是纸上谈兵。</p>
<h2 id="三层叠加的工程细节">三层叠加的工程细节</h2>
<p>单独看每一层，都不算革命性创新——量化、投机解码、执行优化，业界都在做。MiMo × TileRT 的真正价值在于<strong>三层之间的协同设计</strong>：</p>
<table>
  <thead>
      <tr>
          <th>技术层</th>
          <th>独立效果</th>
          <th>协同设计的额外收益</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>FP4 量化</td>
          <td>减少 50% 显存带宽</td>
          <td>DFlash 草稿模型可以更小（因为目标模型已经是 FP4），验证更快</td>
      </tr>
      <tr>
          <td>DFlash 投机解码</td>
          <td>等效 6-7x 吞吐提升</td>
          <td>TileRT 的 Persistent Engine 消除了验证阶段的算子间歇，验证效率最大化</td>
      </tr>
      <tr>
          <td>TileRT 执行优化</td>
          <td>消除微秒级算子开销</td>
          <td>量化后的权重体积更小，预取管线可以更激进地重叠 I/O 和计算</td>
      </tr>
  </tbody>
</table>
<p>这种&quot;模型-系统联合设计&quot;（Model-System Codesign）是文章中最值得记住的概念。传统流程是：模型团队训好模型 → 系统团队想办法部署 → 各自优化 → 拼到一起。MiMo × TileRT 的做法是：<strong>在模型设计阶段就引入推理系统团队的约束</strong>，让模型架构天然适合超低延迟执行。</p>
<h2 id="1000-toks-到底能做什么">1000 tok/s 到底能做什么</h2>
<p>速度数字本身不是目的。MiMo 的博客列了三个场景，我认为其中两个真正有工程价值：</p>
<p><strong>1. Best-of-N / Tree Search 推理</strong></p>
<p>在相同的时间预算内，1000 tok/s 让模型可以并行跑几十条推理路径，自动选出最优解。这比&quot;等一个答案，祈祷它正确&quot;要可靠得多。对于代码生成、数学证明等需要探索的任务，这意味着质量的实质性提升，而不只是更快的打字机。</p>
<p><strong>2. Coding Agent 的实时交互</strong></p>
<p>开发者用 AI 写代码时，最大的体验杀手是&quot;等&quot;。1000 tok/s 意味着大段代码生成可以在几秒内完成，Agent 可以在同一个交互回合中完成&quot;写代码 → 测试 → 修复&quot;的完整循环，而不是让开发者盯着 loading 动画发呆。</p>
<p>第三个场景是&quot;毫秒级实时决策&quot;（量化交易、反欺诈），坦白说我持保留态度——这些场景对模型输出质量的要求和对延迟的要求往往互相矛盾，1000 tok/s 解决了延迟但没解决可靠性问题。</p>
<h2 id="对工程选型的实际意义">对工程选型的实际意义</h2>
<p>如果你在做 AI 基础设施选型，这个发布有几个值得注意的点：</p>
<p><strong>TileRT 是一个实际可用的开源推理引擎</strong>，不是实验室 demo。它已经部署在 GLM-5.1 的生产环境中。如果你的场景对延迟极度敏感（实时 Agent、交互式编码），值得评估。相比 <a href="https://blog.hypho.cn/posts/local-llm-ollama-llama-cpp/">本地推理引擎 Ollama/llama.cpp</a> 的定位是消费级硬件上的便捷部署，TileRT 的定位是数据中心级的极致延迟。</p>
<p><strong>DFlash 的块级预测方式</strong>正在成为推理加速的主流路径。4999 星不是没有原因的——它比传统投机解码更适合大模型、长序列场景。如果你用 vLLM 或 TensorRT-LLM，关注这两个框架对 DFlash 的集成进度。</p>
<p><strong>FP4 量化正在从&quot;勉强可用&quot;变成&quot;生产级&quot;</strong>。MXFP4 标准（<a href="https://github.com/microsoft/microxcaling">Microsoft 主导的 Microscaling 格式</a>）在极低比特下的数值稳定性已经被多个团队验证。但注意，MiMo 的成功依赖于 MoE 架构的特殊性——Expert 层天然对量化友好。如果你的模型是密集架构，全模型 FP4 的效果可能不如预期。</p>
<h2 id="一句话总结">一句话总结</h2>
<p>1000 tok/s 不是一个&quot;量化做得更狠&quot;的结果，而是模型架构和推理系统从设计阶段就深度耦合的产物。当推理速度开始像训练算力一样成为决定模型能力边界的变量时，&ldquo;Speed Scaling&quot;这个概念值得每个做 AI 基础设施的人认真对待。</p>
<hr>
<p><strong>信源</strong>：</p>
<ul>
<li><a href="https://mimo.xiaomi.com/blog/mimo-tilert-1000tps">MiMo × TileRT 官方博客</a></li>
<li><a href="https://www.tilert.ai/blog/breaking-1000-tps.html">TileRT 技术博客：Breaking 1000 TPS</a></li>
<li><a href="https://github.com/tile-ai/TileRT">TileRT GitHub（1277 星）</a></li>
<li><a href="https://github.com/z-lab/dflash">DFlash GitHub（4999 星）</a></li>
<li><a href="https://platform.xiaomimimo.com/docs/en-US/model-intro/mimo-v2.5-pro-ultraspeed">MiMo-V2.5-Pro-UltraSpeed 模型文档</a></li>
<li><a href="https://arxiv.org/abs/2310.10537">MXFP4 Microscaling Formats 规格</a></li>
</ul>
]]></content:encoded></item><item><title>Gemma 4 的多 token 预测：LLM 推理加速不该只盯着量化</title><link>https://blog.hypho.cn/posts/gemma-4-multi-token-prediction-inference/</link><pubDate>Wed, 06 May 2026 10:03:32 +0800</pubDate><guid>https://blog.hypho.cn/posts/gemma-4-multi-token-prediction-inference/</guid><description>Google 在 Gemma 4 中引入多 token 预测草稿器，宣称推理最高可提速 3 倍。本文从 speculative decoding、MTP 训练目标、推理框架调度和生产部署取舍角度分析：为什么 LLM 推理优化不能只盯着量化，哪些场景适合多 token 预测，哪些场景仍要谨慎评估。</description><content:encoded><![CDATA[<p>如果你最近还在把“LLM 推理优化”等同于量化，我建议停一下。</p>
<p>量化当然重要，尤其是本地部署和消费级 GPU 场景。但 Google 刚发的 Gemma 4 多 token 预测（Multi-Token Prediction, MTP）让我更确信一件事：下一轮推理加速的主战场，不只是在“把模型压小”，而是在<strong>减少大模型被调用的次数</strong>。</p>
<p>Google 在官方博客里说，Gemma 4 通过 MTP drafters 在推理阶段最高可以做到 <a href="https://blog.google/innovation-and-ai/technology/developers-tools/multi-token-prediction-gemma-4/">up to 3x faster</a>。这个数字本身很抓眼球，但我更关心它背后的工程含义：如果草稿器能一次猜中多个后续 token，大模型就不必老老实实一个 token 一个 token 地跑完整前向传播。</p>
<p>说白了就是：以前是大模型每吐一个字都要“亲自审批”；现在是小模型先写一小段，大模型批量盖章。</p>
<h2 id="为什么一个-token-一次前向这么浪费">为什么“一个 token 一次前向”这么浪费</h2>
<p>自回归 LLM 的默认解码方式很朴素：给定上下文，预测下一个 token；把这个 token 拼回上下文，再预测下一个。这个循环看起来合理，但对硬件很不友好。</p>
<p>每生成一个 token，模型都要访问大量权重。对于 27B、70B 这种规模，瓶颈往往不是矩阵乘法算不动，而是显存带宽和调度开销被小步循环吃掉。你可以把它理解成：GPU 明明适合一次搬一大车货，结果我们让它每次只送一个快递。</p>
<p>这也是为什么我之前写 <a href="https://blog.hypho.cn/posts/dflash-ddtree-speculative-decoding-llm-inference/">DFlash + DDTree 投机解码</a> 时，最看重的不是某个 benchmark 数字，而是“平均接受长度”。只要一次验证能接受更多 token，大模型前向次数就会下降，吞吐自然上来。</p>
<p>Gemma 4 的 MTP 走的是同一条大方向，但实现路径更靠近模型训练本身。</p>
<p>传统 speculative decoding 通常需要一个独立的小 draft model。经典论文 <a href="https://arxiv.org/abs/2302.01318">Speculative Sampling</a> 的思路就是：小模型先生成候选，大模型并行验证，最后用修正过的采样过程保证输出分布不变。这套方法很漂亮，但工程上有两个麻烦：你要维护两个模型，还要处理 tokenizer、KV cache、调度和显存布局。</p>
<p>MTP 的反直觉之处在于，它不一定非要靠“另一个完整小模型”来猜。Meta 的论文 <a href="https://arxiv.org/abs/2404.19737">Better &amp; Faster Large Language Models via Multi-token Prediction</a> 提出，在训练时让模型不只预测下一个 token，而是同时预测未来多个 token。技术上可以看成在共享 trunk 上接多个输出 head，训练目标从“只看一步”扩展到“顺手看几步”。</p>
<p>人话翻译：模型训练时被迫学习“接下来一小段会怎么走”，而不是只盯着下一个词。</p>
<h2 id="gemma-4-的关键变化草稿器变成模型能力的一部分">Gemma 4 的关键变化：草稿器变成模型能力的一部分</h2>
<p>Google 这次讲 Gemma 4 的重点，是把 MTP drafters 用在推理加速上。按照官方描述，Gemma 4 会用多 token 预测草稿器生成候选 token，然后由主模型验证，从而降低延迟、提高吞吐。Gemma 系列本身是 Google 面向开发者开放的轻量模型家族，相关文档可以在 <a href="https://ai.google.dev/gemma/docs">Gemma 官方文档</a> 里看到；如果你更关心本地 C++ 推理，Google 也维护了 <a href="https://github.com/google/gemma.cpp">gemma.cpp</a>，这是一个专门服务 Gemma 模型的轻量推理引擎。</p>
<p>这里有个细节很重要：MTP 不只是“再外挂一个小模型”。如果训练阶段就把多步预测能力纳入目标函数，草稿器的命中率可能会比临时找一个小模型更稳定。命中率越高，大模型一次验证接受的 token 越多，加速越接近理论上限。</p>
<p>但我不会把它理解成“所有 LLM 推理都要马上换 MTP”。工程上至少有三件事要先问清楚。</p>
<p>第一，<strong>你的场景是 latency-bound 还是 throughput-bound</strong>。如果是单用户聊天，用户感知最明显的是首 token 延迟和流式输出节奏；MTP 可能让后续 token 更快，但未必显著改善 first token。如果是代码补全、批量生成、离线摘要，MTP 的收益通常更实在，因为这些任务可以吃到连续 token 的批量验证红利。</p>
<p>第二，<strong>你的输出是否足够可预测</strong>。代码、结构化文本、模板化报告通常更容易被草稿器猜中；开放式创意写作、强采样、多轮工具调用则不一定。草稿命中率一低，验证成本还在，加速就会打折。</p>
<p>第三，<strong>推理框架是否真的支持这套调度</strong>。很多人看到论文数字就想上线，但真正难的是 runtime：KV cache 怎么复用、draft tokens 怎么批量验证、失败回退怎么处理、batch 内不同请求的接受长度不同怎么办。Google 自家栈可以先做起来，不代表你今天拿 vLLM、llama.cpp 或自研服务就能无缝吃到同样收益。</p>
<p>这也是我对 Gemma 4 MTP 的判断：它是一个值得跟进的推理方向，但不是“替代量化”的银弹。</p>
<h2 id="量化投机解码mtp-应该怎么选">量化、投机解码、MTP 应该怎么选</h2>
<p>如果你在做生产部署，我会按这个顺序考虑。</p>
<p>先做量化，因为它最确定。INT8、INT4、GGUF、AWQ、GPTQ 这些路线解决的是“能不能装下、能不能便宜跑”的问题。我之前在 <a href="https://blog.hypho.cn/posts/local-llm-inference-engine-ollama-llama-cpp/">本地 LLM 推理引擎对比</a> 里也提过，本地推理首先要选对 runtime，否则模型再小也会被后端拖垮。</p>
<p>然后再看 speculative decoding 或 MTP，因为它解决的是“同样一次大模型计算，能不能多吐几个 token”。这类优化对服务端很诱人：吞吐上来，单位 token 成本下降；延迟下降，用户体验也更接近即时反馈。</p>
<p>但别跳过验证。至少要测四个指标：</p>
<ul>
<li>平均接受长度：一次验证平均能保留多少 draft token</li>
<li>首 token 延迟：用户是不是更快看到第一个字</li>
<li>端到端 tokens/s：包含草稿、验证、回退后的真实吞吐</li>
<li>质量一致性：高温采样、代码生成、长上下文下是否偏离原模型</li>
</ul>
<p>最后一个指标经常被忽略。Speculative Sampling 论文强调可以保持目标模型分布，这是理论上很强的保证；但到了具体工程实现，采样参数、数值精度、batch 调度都可能引入偏差。生产环境里，性能优化只要悄悄改变输出行为，就不是纯优化，而是一次模型行为变更。</p>
<h2 id="我真正看好的是什么">我真正看好的是什么</h2>
<p>我看好 MTP，不是因为“Gemma 4 快 3 倍”这个宣传数字，而是因为它把推理加速从外部 hack 推向了模型原生能力。</p>
<p>过去两年，LLM 基础设施的很多优化都是补丁式的：量化、PagedAttention、KV cache、FlashAttention、投机解码，各自解决一段瓶颈。MTP 的意义在于，训练目标本身开始为推理效率让路。模型不再只学“下一个 token”，而是学“未来一小段”。这听起来只是训练技巧，实际上会改变 runtime 的设计假设。</p>
<p>不过我也保留一点怀疑：Google 现在给出的还是官方博客级别的结果，真实开源权重、不同硬件、不同任务上的收益需要社区复现。尤其是中文、代码、长上下文和 agent 工具调用场景，接受长度可能差异很大。这里我也不敢拍胸脯说一定有效。</p>
<p>如果你今天要做决策，我的建议很简单：</p>
<ul>
<li>本地/边缘部署：先关注量化和 runtime，MTP 等生态成熟</li>
<li>服务端高吞吐生成：尽快把 speculative decoding / MTP 纳入 benchmark</li>
<li>代码生成和结构化输出：优先测试，因为草稿命中率可能最高</li>
<li>Agent 工具调用：谨慎，工具边界会打断连续生成，收益未必稳定</li>
</ul>
<p>Gemma 4 这次提醒我们，LLM 推理优化不能只盯着“模型变小”。更大的机会可能在于：让大模型少干重复劳动，把它真正用在验证和决策上。</p>
<p>这条路才刚开始。</p>
]]></content:encoded></item><item><title>单卡 207 tok/s：DFlash + DDTree 让 Qwen3.5-27B 在 RTX 3090 上跑出推理新纪录</title><link>https://blog.hypho.cn/posts/dflash-ddtree-speculative-decoding-llm-inference/</link><pubDate>Tue, 21 Apr 2026 10:05:00 +0800</pubDate><guid>https://blog.hypho.cn/posts/dflash-ddtree-speculative-decoding-llm-inference/</guid><description>DFlash 块扩散草稿 + DDTree 树验证，在单张 RTX 3090 上把 Qwen3.5-27B Q4_K_M 推到 207 tok/s，比自回归解码快 5.46 倍。Lucebox 项目开源了首个 GGUF 版本的 DFlash 实现，揭开消费级 GPU 跑大模型推理的新思路。</description><content:encoded><![CDATA[<p>一个 27B 参数的大模型，在一张 2021 年买的游戏显卡上能跑多快？</p>
<p>Lucebox 团队给出了一个让很多人没想到的数字：<strong>207.6 token/s</strong>。用的还是 Qwen3.5-27B 官方模型，不是蒸馏，不是 INT8 量化残血版——就是 Q4_K_M 量化版本，目标加草稿模型全部加载在一张 24 GB VRAM 的 RTX 3090 上。</p>
<p>这个成绩靠的不是等英伟达下一代消费级显卡，而是对<strong>解码算法本身</strong>动刀子。</p>
<h2 id="为什么自回归解码是瓶颈">为什么自回归解码是瓶颈</h2>
<p>大多数人聊 LLM 推理优化，会先想到量化、KV cache 压缩、batch 并行。但对单卡消费级 GPU 来说，这些都已经做到头了——Q4_K_M 量化能压缩到约 16 GB，再压下去效果肉眼可见地降。</p>
<p>问题出在<strong>自回归解码本身</strong>。每生成一个 token，GPU 要完整跑一遍 27B 参数的前向传播。27B 参数在 Q4_K_M 下大约 16 GB，VRAM 带宽是 936 GB/s——每次解码都要把这 16 GB 从显存读一遍，理论带宽利用率撑死不到 20%。这是机械式的物理限制，不是软件优化能绕过去的。</p>
<p>speculative decoding（投机解码）解决的就是这个问题：用一个<strong>小草稿模型</strong>一次生成多个候选 token，再用<strong>大模型</strong>一次验证整串。如果草稿猜得准，大模型只跑一次就能吐出五六个 token，GPU 计算资源用得更充分。</p>
<h2 id="dflash块扩散草稿比-chain-eagle-更容易命中">DFlash：块扩散草稿，比 Chain EAGLE 更容易命中</h2>
<p>主流投机解码方案是 EAGLE（及其 chain 版），草稿模型做自回归预测，每步大约能接受 3 个 token。<strong>DFlash（2026）</strong> 换了个思路：用<strong>块扩散（block diffusion）</strong> 做草稿——一个 5 层非因果的去噪网络，同时预测多个位置，而不是逐个生成。</p>
<p>效果如何？看数字：</p>
<table>
  <thead>
      <tr>
          <th>任务</th>
          <th style="text-align: center">AR 基线（tok/s）</th>
          <th style="text-align: center">DFlash+DDTree（tok/s）</th>
          <th style="text-align: center">加速比</th>
          <th style="text-align: center">平均接受长度</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>HumanEval</td>
          <td style="text-align: center">37.78</td>
          <td style="text-align: center"><strong>129.52</strong></td>
          <td style="text-align: center"><strong>3.43×</strong></td>
          <td style="text-align: center">8.31</td>
      </tr>
      <tr>
          <td>Math500</td>
          <td style="text-align: center">37.71</td>
          <td style="text-align: center"><strong>110.51</strong></td>
          <td style="text-align: center"><strong>2.93×</strong></td>
          <td style="text-align: center">7.04</td>
      </tr>
      <tr>
          <td>GSM8K</td>
          <td style="text-align: center">37.65</td>
          <td style="text-align: center"><strong>96.15</strong></td>
          <td style="text-align: center"><strong>2.55×</strong></td>
          <td style="text-align: center">6.14</td>
      </tr>
  </tbody>
</table>
<p>AR 基线是 Qwen3.5-27B Q4_K_M 在 RTX 3090 上的原生速度，也是 llama.cpp、SGLang AWQ 等框架在同一硬件上的天花板。DFlash 把这个天花板一口气推到 3 倍以上——而且<strong>平均每次验证接受 8 个 token</strong>，比 EAGLE 的 ~3 高了将近两倍。</p>
<p>但这里有个工程问题：官方 DFlash 实现跑在 BF16 下，需要 60+ GB VRAM 的 B200 专业卡才能装下目标+草稿+验证树。消费级 GPU 想用，得从头移植。</p>
<h2 id="gguf-移植q4_k_m-是-24-gb-的最优解">GGUF 移植：Q4_K_M 是 24 GB 的最优解</h2>
<p>Lucebox 的贡献就是这个移植。他们选了 <strong>Q4_K_M 量化目标（~16 GB）+ BF16 草稿（~3.46 GB）+ DDTree 验证树（budget=22）</strong>，刚好能在 24 GB VRAM 里塞下整个推理链路。</p>
<p>GGUF 是 llama.cpp 的量化格式，在消费级 GPU 上生态最成熟。选择 ggml 作为运行时而非 libllama，是因为 ggml 有<strong>原生 Gated DeltaNet CUDA kernel</strong>，不需要额外改硬件抽象。</p>
<p>整个移植约 2000 行 C++/CUDA 代码，fork 了 llama.cpp 增加了三个 tree-mode 操作：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="n">ggml_ssm_conv_tree</span>      <span class="c1">// SSM 卷积树结构
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">ggml_gated_delta_net_tree</span>        <span class="c1">// Gated DeltaNet 树验证
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="n">ggml_gated_delta_net_tree_persist</span> <span class="c1">// 持久化状态
</span></span></span></code></pre></div><p>硬编码了 Qwen3.5-27B + Qwen3.5-27B-DFlash 这一个模型组合，没有通用性——但消费级单卡跑 27B 规模，这个组合恰好是最有价值的一个。</p>
<h2 id="128k-context-怎么塞进去">128K context 怎么塞进去</h2>
<p>原生 DFlash 在 128K 上下文时会爆显存，因为 KV cache 太大。Lucebox 的解法是<strong>Q4_0 KV cache + 滑动 target_feat ring</strong>（4096 槽位）：</p>
<ul>
<li>Q4_0 比 BF16 省 8 倍显存</li>
<li>Sliding window 限制历史 KV 长度</li>
<li>target_feat 做 ring buffer，超长 prompt 自动驱逐旧状态</li>
</ul>
<p>代价是 Acceptance Length 约下降 3%，但换来了<strong>128K context 稳定在 24 GB 内</strong>，128K 模式下仍能跑出 ~135 tok/s。这对需要超长上下文的应用（代码库分析、长文档对话）是实打实的突破。</p>
<h2 id="关键洞察消费级-gpu-的-llm-推理还没到头">关键洞察：消费级 GPU 的 LLM 推理还没到头</h2>
<p>看完 Lucebox 的实现，有几个工程结论值得关注：</p>
<p><strong>1. 量化不是终点，算法才是</strong></p>
<p>Q4_K_M 已经把 27B 压到 16 GB，这个路径的边际收益越来越小。但在 Q4_K_M 基础上加 DFlash，能在不降低模型质量的前提下再快 3 倍——这说明解码算法的优化空间远没有到头。下一个突破点很可能是<strong>草稿模型和目标模型的协同训练</strong>，而不是继续压缩精度。</p>
<p><strong>2. GGUF 生态正在变厚</strong></p>
<p>Llama.cpp 的 GGUF 量化格式原本是&quot;省显存&quot;的妥协方案，但随着 ggml 支持更多的 CUDA kernel（SSM、Gated DeltaNet），它在某些场景下已经不只是&quot;能用&quot;，而是&quot;最优解&quot;。这对想在消费级硬件上做推理优化的开发者是好消息——不需要自己写 CUDA kernel，现成的生态已经能跑起来。</p>
<p><strong>3. 单卡 27B 的实用边界在拓宽</strong></p>
<p>207 tok/s 意味着什么？实际体验大概是：每秒能吐出大约 150-200 个中文词，或者 300-400 个英文词。这个速度已经能支持<strong>实时交互式 AI 助手</strong>——不是等几秒才回一个字，而是几乎感知不到延迟的流式响应。加上 128K 上下文，单卡 27B 能做的事比去年这个时候多了很多。</p>
<h2 id="快速上手">快速上手</h2>
<p>项目在 GitHub，clone 下来大概需要知道这几步：</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 1. 克隆（含 submodule）</span>
</span></span><span class="line"><span class="cl">git clone --recurse-submodules https://github.com/Luce-Org/lucebox-hub
</span></span><span class="line"><span class="cl"><span class="nb">cd</span> lucebox-hub/dflash
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 2. 编译（CUDA 12+, RTX 3090/sm_86）</span>
</span></span><span class="line"><span class="cl">cmake -B build -S . -DCMAKE_CUDA_ARCHITECTURES<span class="o">=</span><span class="m">86</span> -DCMAKE_BUILD_TYPE<span class="o">=</span>Release
</span></span><span class="line"><span class="cl">cmake --build build --target test_dflash -j
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 3. 下载模型（约 20 GB）</span>
</span></span><span class="line"><span class="cl">huggingface-cli download unsloth/Qwen3.5-27B-GGUF Qwen3.5-27B-Q4_K_M.gguf --local-dir models/
</span></span><span class="line"><span class="cl">huggingface-cli download z-lab/Qwen3.5-27B-DFlash model.safetensors --local-dir models/draft/
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 4. 运行</span>
</span></span><span class="line"><span class="cl">python3 scripts/run.py --prompt <span class="s2">&#34;def fibonacci(n):&#34;</span>
</span></span></code></pre></div><p>完整的 benchmark 结果在 <a href="https://github.com/Luce-Org/lucebox-hub/tree/main/dflash/RESULTS.md">RESULTS.md</a>，包括不同模型、不同 context 长度下的吞吐和内存数据。</p>
<h2 id="信源">信源</h2>
<ul>
<li>Lucebox DFlash 实现：https://github.com/Luce-Org/lucebox-hub</li>
<li>DFlash 论文：https://arxiv.org/abs/2602.06036</li>
<li>DDTree 论文：https://arxiv.org/abs/2604.12989</li>
<li>Lucebox 官方博客：https://lucebox.com/blog/dflash27b</li>
<li>Qwen3.5-27B GGUF 量化模型：https://huggingface.co/unsloth/Qwen3.5-27B-GGUF</li>
<li>Qwen3.5-27B-DFlash 草稿模型：https://huggingface.co/z-lab/Qwen3.5-27B-DFlash</li>
</ul>
]]></content:encoded></item></channel></rss>