Kotonia
ログイン今すぐ始める

Kotonia Articles

投機デコード(MTP)は日本語雑談に効かない — acceptance 36% vs 71% の実測

ThinkingCap-Qwen3.6-27B の MTP 投機デコードを実測。draft acceptance は英語コード生成71% vs 日本語カジュアル会話36%、速度向上は1.85倍vs1.12倍。アクティブパラメータ9倍差のMoEとdenseの速度差が実測2.5倍にとどまる帯域の数学も解説。

著者 3分で読める
#llm#vllm#speculativedecoding#localllm#gpu
他の言語英語中国語

TL;DR

  • ThinkingCap-Qwen3.6-27B (NVFP4) の native MTP head を vLLM で有効化し、単一ストリームの decode 速度を実測した
  • MTP の draft acceptance は英語コード生成で 71%、日本語カジュアル会話で 36%。速度向上は 1.85 倍 vs 1.12 倍と、ワークロードで天と地ほど違う
  • 「アクティブパラメータ 9 倍差の MoE と dense を比べたら 9 倍遅くなる」は誤り。実測は 2.5 倍差で、その内訳は帯域の数学で説明できる(量子化 1 段で 9→5 倍、固定オーバーヘッドで 5→2.5 倍)
  • 音声チャットのようなリアルタイム日本語対話では投機デコードを当てにしない設計が正しい。エージェント/コード用途ではほぼタダで 2 倍近く速くなる

背景: MoE から dense への乗り換えで速度が問題になった

運用中のローカル LLM を、35B-A3B の MoE(アクティブ 3B)から dense 27B に置き換える検討をしていた。指示追従やエージェント性能は dense 側が良い。問題は decode 速度で、リアルタイム音声チャットも同じエンジンに乗っているため「会話が遅くなるなら没」という制約があった。

そこで期待したのが、乗り換え候補モデルに同梱されている MTP (Multi-Token Prediction) head による投機デコードだった。「dense の速度ハンデを投機で補えるか?」が今回の問いになる。

環境と測定方法

  • GPU: RTX PRO 6000 Blackwell (96GB)
  • vLLM 0.24.0 / モデル: ThinkingCap-Qwen3.6-27B-NVFP4(重み ~19.7GB + MTP head bf16 0.85GB)
  • --speculative-config '{"method":"qwen3_5_mtp","num_speculative_tokens":3}' / --kv-cache-dtype fp8
  • 比較対象: Agents-A1(35B-A3B MoE、fp8、投機なし)
  • 単一ストリーム、streaming で TTFT と decode tok/s を測定(completion_tokens / 初トークン以降の実時間)
  • acceptance は vLLM の /metrics の差分から算出:
acceptance = Δ vllm:spec_decode_num_accepted_tokens_total
           / Δ vllm:spec_decode_num_draft_tokens_total

シナリオは 2 つ。ja_chat(ペルソナ付きの日本語カジュアル会話、512 tok 上限)と code_agent(英語のコーディングタスク、2048 tok 上限)。

結果

decode tok/s(中央値)MoE 35B-A3B fp8dense 27B 素dense 27B + MTPMTP acceptance
日本語カジュアル会話17772.080.5 (×1.12)36.1% (92/255)
英語コード生成17770.7131.0 (×1.85)71.4% (2795/3912)

TTFT はどの構成でも 50〜100ms で有意差なし。

素の decode がシナリオ不問でフラット(72 vs 70.7)なのは帯域律速の dense らしい挙動で、差がつくのは全部 MTP の acceptanceということになる。同じモデル・同じ draft head で、コードは 7 割当たり、日本語雑談は 3 割半しか当たらない。

なぜ日本語雑談で外れるのか

投機デコードの利得は「draft がどれだけ本体の出力を言い当てるか」で決まる。当たりやすいのは次トークンのエントロピーが低いテキストだ。

  • コード: 構文の制約が強く、boilerplate・インデント・キーワードなど「ほぼ一本道」のトークンが大量にある。draft はそこを刈り取れる
  • 日本語カジュアル会話: 語尾・言い回し・相槌のバリエーションが本質的に多い。「〜だね」「〜だよ」「〜かな」のどれも自然な地点では、draft は当てようがない

加えて、コミュニティの MTP/投機デコードの評判は英語+コードのベンチに偏っている。「投機で 2 倍速い」系の報告を日本語対話サービスにそのまま持ち込むと、期待の半分も出ないというのが今回の学びだ。逆に、翻訳やテンプレ性の高い文書生成なら日本語でも当たる可能性は残る(未計測)。

「アクティブ 9 倍差で速度 2.5 倍差」の内訳

もう一つ、直感に反した数字が「MoE(アクティブ 3B)と dense 27B の速度差」だった。パラメータ比 9 倍に対し、実測は 177 vs 71 の 2.5 倍しか違わない。

decode は帯域律速なので、効くのはパラメータ数ではなく 1 トークンあたりの重み読み出しバイト数:

  • MoE 35B-A3B @ fp8: アクティブ ~3B × 1 byte + shared expert + attention ≈ ~4 GB/token
  • dense 27B @ NVFP4: ~0.56 byte/param(+ bf16 の埋め込み等)≈ ~20 GB/token

つまり真の比は 9 倍ではなく ~5 倍(FP4 が fp8 の半分/param なので 9 → 5 に縮む)。さらに理論天井と実測を比べると:

帯域理論値 (~1.7TB/s)実測天井到達率
MoE 35B-A3B~425 tok/s177~42%
dense 27B FP4~85 tok/s71~84%

dense は帯域天井近くまで回っているのに対し、MoE は kernel 起動やサンプラー等の固定費に食われて天井の半分も出ていない。高 tok/s 側ほど固定費で理論比が圧縮されるため、5 倍が 2.5 倍まで縮む。「MoE は速い」は事実だが、単一ストリームでは公称ほどの差にならない — これは逆に言えば、dense 側の見かけの絶望感も公称ほどではないということだ。

運用の結論

  1. リアルタイム日本語対話は投機デコードを当てにしない。 acceptance 36% では体感を変えるほどの利得がない。会話パスの速度が要件なら、素の decode 速度(= bytes/token)で選ぶ
  2. エージェント/コード用途では MTP はほぼタダ飯。 フラグ 1 つで 1.85 倍。しかも同梱 head なので追加 VRAM は ~1GB
  3. acceptance は自分のワークロードで測る。 /metrics の差分を取るだけで 5 分で分かる。英語コードのベンチ数字は日本語対話の参考にならない
  4. 最終的に我々は指示追従を優先して dense 27B への全面移行を選び、会話パスの 0.45 倍は「実測した上で許容」した。この判断が精神論にならなかったのは、シナリオ別の実測が先にあったから

kotonia.ai の音声チャット/デスクトップエージェント基盤の刷新記録。関連記事: 「ローカルLLMが『Pythonで計算しました』と嘘をつくとき」(指示追従側の検証)。

Kotonia は音声AI、AIチャット、画像生成、チーム共有をひとつにまとめたAIワークスペースです。

試してみる