LLMを速くするために、まずGPUを買い替えようとしているなら、この360回の測定を見てほしい。
24GBのNVIDIA A10Gで、同じGemma 4を動かす。変えるのは、次のトークンを先読みする補助モデルを使うかどうかだ。
- 先読みする候補は 2トークン。
- 比較したのは文章生成・推論問題・ツール呼び出しの 3種類、計360リクエスト。
- 9種類の全プロンプトで、出力スループットは 1.91〜2.19倍。
それが、Suwesh Prasad Sahが9月28日に公開したGemma 4のMTP実測研究だ。MTPはMulti-Token Predictionの略である。
驚くのは、その理由だ。代表的な主要GPUカーネルの所要時間は、通常生成が 2.78ms、MTPが 2.79ms。ここは速くなっていない。
論文の要旨にも、こう書かれている。
The dominant MTP GEMM kernel was not faster than the dominant autoregressive GEMV kernel
1回の処理を速くしなくても、同じ処理を呼ぶ回数が減れば、生成は速くなる。
結論から言うと
1. 対応するGemma 4を使っているなら、通常生成とMTPを同じ入力で比較すること。
この研究では、同じ量子化済みターゲットに補助モデルを追加し、生成中のスループットが約2倍になった。
2. 速くなった主因は、主要カーネルの高速化ではなく、トークンあたりの反復実行の削減だ。
プロファイルした3組では、選定した反復CUDA Graphの実行回数が、出力トークンあたり56.4〜78.1%減った。
3. 360回の測定は、360種類の問題でも、同時360リクエストでもない。
9種類の固定プロンプトを各方式20回ずつ、同時実行数1で測った結果なので、本番の混雑時の性能は別に測る必要がある。

