5分でできる設定
vLLMでLLMを動かしているのにSpeculative Decodingを有効にしていなければ、GPUの潜在的な速度の40〜60%を無駄にしています。このセクションでその機能をすぐに有効にする方法を説明します。
環境の準備
vLLMバージョン0.4.0以上が必要です:
pip install vllm --upgrade
python -c "import vllm; print(vllm.__version__)"
Speculative Decodingを有効にしてサーバーを起動
次のコマンドを実行してすぐに有効化できます — targetモデルはLlama 3.1 8B、draftモデルはLlama 3.2 1B:
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-3.1-8B-Instruct \
--speculative-model meta-llama/Llama-3.2-1B-Instruct \
--num-speculative-tokens 5 \
--use-v2-block-manager \
--gpu-memory-utilization 0.9
通常のvLLMコマンドと比べてわずか2行追加するだけです。自分でproduction環境に適用してみましたが、結果はかなり安定していました — A10GでLlama 3.1 8B + draft 1Bの組み合わせでスループットが約1.8〜2倍向上しました。
効果を素早くテストする
curl http://localhost:8000/v1/completions \
-H "Content-Type: application/json" \
-d '{
"model": "meta-llama/Llama-3.1-8B-Instruct",
"prompt": "CSVファイルを読み込むPythonスクリプトを書いてください:",
"max_tokens": 200,
"temperature": 0
}'
テスト時はtemperature: 0に注意してください — speculative decodingはgreedy decodingで最も効果を発揮します。
Speculative Decodingの仕組み
仕組みを理解すれば、推測で調整するのではなく、適切にチューニングできます。LLM推論の核心的な問題:生成される各トークンは、モデル全体を通じて1回のforward passを実行する必要があります。GPU上の8Bモデルでは、このステップは膨大なメモリ帯域幅を消費します — 実際の計算量はそれほど多くないにもかかわらず。
Draft-then-Verifyの仕組み
Speculative Decodingは推論を2つのステップに分けます:
- Draft phase: 小さなdraftモデル(例:1B)がN個のトークンを連続して素早く生成します — これを「speculative tokens」と呼びます。
- Verify phase: 大きなtargetモデル(8B/70B)が、N個のトークンすべてをたった1回のforward passで検証します。
draftモデルが5トークンすべてを正しく予測したとします:targetモデルのforward pass 1回 + draftモデル1回のコストで5トークンを生成できました — 5回別々に実行する代わりに。これがスループットが大幅に向上する理由です。
では、draftがk番目のトークンで誤りを予測した場合は?targetモデルはその位置から拒否し、それ以前の正しいトークンを保持して再生成します。誤ったトークンは一切出力されません — outputはtargetモデル単独で実行した場合と完全に同一です。これがquantizationやpruningとの違いで、それらは品質とのトレードオフがあります。
最も効果的な場面
- 低temperature(0.0〜0.6):draftモデルが正確に予測しやすい
- 繰り返しパターンのあるoutput:コード、markdown、技術的なリスト
- GPUがFLOPsではなくメモリ帯域幅でボトルネックになっている場合
temperatureが高い(0.8以上)創作系のライティングでは、draftモデルがtargetモデルのランダム性に追いつきにくいため、効果が低下します。
高度な設定
speculative tokensの数をチューニング
--num-speculative-tokensパラメータは実際の結果に大きく影響します:
# 控えめ:3トークン — acceptance rateが高く、スループットは適度に向上
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-3.1-8B-Instruct \
--speculative-model meta-llama/Llama-3.2-1B-Instruct \
--num-speculative-tokens 3
# 積極的:7トークン — ワークロードに合えばスループットがより向上
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-3.1-8B-Instruct \
--speculative-model meta-llama/Llama-3.2-1B-Instruct \
--num-speculative-tokens 7
シンプルなルール:draft tokensのacceptance rateが70%を超えているならnum-speculative-tokensを増やしましょう。50%未満なら減らすか、draftモデルを変更してください。
Ngram-based Speculative Decoding — draftモデル不要
適切なdraftモデルがない、またはGPUのVRAMが不足している場合は?vLLMはngram prompt lookupをサポートしています — 入力コンテキスト自体を使って次のトークンを予測します:
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-3.1-70B-Instruct \
--speculative-model "[ngram]" \
--num-speculative-tokens 5 \
--ngram-prompt-lookup-max 4 \
--use-v2-block-manager
この方法は、コード生成やRAGなど — outputが入力の語句を繰り返すことが多いタスクに特に有効です。追加のGPUメモリは不要で、フラグを2つ追加するだけです。
EAGLE Speculative Decoding
同じファミリーの小さいモデルをdraftとして使う代わりに、EAGLEはtargetモデルに特別に調整された専用のdraftモデルをトレーニングします — 実際のacceptance rateが15〜20%高くなります:
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-3.1-8B-Instruct \
--speculative-model yuhuili/EAGLE-LLaMA3-Instruct-8B \
--speculative-draft-tensor-parallel-size 1 \
--num-speculative-tokens 4
HuggingFaceでEAGLE-{ModelName}形式のEAGLEモデルを探してください。Llama 3.x以外にも、Qwen2.5やMistral向けのモデルがあります — targetモデル名で検索すればすぐに見つかります。
マルチGPU設定
# targetモデルは2 GPU、draftモデルは1 GPUで実行
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-3.1-70B-Instruct \
--tensor-parallel-size 2 \
--speculative-model meta-llama/Llama-3.1-8B-Instruct \
--speculative-draft-tensor-parallel-size 1 \
--num-speculative-tokens 4 \
--use-v2-block-manager
注意:--speculative-draft-tensor-parallel-sizeは--tensor-parallel-sizeの約数でなければなりません。
実践的なヒント
同じファミリーのdraftモデルを選ぶ
acceptance rateを高くするために、draftモデルはtargetモデルと同じtokenizerとアーキテクチャである必要があります:
- Llama 3.1 8B → draft:Llama 3.2 1B または 3B
- Llama 3.1 70B → draft:Llama 3.1 8B
- Qwen2.5 7B → draft:Qwen2.5 0.5B または 1.5B
- Mistral 7B → 同じファミリーの小さいdraftモデルなし — ngramを代わりに使用
異なるファミリーのdraftモデル(例:QwenをLlamaのdraftとして使用)は通常acceptance rateが30%未満で、速度改善にならず、むしろ遅くなることもあります。
有効化前にGPUメモリを計算する
# 必要なメモリの見積もり(fp16)
# Targetモデル 8B: ~16 GB
# Draftモデル 1B: ~2 GB
# KV cache: ~4 GB
# 合計: ~22 GB → GPU 24 GB必要(RTX 3090/4090またはA10G)
nvidia-smi --query-gpu=memory.total,memory.free --format=csv
VRAMが不足している場合は、draftモデルにint8 quantizationを使用してメモリを〜50%節約できます:
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-3.1-8B-Instruct \
--speculative-model meta-llama/Llama-3.2-1B-Instruct \
--speculative-model-quantization int8 \
--num-speculative-tokens 5
実際のacceptance rateを監視する
vLLMはspeculative decodingが実際に効果的かどうかを確認するためのmetricsを公開しています:
import requests
metrics = requests.get("http://localhost:8000/metrics").text
for line in metrics.split("\n"):
if "spec" in line.lower() and not line.startswith("#"):
print(line)
監視すべき重要なMetrics:
vllm:spec_decode_draft_acceptance_rate:目標は0.6以上vllm:spec_decode_efficiency:ベースラインとの比較効率vllm:generation_tokens_per_second:実際のスループット
本番環境に移行する前にベンチマークを実施する
python benchmarks/benchmark_throughput.py \
--model meta-llama/Llama-3.1-8B-Instruct \
--dataset sharegpt \
--num-prompts 200 \
--speculative-model meta-llama/Llama-3.2-1B-Instruct \
--num-speculative-tokens 5
ベンチマーク結果はワークロードによってかなり異なります:コード生成は通常2.5〜3倍向上し、会話型チャットは1.5〜2倍向上します。他の人の数値で判断しないでください — 実際のトラフィックに近いデータセットでベンチマークを実行することが意味を持ちます。
Speculative Decodingは基本的なvLLMガイドではほとんど言及されませんが、outputの品質に手を加えずにスループットを向上させることができる数少ない手法の一つです。唯一の条件:適切なdraftモデルを選択し、実際のアプリケーションの入力パターンに合わせてnum-speculative-tokensをチューニングすることです。

