<?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>Inference-Optimization on Tarragon</title><link>https://tarrragon.github.io/blog/tags/inference-optimization/</link><description>Recent content in Inference-Optimization on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Tue, 12 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/inference-optimization/index.xml" rel="self" type="application/rss+xml"/><item><title>Prompt Cache</title><link>https://tarrragon.github.io/blog/llm/knowledge-cards/prompt-cache/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/knowledge-cards/prompt-cache/</guid><description>&lt;p>Prompt cache 的核心概念是「&lt;strong>LLM 服務端 / 推論伺服器把重複出現的 prompt prefix（如 system prompt + tool schema）的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache&lt;/a> 暫存起來、後續 query 跳過該 prefix 的 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/prefill/" data-link-title="Prefill" data-link-desc="Prompt 首次處理時的計算階段：把整段輸入跑過模型、產生 KV cache">prefill&lt;/a> 階段&lt;/strong>」。Anthropic / OpenAI / Bedrock / Gemini 都提供、最高 90% cost 折扣 + 13-31% &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/ttft/" data-link-title="TTFT" data-link-desc="Time To First Token：送出 prompt 到第一個 token 出現的等待時間">TTFT&lt;/a> 改善、是 coding agent / long-context 應用的核心 cost / latency 槓桿。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>跟既有 cache 概念的層次：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>Cache 層&lt;/th>
 &lt;th>範圍&lt;/th>
 &lt;th>機制&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache&lt;/a>&lt;/td>
 &lt;td>單一 conversation 的同一次推論&lt;/td>
 &lt;td>過去 token 的 K/V 暫存、autoregressive 才省重算&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/prefix-cache/" data-link-title="Prefix Cache" data-link-desc="把多個請求共用的前綴 prompt 的 KV cache 重用、省下重複 prefill 算力的優化、production 多用戶服務的常見設計">Prefix cache&lt;/a>&lt;/td>
 &lt;td>多 request 共用 prefix（同 server 同 model）&lt;/td>
 &lt;td>跨 request 共用 KV cache、production 推論伺服器特性&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>Prompt cache（本卡）&lt;/strong>&lt;/td>
 &lt;td>跨 request 跨時間、雲端 LLM API 服務端&lt;/td>
 &lt;td>服務端把 prefix 的 KV cache 持久化、有 TTL&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>Prompt cache 的「保留範圍」跟「定價」是商業 LLM 的 product feature：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>服務&lt;/th>
 &lt;th>Cache TTL&lt;/th>
 &lt;th>Write cost&lt;/th>
 &lt;th>Read cost&lt;/th>
 &lt;th>觸發方式&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Anthropic（cache_control）&lt;/td>
 &lt;td>5min 預設、1h ext&lt;/td>
 &lt;td>1.25× 原價&lt;/td>
 &lt;td>0.1× 原價（90% 折扣）&lt;/td>
 &lt;td>明確 cache_control breakpoint&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>OpenAI&lt;/td>
 &lt;td>自動（隱式）&lt;/td>
 &lt;td>同原價&lt;/td>
 &lt;td>0.5× 原價（50% 折扣）&lt;/td>
 &lt;td>自動偵測重複 prefix（&amp;gt; 1024 token）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Bedrock（Anthropic）&lt;/td>
 &lt;td>5min&lt;/td>
 &lt;td>同 Anthropic&lt;/td>
 &lt;td>同上&lt;/td>
 &lt;td>同 Anthropic&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Gemini&lt;/td>
 &lt;td>自動 + explicit&lt;/td>
 &lt;td>視方案&lt;/td>
 &lt;td>視方案&lt;/td>
 &lt;td>implicit + context caching API&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;blockquote>