候補を先に用意し、重い検証処理をまとめて通す仕組みを表したAI生成イラスト。実験設備や性能比を描いたものではない。
情報確認日は2026年10月8日。性能値はSahの9月28日公開の技術報告から引用・再集計した値で、査読前である。本記事でGPU推論は再実行していない。実行したのは掲載値の算術チェックであり、後半の推論コードは未実行だ。操作例と方式比較にはGoogleおよびvLLMの公式文書を使用した。Gemma 4自体の新発売を伝える記事ではない。
数字で見る「最大2.19倍」の実験
まず、実験条件と結果を固定する。ターゲットとは回答を決める本体、drafterとは候補を提案する補助モデルのことだ。
| 項目 | 研究で使った条件・観測値 |
|---|---|
| GPU | NVIDIA A10G 1基、24GB |
| 推論エンジン | vLLM 0.24.0 |
| ターゲット | google/gemma-4-E4B-it-qat-w4a16-ct |
| 量子化 | 重み4bit・活性16bit、compressed-tensors形式 |
| drafter | google/gemma-4-E4B-it-assistant |
| 投機の深さ | 2トークン、検証1回で最大3トークン進行 |
| 配信条件 | 同時実行数 1、最大コンテキスト8,192、GPUメモリ利用率上限0.80 |
| 測定数 | 2方式 × 3用途 × 3プロンプト × 20回 = 360回 |
| プロンプト別の出力速度比 | 1.91〜2.19倍 |
| 最初の出力までの時間短縮 | 10.0〜14.2% |
付録の測定プロトコルではprefix cachingを有効にしつつ、入力の先頭に固有IDを入れるcontrolled-cold条件を使っている。対応するARとMTPには同じID入り入力を渡し、キャッシュが温まった条件の比較は後回しにしている。
最初の出力までの時間はTTFOである。研究では、推論内容・回答本文・ツール呼び出し断片のいずれかが届いた時点を使い、メタデータだけのイベントを除外している。
つまり「約2倍」は、最初の一文字が出るまでの待ち時間を半分にしたという意味ではない。大きく変わったのは、その後の生成だ。
ここまでは出力速度の話。面白いのはその先だ。
主要カーネルは速くない。減ったのは「何回やるか」だった
2個先読みして、最大3個進む
普通の自己回帰生成、以下ARでは、確定した文章を使って次の1トークンを決める。MTPでは軽いdrafterが先に候補を作り、ターゲットが複数位置をまとめて検証する。
Googleの仕組みの説明によると、Gemma 4のdrafterはターゲットの活性値やKVキャッシュも利用する。小さい汎用モデルを横に置くだけの構成とは違う。
2候補の場合、最初の候補で外れたら、後ろの候補も捨てる。後ろの候補は「最初が正しかった世界」を前提に作られたからだ。両方通れば、ターゲットが決める追加の1個と合わせ、最大3個進める。
次は greedy生成を説明する擬似コード・未実行 だ。確率的サンプリングでは別途、受理確率と棄却時の分布補正が必要になる。
候補 = drafterが2トークンを提案(確定済みの列)
判定 = targetが候補列の各位置をまとめて計算
先頭から一致する候補だけを採用
最初の不一致位置ではtargetの選択を採用
両方一致したらtargetの追加1トークンも採用
確定した列を更新して繰り返す
速い補助モデルに回答を丸投げしているわけではない。採用を決めるのはターゲットだ。
1回が重くなるのに、合計は軽くなる
研究の要旨には、こうある。
greater token progress reduced repeated GPU execution
GEMVは行列とベクトル、GEMMは行列同士の積だ。複数位置を扱うMTPでは、主要な処理がGEMV中心からGEMM中心に変わった。それだけで「Tensor Coreが効いて全部速くなった」と結論づけたくなる。
本当にそうか?
Table 4・5・10を突き合わせると、別の説明が見える。
| 観測対象 | AR | MTP | 何が分かるか |
|---|---|---|---|
| 主要カーネルの代表1回の時間 | 2.78ms | 2.79ms | 単発の短縮ではない |
| 同じ代表カーネルのメモリ帯域 | 579.04GB/s | 575.07GB/s | 両方とも約600GB/sの上限に近い |
| ツール呼び出し時の反復Graph開始間隔の中央値 | 10.383ms | 12.399ms | MTP側の間隔は 約19.4%長い |
| 同じトレースの反復Graph実行数/出力トークン | 0.654 | 0.143 | MTP側は 約78.1%少ない |
上2行は推論問題から選んだ代表カーネル、下2行はツール呼び出しのプロファイルであり、同じ計測単位ではない。CUDA Graphも、アルゴリズム上の検証1回と一対一ではない。
19.4%は 12.399 / 10.383 - 1、78.1%は 1 - 0.143 / 0.654 から、本記事で再計算した。掲載値が丸められているため、結果も概数だ。
MTPでは、候補生成、サンプリング、候補の選択、状態更新という仕事が増える。それでも、出力1トークンを得るまでに重い処理を繰り返す回数が減れば、全体では得になる。
この関係だけを抽象化すると、見るべき量は次になる。
$$
\text{生成効率} = \frac{\text{確定した出力トークン数}}{\text{候補生成と検証を含む経過時間}}
$$
分子だけを見れば受理率自慢になる。分母の一部だけを見ればカーネル自慢になる。ユーザーが待っているのは、両方を合わせた結果だ。
あなたの環境では、候補を増やしたときに先に悪化するのは受理率か、検証の時間か。あなたの予想もコメントで教えてほしい。
この測定が示すのは1モデル対・1GPU・同時実行数1での実行機構を説明する証拠であり、別ハードウェアや高負荷時まで同じ倍率を保証するものではない。
同じ321トークンでも、3.37秒から1.63秒へ
「出力が短くなっただけでは?」という疑いも潰しておこう。
Table 1の用途別中央値を読み直し、倍率を計算したのが次の表だ。各方式・各用途は60リクエストである。
| 用途 | AR → MTPの出力速度(tokens/s) | 本記事で計算した速度比 | AR → MTPの全体時間 | 出力長の中央値 |
|---|---|---|---|---|
| 文章生成 | 97.46 → 192.80 | 1.98倍 | 5.107 → 2.676秒 | 491 → 499.5 |
| 推論問題 | 96.61 → 204.70 | 2.12倍 | 8.374 → 4.074秒 | 802 → 811 |
| ツール呼び出し | 97.26 → 204.98 | 2.11倍 | 3.369 → 1.631秒 | 321 → 321 |
この表は「用途別中央値同士の比」であり、タイトルの2.19倍は「同じプロンプトの20回中央値同士の比」の最大値である。集計単位を混ぜないこと。
特にツール呼び出しは、出力長の中央値が両方式で321トークンと揃う。研究では3つのプロンプトそれぞれでも中央値が一致しており、単に短い回答へ変わっただけでは説明しにくい。
一方、文章生成の一部では出力長が変わっている。したがって、全体時間だけを見て「生成能力が2倍」と読むのは雑だ。
次の計算は 実行済み である。再計算したのは論文の掲載値であり、新たな推論ベンチマークではない。
rows = [
("plain", 97.46, 192.80),
("reasoning", 96.61, 204.70),
("tool", 97.26, 204.98),
]
for name, ar, mtp in rows:
print(f"{name}: {mtp / ar:.2f}x")
print(f"cadence: {(12.399 / 10.383 - 1) * 100:.1f}% longer")
print(f"graphs/token: {(1 - 0.143 / 0.654) * 100:.1f}% fewer")
plain: 1.98x
reasoning: 2.12x
tool: 2.11x
cadence: 19.4% longer
graphs/token: 78.1% fewer
今すぐ試すべき2つの方法
1. Transformersで、補助モデルあり・なしの出力を比べる
まず仕組みに触れるなら、Googleの公式チュートリアルが短い。以下はE4Bを選び、非推論モードと最大2候補を明示した例だ。公式例の torch_dtype は、同ページの非推奨警告に従って dtype に置き換えた。
未実行。CUDA環境と、非量子化ターゲット+補助モデルが収まるメモリを前提とする。 論文の4bit構成とは異なるため、24GBでの動作や同じ速度比を示すコードではない。
pip install torch accelerate transformers
import torch
from transformers import AutoProcessor, AutoModelForCausalLM
target_id = "google/gemma-4-E4B-it"
processor = AutoProcessor.from_pretrained(target_id)
target = AutoModelForCausalLM.from_pretrained(
target_id, dtype=torch.bfloat16, device_map="auto"
)
assistant = AutoModelForCausalLM.from_pretrained(
target_id + "-assistant", dtype=torch.bfloat16, device_map="auto"
)
assistant.generation_config.num_assistant_tokens = 2
assistant.generation_config.num_assistant_tokens_schedule = "constant"
messages = [{
"role": "user",
"content": "Explain speculative decoding in three sentences."
}]
text = processor.apply_chat_template(
messages, tokenize=False, add_generation_prompt=True,
enable_thinking=False,
)
inputs = processor(text=text, return_tensors="pt").to(target.device)
input_len = inputs["input_ids"].shape[1]
for label, extra in [("AR", {}), ("MTP", {"assistant_model": assistant})]:
output = target.generate(
**inputs, max_new_tokens=256, do_sample=False, **extra
)
print(label, processor.decode(
output[0][input_len:], skip_special_tokens=True
))
MTPを有効にする中心は assistant_model=assistant だ。この例は出力の確認用で、時間は測っていない。速度を測る段階ではウォームアップを分け、GPUの同期と生成トークン数を記録すること。
2. vLLMで、論文と同じターゲット・drafterの組を試す
配信側で試すなら、vLLMのGemma 4用MTP設定を使う。次は公式の起動形式を、論文のモデル対と主要な配信条件に合わせた例だ。
未実行。Gemma 4 MTP対応のvLLM環境が必要である。 論文で使われたバージョンは0.24.0。以下は起動確認用で、論文の独自チャットテンプレートや360回の測定手順まで再現するものではない。
vllm serve google/gemma-4-E4B-it-qat-w4a16-ct \
--host 127.0.0.1 \
--tensor-parallel-size 1 \
--max-model-len 8192 \
--max-num-seqs 1 \
--max-num-batched-tokens 2048 \
--gpu-memory-utilization 0.80 \
--enable-chunked-prefill \
--enable-prefix-caching \
--speculative-config '{"method":"mtp","model":"google/gemma-4-E4B-it-assistant","num_speculative_tokens":2}'
ARと比較するときは、同じ起動コマンドから --speculative-config だけを外したサーバーを別の測定回で使う。同じGPUに両方を同時起動して比較しないこと。
入力、出力上限、サンプリング、キャッシュ条件を揃え、ARとMTPで同じリクエストを送る。記録するのは 最初の出力時刻、終了時刻、出力トークン数、出力の妥当性 だ。この研究の出力速度は (出力トークン数 - 1) / (終了時刻 - 最初の出力時刻) で計算されている。
知らないと損する4つの罠
罠1:assistant だから draft_model でよいと思う
vLLMの公式注意事項では、Gemma 4 assistantは専用MTP経路を通す。model 欄に別チェックポイントを渡す見た目でも、汎用draft model扱いではない。
{"method": "mtp", "model": "google/gemma-4-E4B-it-assistant"}
古い版で SpeculativeConfig(method='draft_model', ...) と表示された場合、Gemma 4の対応経路が含まれておらず、初期化に失敗する可能性がある。
対策:method を mtp にし、Gemma 4 MTP対応版で起動ログを確認すること。
罠2:受理長2.595なら、2.595倍速いと思う
Table 3のツール呼び出しでは、平均受理長のログ窓ごとの中央値は2.595だ。これはターゲット由来の1トークンも含み、2候補設定では1〜3の範囲を取る。
ところが、同用途のプロンプト別速度比の中央値は2.11倍である。候補を作って選ぶ費用が無料ではないからだ。しかも受理長は約10秒ごとの集計窓から得た値で、各リクエストの速度と直接対応づけられていない。
対策:受理率を採用判定にせず、出力速度と全体時間を同時に測ること。
罠3:360回すべてが、正しい回答だったと思う
出力検証の内訳は、ARが177/180件、MTPが172/180件だ。残る11件は、推論問題の指定回答との不一致6件と、長さ上限に達した5件である。
研究はこの11件を捨てず、速度の集計に含めている。一方、正しく完了した出力だけに絞っても推論問題の約2倍の短縮は残った。
この少数の結果だけでMTPの品質低下を断定することもできない。「投機的生成は理論上lossless」と「実装で常に同じ文字列が出る」も別の話で、vLLMは数値精度やバッチ条件による差を明記している。
対策:速度と一緒に、正答・JSONスキーマ・終了理由を保存すること。失敗した試行を成功例で置き換えないこと。
罠4:プロファイラを付けた時間を、そのままユーザーの待ち時間と呼ぶ
この研究の測定手順は、通常ベンチマークとNsight/PyTorch Profilerの実行を分けている。プロファイルは各用途・各方式1リクエストであり、360件全部の内部を観察したわけではない。
カーネル時間の合計、GPU注釈区間、CUDA Graph開始間隔、HTTP応答時間は、それぞれ違う量だ。異なる時計を足し合わせると、存在しない内訳を作ってしまう。
対策:速さの主張はプロファイラなしの測定、理由の説明は別採取のトレースで行うこと。
MTP以外も含めて4方式を比較する
補助モデルを置けば、どのLLMでも同じ得が得られるのか。ここは方式を分けて選ぶ。
2026年10月8日に確認したvLLMの方式一覧、MTP、EAGLE、N-gram、Draft Modelsから、導入条件を整理した。速度ランキングではない。
| 方式 | 候補の作り方 | 追加の重み | 比較するときの焦点 |
|---|---|---|---|
| Gemma 4 MTP | 対応assistantが内部情報を使って候補を提案 | 対応assistantが必要 | 同じターゲットで受理長と実時間が釣り合うか |
| EAGLE系 | 対応する特徴予測モデルで候補を提案 | 対応するdrafterが必要 | ターゲットに合うチェックポイントがあるか |
| 汎用draft model | 小さい言語モデルで先に候補を生成 | 別の言語モデルが必要 | drafterの費用と語彙の互換性 |
| N-gram | 入力内のトークン列の一致から候補を拾う | 追加モデル不要 | 再利用できる並びが入力にあるか |
表から読み取れること:
- Gemma 4の専用assistantを使えるなら、まずMTPをARと比べる理由がある。
- 追加のモデルを載せたくないなら、N-gramが比較候補になる。ただし、一致候補が少ない入力で同じ効果を期待する根拠はない。
- 対応モデルの有無と実測結果は別だ。研究の2.19倍を、表の別方式に移し替えてはいけない。
追加モデルなしの対照実験には、公式のN-gram設定を使える。以下はターゲットを今回のモデルに置き換えた 未実行の比較用例 だ。
vllm serve google/gemma-4-E4B-it-qat-w4a16-ct \
--host 127.0.0.1 \
--max-model-len 8192 \
--max-num-seqs 1 \
--max-num-batched-tokens 2048 \
--gpu-memory-utilization 0.80 \
--enable-chunked-prefill \
--enable-prefix-caching \
--speculative-config '{"method":"ngram","num_speculative_tokens":2,"prompt_lookup_min":2,"prompt_lookup_max":5}'
同じ2候補でも、候補を作る費用も、当たる入力も違う。だから比較する意味がある。
教訓:速いカーネルを探す前に、呼び出し回数を見る
✗ "約2倍速いなら、最初の出力も半分の時間だ" → TTFOの短縮は10.0〜14.2%
✗ "GEMMになったから、主要カーネルが速くなった" → 代表例は2.78msから2.79ms
✗ "受理長2.595なら、速度も2.595倍だ" → 候補生成と検証の費用が残る
✗ "360回通ったから、360問を正解した" → 9プロンプトの反復で出力検証成功は349件
✗ "同時実行数1で速ければ、本番でも同じだ" → 混雑時の処理能力は別途測定が必要
この研究の価値は「Gemma 4を速くする設定があった」だけではない。単発のカーネル、生成の進み方、ユーザーが待つ時間を分けて測った結果、1回が重い処理でも、呼ぶ回数を減らせば勝てると見えたことだ。
自分のLLM配信でも、主要カーネルをさらに削る余地が小さいなら、そのカーネルを何回呼んでいるかを見てほしい。今日、同じ入力でARとMTPを1組比較し、出力長・妥当性・経過時間を並べることから始めよう。
参考資料
Beneath the Tokens: A Performance Engineering Study of Multi-Token Prediction in GPU-Accelerated LLM Inference / Suwesh Prasad Sah / 2026-09-28 / CC BY 4.0。本記事の測定表は同論文の値を抜粋・再構成し、一部の比率を再計算した。
https://arxiv.org/html/2609.35188v1
Gemma 4 Multi-Token Prediction (MTP) using Hugging Face Transformers / Google。本文説明はCC BY 4.0、コード例はApache 2.0。本記事のTransformers例はモデル指定・設定を変更した。
https://ai.google.dev/gemma/docs/mtp/mtp
Gemma 4 E4B IT QAT W4A16 / Google
https://huggingface.co/google/gemma-4-E4B-it-qat-w4a16-ct
Gemma 4 E4B IT Assistant / Google
https://huggingface.co/google/gemma-4-E4B-it-assistant
Speculative Decoding / vLLM
https://docs.vllm.ai/en/latest/features/speculative_decoding/
MTP (Multi-Token Prediction) / vLLM
https://docs.vllm.ai/en/latest/features/speculative_decoding/mtp/
N-Gram Speculation / vLLM
https://docs.vllm.ai/en/latest/features/speculative_decoding/n_gram/
Draft Models / vLLM
https://docs.vllm.ai/en/latest/features/speculative_decoding/draft_model/
EAGLE Draft Models / vLLM
https://docs.vllm.ai/en/latest/features/speculative_decoding/eagle/
GPUを増やす前の比較に使えそうなら、いいねと保存を。LLMの配信を担当している仲間にも、この「1回の速さと呼ぶ回数」の違いをシェアしてほしい。
コメントで教えてほしい。
- 最初に試すなら、専用MTPと追加モデル不要のN-gram、どちらを選ぶ?
- あなたの用途で困っているのは、最初の出力までの待ち時間、それとも生成中の遅さ?
- 候補を2個から増やしたら、速くなると思う? それとも検証コストが先に効く?