8月31日、Abid Ali Awanが「Speed Up LLM Inference with DSpark Speculative Decoding」と題した記事を公開した。この記事では、DeepSeekが開発した投機的デコーディング手法「DSpark」をllama.cppで実際に試し、ローカルLLM推論の速度向上を測定する方法について詳しく紹介されている。
DSpark投機的デコーディングとは何か
投機的デコーディング(Speculative Decoding)は、小さなドラフトモデルが先にトークンを予測し、大きなターゲットモデルがそれを並列検証することで、生成速度を引き上げる手法だ。複数のアプローチが存在するが、代表的なものとして以下の3つがある。
- MTP(Multi-Token Prediction):1回のフォワードパスで複数トークンを同時に予測するアプローチ。DeepSeek-V3などで採用されている(論文)
- Medusa:ターゲットモデルに複数のデコーダヘッドを追加し、並列でドラフトトークンを生成する手法(論文)
- EAGLE:ターゲットモデルの特徴量を再利用して軽量なドラフトモデルを動かす手法で、高いドラフト受諾率を実現する(論文)
DSparkはDeepSeekが提案した独自の改良手法(論文)である。
通常の並列ドラフトモデルは、トークンのブロックを一度に予測できる反面、後半の予測が前半の情報を十分に活用できず精度が落ちる問題がある。DSparkは並列バックボーンと軽量な逐次コンポーネントを組み合わせることで、この精度低下を抑えつつ並列生成の速度メリットを保つ設計となっている。さらに、ドラフトトークンが検証を通過する確率を推定し、信頼度の低い部分を切り捨てることで無駄な検証コストを削減できる。
DeepSeekは自社の本番環境でDSparkを導入し、旧MTP-1ベースラインと比較してユーザーあたりの生成速度が60〜85%向上したと報告している。ただし、これはDeepSeekの大規模インフラでの数値であり、ローカル環境での小規模モデルに直接当てはまるわけではない点は注意が必要だ。
llama.cppとQwen3-8Bで実際に測定する
環境構築
llama.cppを最新ソースからビルドし、CUDA加速を有効にする。
apt-get update && apt-get install -y git cmake build-essential
cd /workspace && git clone https://github.com/ggml-org/llama.cpp
cmake llama.cpp -B llama.cpp/build \
-DBUILD_SHARED_LIBS=OFF -DGGML_CUDA=ON
cmake --build llama.cpp/build \
--config Release -j --clean-first \
--target llama-cli llama-mtmd-cli llama-server llama-gguf-split
モデルのダウンロード
ターゲットモデルとDSparkドラフトモデルをHugging Face CLIで取得する。
pip install -U huggingface_hub
hf auth login --token "$HF_TOKEN"
# ターゲットモデル(Qwen3-8B Q4_K_M: 4.7GB)
hf download Qwen/Qwen3-8B-GGUF Qwen3-8B-Q4_K_M.gguf --local-dir /workspace/models
# DSparkドラフトモデル(Q8_0: 1.2GB)
hf download ggml-org/Qwen3-8B-GGUF dspark-Qwen3-8B-Q8_0.gguf --local-dir /workspace/models
ベースラインとDSparkの速度比較
ベースライン計測(DSpark無効)
cd /workspace/llama.cpp
./build/bin/llama-cli \
-m /workspace/models/Qwen3-8B-Q4_K_M.gguf \
-ngl all -fa on --temp 0 --top-k 1 -n 512 -st \
-p "Write a complete Python implementation of merge sort. Explain how it works and include its time and space complexity. /no_think"
-ngl allで全レイヤーをGPUにオフロード、-fa onでFlash Attentionを有効にしている。--temp 0 --top-k 1で決定論的デコーディングを指定し、比較条件を揃えている。
結果:
[ Prompt: 294.6 t/s | Generation: 95.0 t/s ]
DSpark有効時
./build/bin/llama-cli \
-m /workspace/models/Qwen3-8B-Q4_K_M.gguf \
-md /workspace/models/dspark-Qwen3-8B-Q8_0.gguf \
--spec-type draft-dspark \
--spec-draft-n-max 3 \
-ngl all -ngld all -fa on --temp 0 --top-k 1 -n 512 -st \
-p "Write a complete Python implementation of merge sort. ..."
-mdでDSparkドラフトモデルを指定、--spec-type draft-dsparkでDSparkモードを有効化、--spec-draft-n-max 3で最大3トークンのドラフトを許可する。
結果:
[ Prompt: 88.0 t/s | Generation: 124.9 t/s ]
結果まとめ
| 設定 | プロンプト処理速度 | 生成速度 |
|---|---|---|
| Qwen3-8B(ベースライン) | 294.6 t/s | 95.0 t/s |
| Qwen3-8B + DSpark | 88.0 t/s | 124.9 t/s |
生成速度は95.0 → 124.9 tokens/s、約1.31倍(+31.5%)の向上となった。一方、プロンプト処理速度はDSpark有効時に294.6→88.0 t/sと大きく低下している。これはDSpark有効時にはドラフトモデル自身のプリフィル処理(入力プロンプト全体をドラフトモデルにも通すKVキャッシュの構築)が加わるためだ。プロンプト処理の増加コストは、長い応答を生成するワークロードであれば生成速度の向上によって十分に相殺される。
現時点での評価と制限
著者のAbid Ali Awanは、実用性の観点ではMTPのほうが依然として有力な選択肢だと述べている。理由は主に2点だ。
- 対応モデルが少ない:DSparkの互換ドラフトモデルが存在するモデルは現時点では限られている
- llama.cppのサポートがまだ新しい:バグや不安定な挙動に遭遇する可能性がある
ただし、ドラフトの品質が高い場合にはDSparkがMTPを上回ることもあるとしており、セットアップ自体はllama.cpp上で完結する手軽さがある。
詳細はSpeed Up LLM Inference with DSpark Speculative Decodingを参照していただきたい。