&lt;p>&lt;strong>事實查核註&lt;/strong>：定價跟 TTL 隨時間更新、引用前以對應 vendor 當前文件為準。&lt;/p>&lt;/blockquote>
&lt;h2 id="設計責任">設計責任&lt;/h2>
&lt;p>讀 LLM API docs / coding agent 設計 / cost optimization blog 看到「prompt cache」「context caching」「cache_control」就是這機制。寫 code 場景的判讀：&lt;/p></description><content:encoded><![CDATA[<p>Prompt cache 的核心概念是「<strong>LLM 服務端 / 推論伺服器把重複出現的 prompt prefix（如 system prompt + tool schema）的 <a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache</a> 暫存起來、後續 query 跳過該 prefix 的 <a href="/blog/llm/knowledge-cards/prefill/" data-link-title="Prefill" data-link-desc="Prompt 首次處理時的計算階段：把整段輸入跑過模型、產生 KV cache">prefill</a> 階段</strong>」。Anthropic / OpenAI / Bedrock / Gemini 都提供、最高 90% cost 折扣 + 13-31% <a href="/blog/llm/knowledge-cards/ttft/" data-link-title="TTFT" data-link-desc="Time To First Token：送出 prompt 到第一個 token 出現的等待時間">TTFT</a> 改善、是 coding agent / long-context 應用的核心 cost / latency 槓桿。</p>
<h2 id="概念位置">概念位置</h2>
<p>跟既有 cache 概念的層次：</p>
<table>
  <thead>
      <tr>
          <th>Cache 層</th>
          <th>範圍</th>
          <th>機制</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache</a></td>
          <td>單一 conversation 的同一次推論</td>
          <td>過去 token 的 K/V 暫存、autoregressive 才省重算</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/prefix-cache/" data-link-title="Prefix Cache" data-link-desc="把多個請求共用的前綴 prompt 的 KV cache 重用、省下重複 prefill 算力的優化、production 多用戶服務的常見設計">Prefix cache</a></td>
          <td>多 request 共用 prefix（同 server 同 model）</td>
          <td>跨 request 共用 KV cache、production 推論伺服器特性</td>
      </tr>
      <tr>
          <td><strong>Prompt cache（本卡）</strong></td>
          <td>跨 request 跨時間、雲端 LLM API 服務端</td>
          <td>服務端把 prefix 的 KV cache 持久化、有 TTL</td>
      </tr>
  </tbody>
</table>
<p>Prompt cache 的「保留範圍」跟「定價」是商業 LLM 的 product feature：</p>
<table>
  <thead>
      <tr>
          <th>服務</th>
          <th>Cache TTL</th>
          <th>Write cost</th>
          <th>Read cost</th>
          <th>觸發方式</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Anthropic（cache_control）</td>
          <td>5min 預設、1h ext</td>
          <td>1.25× 原價</td>
          <td>0.1× 原價（90% 折扣）</td>
          <td>明確 cache_control breakpoint</td>
      </tr>
      <tr>
          <td>OpenAI</td>
          <td>自動（隱式）</td>
          <td>同原價</td>
          <td>0.5× 原價（50% 折扣）</td>
          <td>自動偵測重複 prefix（&gt; 1024 token）</td>
      </tr>
      <tr>
          <td>Bedrock（Anthropic）</td>
          <td>5min</td>
          <td>同 Anthropic</td>
          <td>同上</td>
          <td>同 Anthropic</td>
      </tr>
      <tr>
          <td>Gemini</td>
          <td>自動 + explicit</td>
          <td>視方案</td>
          <td>視方案</td>
          <td>implicit + context caching API</td>
      </tr>
  </tbody>
</table>
<blockquote>
<p><strong>事實查核註</strong>：定價跟 TTL 隨時間更新、引用前以對應 vendor 當前文件為準。</p></blockquote>
<h2 id="設計責任">設計責任</h2>
<p>讀 LLM API docs / coding agent 設計 / cost optimization blog 看到「prompt cache」「context caching」「cache_control」就是這機制。寫 code 場景的判讀：</p>
<ol>
<li><strong>誰最值得開</strong>：coding agent（system prompt + tool schema 經常 &gt; 10K token、每 turn 重用）、long-context RAG（檢索 chunks 重用）、long conversation（history 累積）</li>
<li><strong>設計原則</strong>：把不變的內容（system prompt、tool schema、固定文件）放 prefix；變動的（user query、最新 file content）放後面</li>
<li><strong>常見 anti-pattern</strong>：在 prefix 插入 timestamp / user-id / request-id → 每次 prefix 不同 → cache 從不命中、付 1.25× write cost 沒得回本</li>
<li><strong>5 分鐘 TTL 的意涵</strong>：query 之間間隔 &gt; 5 分鐘、cache 已 expire、要 1h ext TTL 才能撐長對話</li>
<li><strong>跟 <a href="/blog/llm/knowledge-cards/context-budget/" data-link-title="Context Budget" data-link-desc="Coding agent 的 context window 拆分配額：system prompt &#43; tool schema &#43; history &#43; file content &#43; reasoning &#43; tool result 各佔多少、留多少 margin">context budget</a> 的關係</strong>：cache 攤平 scaffold 部分的 cost、所以可以放寬「scaffold ≤ 25%」的成本顧慮、focus 在「不超 context limit」即可</li>
</ol>
]]></content:encoded></item><item><title>3.9 Speculative decoding 內部：drafter / 驗證 / 加速上限</title><link>https://tarrragon.github.io/blog/llm/03-theoretical-foundations/speculative-decoding-internals/</link><pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/llm/03-theoretical-foundations/speculative-decoding-internals/</guid><description>&lt;p>&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">Speculative decoding&lt;/a> 在多個前面章節被引用作為「LLM 推論加速的主要技術之一」。本章把這個機制完整展開：為什麼能加速、acceptance 怎麼運作、實際加速倍率怎麼算、&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/drafter-model/" data-link-title="Drafter Model" data-link-desc="speculative decoding 中用來快速猜未來 token 的小模型">drafter model&lt;/a> 怎麼選、跟 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/mtp/" data-link-title="Multi-Token Prediction (MTP)" data-link-desc="Google 為 Gemma 系列釋出的 speculative decoding 工程化實作">MTP&lt;/a> / EAGLE 等變體的關係。&lt;/p>
&lt;p>讀完本章後、看到「speculative decoding 加速 2.5×」這類聲稱時、能判斷可信度、能對自己工作流估算實際收益、能挑對 drafter。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;ol>
&lt;li>解釋為什麼 speculative decoding 能在「不降品質」前提下加速。&lt;/li>
&lt;li>區分 drafter-based、MTP、EAGLE 三條主流路線。&lt;/li>
&lt;li>用 &lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/acceptance-rate/" data-link-title="Acceptance Rate" data-link-desc="speculative decoding 中 drafter 提出的 token 被 target model 接受的比例、決定實際加速倍率">acceptance rate&lt;/a> 估算實際加速倍率。&lt;/li>
&lt;li>判斷一個 drafter / target 配對是否值得用。&lt;/li>
&lt;li>看到 &lt;code>llama-bench&lt;/code> 結果時、判讀「speculative speed」對自己場景的意義。&lt;/li>
&lt;/ol>
&lt;h2 id="為什麼能加速memory-bandwidth-bound-的縫隙">為什麼能加速：&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/memory-bandwidth/" data-link-title="Memory Bandwidth" data-link-desc="記憶體每秒能讀寫多少 bytes：決定本地 LLM 生字速度的真正瓶頸">memory bandwidth&lt;/a> bound 的縫隙&lt;/h2>
&lt;p>回顧 LLM 推論的瓶頸：&lt;a href="https://tarrragon.github.io/blog/llm/knowledge-cards/forward-pass/" data-link-title="Forward Pass" data-link-desc="input 經過所有 layer 的計算、得到 output 的單向流程；推論跟訓練都會跑、訓練多一個反向階段">forward pass&lt;/a> 每生一個 token 要把整份模型權重從記憶體讀到處理器一次、所以 memory bandwidth 是上限。每次讀的時候、處理器有大量算力是閒置的（modern GPU / Apple Silicon 算力遠超頻寬）。&lt;/p>
&lt;p>Speculative decoding 攻擊這個閒置：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">單純 autoregressive 推論：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl"> 每 token：讀整份權重 → 算 forward → 出 1 個 token
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl"> 讀權重 N 次、生 N 個 token
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl"> 瓶頸 = memory bandwidth × N
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">Speculative decoding（K=4）：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> Drafter 一次生 4 個候選 token（drafter 小、讀它的權重快）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> Target 一次驗證 4 個位置（並行算 forward、權重只讀 1 次）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> 若全部接受、生 4-5 個 token（含 bonus）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl"> 讀 target 權重次數從 4 降到 1、平均 token 成本顯著降&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>關鍵理解：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Target model 的 forward pass 對 K 個位置是並行的&lt;/strong>：一次讀權重、做矩陣乘法時把 K 個位置同時算（batch dimension 變大）&lt;/li>
&lt;li>&lt;strong>算力是免費資源&lt;/strong>：原本閒置的算力被用來「同時算多個位置」、不增加 memory bandwidth 消耗&lt;/li>
&lt;li>&lt;strong>正確性保證&lt;/strong>：sampling 階段的接受 / 拒絕邏輯確保最終輸出分佈跟「純 target 自回歸生成」一致 — speculative decoding 不降品質、只省時間&lt;/li>
&lt;/ol>
&lt;h2 id="演算法核心sampling-階段的接受邏輯">演算法核心：sampling 階段的接受邏輯&lt;/h2>
&lt;p>詳細的接受機制（簡化版）：&lt;/p></description><content:encoded><![CDATA[<p><a href="/blog/llm/knowledge-cards/speculative-decoding/" data-link-title="Speculative Decoding" data-link-desc="用小模型猜未來 token、大模型並行驗證的加速技巧">Speculative decoding</a> 在多個前面章節被引用作為「LLM 推論加速的主要技術之一」。本章把這個機制完整展開：為什麼能加速、acceptance 怎麼運作、實際加速倍率怎麼算、<a href="/blog/llm/knowledge-cards/drafter-model/" data-link-title="Drafter Model" data-link-desc="speculative decoding 中用來快速猜未來 token 的小模型">drafter model</a> 怎麼選、跟 <a href="/blog/llm/knowledge-cards/mtp/" data-link-title="Multi-Token Prediction (MTP)" data-link-desc="Google 為 Gemma 系列釋出的 speculative decoding 工程化實作">MTP</a> / EAGLE 等變體的關係。</p>
<p>讀完本章後、看到「speculative decoding 加速 2.5×」這類聲稱時、能判斷可信度、能對自己工作流估算實際收益、能挑對 drafter。</p>
<h2 id="本章目標">本章目標</h2>
<ol>
<li>解釋為什麼 speculative decoding 能在「不降品質」前提下加速。</li>
<li>區分 drafter-based、MTP、EAGLE 三條主流路線。</li>
<li>用 <a href="/blog/llm/knowledge-cards/acceptance-rate/" data-link-title="Acceptance Rate" data-link-desc="speculative decoding 中 drafter 提出的 token 被 target model 接受的比例、決定實際加速倍率">acceptance rate</a> 估算實際加速倍率。</li>
<li>判斷一個 drafter / target 配對是否值得用。</li>
<li>看到 <code>llama-bench</code> 結果時、判讀「speculative speed」對自己場景的意義。</li>
</ol>
<h2 id="為什麼能加速memory-bandwidth-bound-的縫隙">為什麼能加速：<a href="/blog/llm/knowledge-cards/memory-bandwidth/" data-link-title="Memory Bandwidth" data-link-desc="記憶體每秒能讀寫多少 bytes：決定本地 LLM 生字速度的真正瓶頸">memory bandwidth</a> bound 的縫隙</h2>
<p>回顧 LLM 推論的瓶頸：<a href="/blog/llm/knowledge-cards/forward-pass/" data-link-title="Forward Pass" data-link-desc="input 經過所有 layer 的計算、得到 output 的單向流程；推論跟訓練都會跑、訓練多一個反向階段">forward pass</a> 每生一個 token 要把整份模型權重從記憶體讀到處理器一次、所以 memory bandwidth 是上限。每次讀的時候、處理器有大量算力是閒置的（modern GPU / Apple Silicon 算力遠超頻寬）。</p>
<p>Speculative decoding 攻擊這個閒置：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">單純 autoregressive 推論：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">  每 token：讀整份權重 → 算 forward → 出 1 個 token
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">  讀權重 N 次、生 N 個 token
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">  瓶頸 = memory bandwidth × N
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">Speculative decoding（K=4）：
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">  Drafter 一次生 4 個候選 token（drafter 小、讀它的權重快）
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">  Target 一次驗證 4 個位置（並行算 forward、權重只讀 1 次）
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">  若全部接受、生 4-5 個 token（含 bonus）
</span></span><span class="line"><span class="ln">10</span><span class="cl">  讀 target 權重次數從 4 降到 1、平均 token 成本顯著降</span></span></code></pre></div><p>關鍵理解：</p>
<ol>
<li><strong>Target model 的 forward pass 對 K 個位置是並行的</strong>：一次讀權重、做矩陣乘法時把 K 個位置同時算（batch dimension 變大）</li>
<li><strong>算力是免費資源</strong>：原本閒置的算力被用來「同時算多個位置」、不增加 memory bandwidth 消耗</li>
<li><strong>正確性保證</strong>：sampling 階段的接受 / 拒絕邏輯確保最終輸出分佈跟「純 target 自回歸生成」一致 — speculative decoding 不降品質、只省時間</li>
</ol>
<h2 id="演算法核心sampling-階段的接受邏輯">演算法核心：sampling 階段的接受邏輯</h2>
<p>詳細的接受機制（簡化版）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">給定：drafter D、target T、context prefix x、speculative length K
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">Step 1：D 從 x 生 K 個候選 token：d_1, d_2, ..., d_K
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">        對每個位置算 D(d_i | x, d_1..i-1) 機率
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">Step 2：T 對 (x, d_1, d_2, ..., d_K) 做一次 forward pass、得到每個位置的 T 分佈
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">        T_1 = T(· | x)
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">        T_2 = T(· | x, d_1)
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">        ...
</span></span><span class="line"><span class="ln">10</span><span class="cl">        T_K = T(· | x, d_1..K-1)
</span></span><span class="line"><span class="ln">11</span><span class="cl">        T_{K+1} = T(· | x, d_1..K)   ← bonus token 位置
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl">Step 3：從前往後處理：
</span></span><span class="line"><span class="ln">14</span><span class="cl">        for i = 1 to K:
</span></span><span class="line"><span class="ln">15</span><span class="cl">          r = uniform random in [0, 1]
</span></span><span class="line"><span class="ln">16</span><span class="cl">          if r &lt; min(1, T_i(d_i) / D(d_i)):
</span></span><span class="line"><span class="ln">17</span><span class="cl">            accept d_i           ← d_i 在 T 下機率 ≥ D 下機率、接受
</span></span><span class="line"><span class="ln">18</span><span class="cl">          else:
</span></span><span class="line"><span class="ln">19</span><span class="cl">            reject、sample 替代 token from (T_i - D)+ normalized
</span></span><span class="line"><span class="ln">20</span><span class="cl">            break
</span></span><span class="line"><span class="ln">21</span><span class="cl">
</span></span><span class="line"><span class="ln">22</span><span class="cl">Step 4：若全 K 個接受、再 sample 一個 bonus token from T_{K+1}</span></span></code></pre></div><p>關鍵性質（數學上可證明）：</p>
<ol>
<li><strong>最終輸出分佈 ≡ 純 target 自回歸</strong>：不管 drafter 多爛、speculative decoding 的輸出在統計上跟「就用 T 從頭生」完全相同 — 不是「近似」、是「等價」</li>
<li><strong>Drafter 越接近 target、acceptance rate 越高</strong>：但即使 drafter 完全亂猜、輸出仍正確、只是沒加速</li>
<li><strong>每 step 至少生 1 個 token</strong>：最差情況第一個就拒絕、用 T 取代、退化成單純 T 自回歸</li>
</ol>
<h2 id="加速倍率--k--acceptance-rate-的限制">加速倍率 = K × acceptance rate 的限制</h2>
<p>理論加速分析：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">Step 平均生 token 數 = E[接受長度] + 1（bonus 若有）
</span></span><span class="line"><span class="ln">2</span><span class="cl">                    ≈ K × acceptance_rate （簡化估算）
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl">每 step 主要成本：
</span></span><span class="line"><span class="ln">5</span><span class="cl">  Drafter K 次小 forward + Target 1 次大 forward
</span></span><span class="line"><span class="ln">6</span><span class="cl">  ≈ K × T_drafter + T_target
</span></span><span class="line"><span class="ln">7</span><span class="cl">  ≈ T_target × (1 + K × C)   where C = T_drafter / T_target
</span></span><span class="line"><span class="ln">8</span><span class="cl">
</span></span><span class="line"><span class="ln">9</span><span class="cl">加速倍率 ≈ K × acceptance_rate / (1 + K × C)</span></span></code></pre></div><p>實際例子（Gemma 4 31B target + Gemma 4 E4B drafter、K=5）：</p>
<ul>
<li>T_drafter / T_target ≈ 4B / 31B ≈ 0.13</li>
<li>K = 5、acceptance rate ≈ 0.7（同 family、estimate）</li>
<li>加速倍率 ≈ 5 × 0.7 / (1 + 5 × 0.13) ≈ 3.5 / 1.65 ≈ <strong>2.1×</strong></li>
</ul>
<p>對照 LM Studio / llama.cpp 實測常見的「2-3×」加速、推導合理。</p>
<p>什麼破壞加速：</p>
<ol>
<li><strong>Drafter 太大</strong>：C 接近 1、(1 + K × C) 爆增、淨收益消失</li>
<li><strong>Acceptance rate 太低</strong>：K × acceptance 達不到 1 + K × C、淨收益負</li>
<li><strong>K 設太大</strong>：drafter 後面 token acceptance rate 急降、且每步成本 K × T_drafter 線性增加</li>
</ol>
<h2 id="三條主流變體">三條主流變體</h2>
<h3 id="drafter-based經典-speculative-decoding">Drafter-based（經典 speculative decoding）</h3>
<p>Leviathan et al. 2022 / Chen et al. 2023 提出：</p>
<ul>
<li><strong>方式</strong>：獨立訓練一個小 drafter model、跟 target 同 family / 同 tokenizer</li>
<li><strong>代表</strong>：Gemma 4 31B + E4B、Llama 3.1 405B + 8B、Qwen3 30B + 1.5B</li>
<li><strong>優點</strong>：相對成熟、各推論伺服器（llama.cpp、vLLM）廣泛支援</li>
<li><strong>缺點</strong>：要訓 / 維護兩個 model；drafter 跟 target 必須完全相容</li>
</ul>
<h3 id="mtpmulti-token-prediction">MTP（Multi-Token Prediction）</h3>
<p>DeepSeek-V3 / Gemma 4 等內建：</p>
<ul>
<li><strong>方式</strong>：訓練 target 時、output 端額外加 K 個 head、每個 head 學「預測 N+1, N+2, &hellip;, N+K」</li>
<li><strong>代表</strong>：DeepSeek-V3（MTP=4）、Gemma 4 coding 變體</li>
<li><strong>優點</strong>：不需獨立 drafter、head 跟 target 完全同分佈、acceptance rate 高（通常 0.7-0.85）</li>
<li><strong>缺點</strong>：需要 target model 訓練時就支援、現存模型不能後加</li>
</ul>
<h3 id="eagleextrapolation-algorithm-for-greater-llm-efficiency">EAGLE（Extrapolation Algorithm for Greater LLM Efficiency）</h3>
<p>Li et al. 2024 / EAGLE-2 / EAGLE-3：</p>
<ul>
<li><strong>方式</strong>：drafter 用 target 內部的 hidden state（不是 token embedding）當輸入、預測下一個位置的 token 機率、逼近 target 的分佈。因為 drafter 看的是 target 已經處理過的 feature、acceptance rate 比純 token-based drafter 高</li>
<li><strong>代表</strong>：EAGLE-2、EAGLE-3 應用在 Llama 系列</li>
<li><strong>優點</strong>：acceptance rate 通常更高（0.8+）、且 drafter 可以很小</li>
<li><strong>缺點</strong>：實作較複雜、需要 access target 的 hidden state、推論伺服器支援度較窄</li>
</ul>
<blockquote>
<p><strong>事實查核註</strong>：MTP / EAGLE 的具體 acceptance rate 跟加速倍率依模型、任務、量化、推論伺服器實作而異、引用前以各推論伺服器 release notes 跟自己 <code>llama-bench</code> 結果為準。</p></blockquote>
<h2 id="怎麼挑-drafter">怎麼挑 drafter</h2>
<p>實務判讀：</p>
<table>
  <thead>
      <tr>
          <th>條件</th>
          <th>選擇</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Target 有內建 MTP（如 Gemma 4 coding-mtp）</td>
          <td>直接用 MTP、不另找 drafter</td>
      </tr>
      <tr>
          <td>Target 沒 MTP、有同 family 小模型</td>
          <td>用 drafter-based、選小一個量級的同 family 模型</td>
      </tr>
      <tr>
          <td>Target 沒 MTP、無同 family 小模型</td>
          <td>多半不值得 speculative、用一般推論</td>
      </tr>
      <tr>
          <td>用 Apple Silicon Mac、target ≤ 30B</td>
          <td>MTP 是首選、見 <a href="/blog/llm/knowledge-cards/mtp/" data-link-title="Multi-Token Prediction (MTP)" data-link-desc="Google 為 Gemma 系列釋出的 speculative decoding 工程化實作">MTP 卡片</a></td>
      </tr>
      <tr>
          <td>用 PC 獨立 GPU、target 較大</td>
          <td>看 llama.cpp 支援度、EAGLE-2 / drafter-based 都可</td>
      </tr>
  </tbody>
</table>
<p>挑 drafter 的反例（不該配）：</p>
<ol>
<li><strong>跨 family</strong>：Llama 3 + Qwen3 — tokenizer 不一致、無法配對</li>
<li><strong>跨 generation</strong>：Llama 2 + Llama 3 — vocab 不同</li>
<li><strong>太大 drafter</strong>：target 8B + drafter 3B — drafter 成本接近 target、淨收益小</li>
<li><strong>量化不對稱</strong>：target Q4 + drafter Q8 — drafter 不必比 target 精度高、浪費記憶體</li>
</ol>
<h2 id="怎麼測自己的加速倍率">怎麼測自己的加速倍率</h2>
<p><code>llama-bench</code> 是 llama.cpp 官方 benchmark 工具：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 純 target 推論</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">llama-bench -m gemma-4-31b-Q4_K_M.gguf -p <span class="m">512</span> -n <span class="m">128</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 加 drafter（speculative decoding）</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">llama-bench -m gemma-4-31b-Q4_K_M.gguf <span class="se">\
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="se"></span>            --draft-model gemma-4-e4b-Q4_K_M.gguf <span class="se">\
</span></span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="se"></span>            --n-predict <span class="m">128</span> --speculative-draft <span class="m">5</span></span></span></code></pre></div><p>看的指標：</p>
<ul>
<li><strong>tg128 (純 target)</strong>：純自回歸生 128 token 的 tokens/s</li>
<li><strong>tg128 (with draft)</strong>：speculative decoding 模式的 tokens/s</li>
<li><strong>加速倍率</strong>：後者 / 前者</li>
</ul>
<p>實際工作流的 acceptance rate 跟 benchmark 上可能不同（取決於任務）、benchmark 是上限估算。</p>
<h2 id="跟其他加速技巧的關係">跟其他加速技巧的關係</h2>
<table>
  <thead>
      <tr>
          <th>技巧</th>
          <th>攻擊的瓶頸</th>
          <th>跟 speculative decoding 的關係</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/quantization/" data-link-title="Quantization" data-link-desc="用較少 bits 表示模型權重：壓縮記憶體佔用、加快生字速度，代價是少量品質衰減">Quantization</a></td>
          <td>權重大小</td>
          <td>正交、可疊加（兩個都用）</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/flash-attention/" data-link-title="Flash Attention" data-link-desc="Attention 計算的記憶體友善實作、減少 GPU memory 讀寫、提升長 context 推論吞吐">Flash Attention</a></td>
          <td>Attention 記憶體佔用</td>
          <td>正交、可疊加</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/kv-cache/" data-link-title="KV Cache" data-link-desc="已處理 token 的 attention 中間結果暫存：避免重算、加速後續生成">KV cache 量化</a></td>
          <td>KV cache 大小</td>
          <td>正交、可疊加</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/batching/" data-link-title="Batching" data-link-desc="多 request 一起跑、攤平 model load 成本：production LLM inference 的核心優化、決定 throughput vs latency 取捨">Batching</a></td>
          <td>多請求共用權重讀取</td>
          <td>跟 speculative 邏輯衝突（共用 batch dim）</td>
      </tr>
      <tr>
          <td><a href="/blog/llm/knowledge-cards/prefix-cache/" data-link-title="Prefix Cache" data-link-desc="把多個請求共用的前綴 prompt 的 KV cache 重用、省下重複 prefill 算力的優化、production 多用戶服務的常見設計">Prefix cache</a></td>
          <td>Prompt 重複部分</td>
          <td>正交、可疊加</td>
      </tr>
  </tbody>
</table>
<p>關鍵注意：<strong>Speculative decoding + batching 同時開的支援度差</strong> — 推論伺服器多半要選一個。個人 dev 場景 batch size = 1、用 speculative 是合理選擇；高併發 production 場景多半選 batching。</p>
<h2 id="何時不適合用-speculative-decoding">何時不適合用 speculative decoding</h2>
<ol>
<li><strong>Batch size &gt; 1 場景</strong>：跟 batching 衝突、加速可能反向</li>
<li><strong>Reasoning model</strong>：reasoning trace 的 token 多樣化、drafter 很難猜對、acceptance rate 低（多數 reasoning model 不用 speculative）</li>
<li><strong>Drafter 不存在或不合</strong>：勉強配差 family 的 drafter 反而拖慢</li>
<li><strong>記憶體吃緊</strong>：drafter 也要載入、可能擠掉 KV cache budget、其他地方變慢</li>
</ol>
<h2 id="何時過時--何時不過時">何時過時 / 何時不過時</h2>
<p><strong>不會過時的部分</strong>：</p>
<ul>
<li>「Memory bandwidth bound 留下算力閒置」的根本觀察</li>
<li>接受 / 拒絕 sampling 邏輯（數學上等價於純 target）</li>
<li>Acceptance rate × K 是加速倍率主要 driver</li>
<li>Drafter / target 必須 tokenizer 相容</li>
<li>跟 batching 衝突的 trade-off</li>
</ul>
<p><strong>會變的部分</strong>：</p>
<ul>
<li>具體變體（drafter-based / MTP / EAGLE → 未來可能新方法）</li>
<li>各推論伺服器的支援度（llama.cpp、vLLM、TGI 都在演化）</li>
<li>模型廠商是否內建 MTP（目前 Gemma 4、DeepSeek 等先行、未來普及）</li>
<li>Reasoning model 是否會有 reasoning-aware speculative 變體</li>
</ul>
<h2 id="下一步">下一步</h2>
<p>下一步：模組三的內容到此完整、進入 <a href="/blog/llm/04-applications/" data-link-title="模組四：LLM 應用層原理" data-link-desc="Prompt 技術光譜、RAG、tool use、agent、應用層協議、人機協作、multi-agent、workflow 編排、eval 設計：跨工具不變的概念地圖">模組四 應用層原理</a> 看 LLM 作為系統元件的設計取捨。</p>
]]></content:encoded></item></channel></rss>