DeepSeek-V3.2の速度とキャッシュ

DeepSeek-V3.2 Specialeのローカル推論ログから、PP、TG、KV cache、prompt cache、MoEの条件を確認しました。Kimi系より遅く感じた理由を調べ、LLM導入時に揃える設定を整理します。

今回のログでは、PPに比べTGが伸びず、prompt cacheの部分不一致も繰り返し出ていました。

背景

EPYC 9175FのKimi-K2.5(1T級MoE)は、バッチで10-13 tok/sでした。別の判断を得るモデルとして、同じllama.cpp環境でDeepSeek-V3.2を評価しました。

DeepSeekのPPは50-100 tok/s、TGは14-15 tok/sでした。体感では遅さがありましたが、この数値だけでKimiとの速度順位は判断できません。モデルと運用設定を分けて確認します。

目的

  1. DeepSeek-V3.2のデコード速度が14-15 tok/sに停滞する原因を特定する
  2. llama.cppのログから、キャッシュ制御と最適化フラグの影響を定量的に把握する
  3. 改善策の優先順位を整理する

実験環境

  • CPU: AMD EPYC 9175F(Zen 5, 16C)
  • メモリ: DDR5-6400 768GB(12ch)
  • OS: Ubuntu 24.04 LTS
  • Runtime: llama.cpp(server mode, fused_moe=1)
  • Model: DeepSeek-V3.2 Speciale(MoE構成)
  • KV Cache: f16(デフォルト)

結果

推論スループット実測値

連続4タスクのログから抽出しました。

Task IDPP (tok)TG (tok)累積トークンPP速度 (tok/s)TG速度 (tok/s)PP時間 (s)TG時間 (s)
02,7311,0243,75599.7514.5727.470.3
10268571,0245,63674.4715.2111.567.3
20513119826,92952.9214.515.967.7
30344,8651,02412,818100.2214.2248.572.0

PPは50-100 tok/s、TGは14.22-15.21 tok/sでした。この4タスクではTGの変動が小さく、入力や累積トークン数を変えても伸びませんでした。

ログに観測されたキャッシュ不一致

  Common part does not match fully → kv cache rm [p0, end)
  

全タスクで先頭トークンの不一致とKVキャッシュ削除が出ていました。

Speculative Decodingの状態

  no implementations specified for speculative decoding
  

draftモデルを指定しておらず、Speculative Decodingは使っていません。

設定から考えられる原因

1. Speculative decoding(未使用)

no implementations specified for speculative decodingと記録されています。TGを改善する候補ですが、効果はまだ測っていません。

2. KV cacheの精度設定

llama.cppのログはKV self size: f16です。長い文脈では帯域とattention計算の負荷が増える可能性があります。Kimi-K2.5で使ったq8_0をDeepSeekでも試す案です。

3. MoE最適化の差

fused_moe=1は有効でした。vLLMやサービスの専用カーネルとllama.cppの汎用MoE実装、expert routingの違いが速度に影響する可能性があります。

4. ログに出たキャッシュ不一致

各タスクでCommon part does not match fullyの後にkv cache rm [p0, end)が出ています。

部分不一致でprompt cacheを削除しています。<think>、system、prefixの混在で先頭が変わっていた可能性があります。

キャッシュ条件が揃っていないため、モデル固有の遅さとして結論づける段階ではありません。

考察

TGが14-15 tok/sに留まる理由

ほぼ一定のTGは、メモリ帯域の制約を疑う材料です。f16 KV cacheと長い文脈でのattention負荷が考えられますが、このログだけでは原因を確定できません。

プロンプトキャッシュ不一致の影響

KimiではSystem Prompt + ナレッジダイジェストを固定してLCPキャッシュを使っていました。DeepSeek側では次の差がありました。

  1. <think>タグの有無の揺れ: Thinking Promptの有無がリクエストごとに変わり、先頭トークン列が不一致
  2. System Promptの微妙な差異: テンプレートが固定されていなかった
  3. 会話履歴の管理差: Kimi-K2.5は前の文脈を再利用する設計だったが、DeepSeek側は毎回文脈を再構築していた

改善策の優先順位

優先度施策期待効果実装コスト
Aプロンプトプレフィックスの固定化PP大幅短縮低(設定変更のみ)
BSpeculative Decoding導入TG体感速度改善中(ドラフトモデル選定が必要)
CKVキャッシュq8_0化TG帯域負荷軽減低(フラグ変更のみ)
D生成条件の統制公平な比較の実現低(テスト設計の問題)

A. プロンプトキャッシュの完全一致を作る

<think>、system、prefixテンプレートを固定し、先頭トークン列を揃えます。

B. Speculative decodingを使える構成にする

次にdraftモデルを用意し、speculative decodingのTG改善を測る案です。

C. KV cacheの型を落とす

cache-type-k/vでq8やiqを使える場合は、長文・長生成で比較します。

D. 生成条件を揃えて比較する

出力長、温度、top_p、stop、stream、system、thinkingを揃えます。thinkingの内部生成が増えると、見える出力が同じでも所要時間は変わります。

比較条件を揃えて再測定

今回確認できたのは、キャッシュの不一致と設定差です。体感の遅さをそのままDeepSeekのモデル性能とすることはできません。

まずprefixを揃え、その後にspeculative decodingとKV cacheを比較する方針です。

再現方法

1. DeepSeek-V3.2の実行

  podman run --rm -p 8081:8080 --shm-size 16g --cap-add=SYS_NICE \
  -v /path/to/deepseek-v3.2:/models:Z \
  compute.home.arpa/llamacpp-zen5:latest \
  -m /models/DeepSeek-V3.2-Speciale.gguf \
  --cache-type-k f16 --cache-type-v f16 --flash-attn on \
  --ctx-size 16384 --parallel 1 --threads 13 --threads-batch 13 \
  --batch-size 2048 --ubatch-size 512 --jinja --host 0.0.0.0 --port 8080
  

2. 改善版(KVキャッシュ量子化 + プロンプト固定)

  # KVキャッシュをq8_0に変更
--cache-type-k q8_0 --cache-type-v q8_0

# プロンプトキャッシュを有効化
--prompt-cache /tmp/deepseek-cache.bin
  

System Promptと<think>の有無もリクエスト間で固定します。

3. 計測

ログからS_PPとS_TGを抽出し、変更前後を比較します。

補足ノウハウ

プロンプトキャッシュを効かせるための原則

  1. 先頭トークン列を固定する: System Prompt → 固定コンテキスト → 可変部分、の順序を厳守
  2. Thinkingモードは一貫させる: 有効にするなら全リクエストで有効に。リクエストごとに切り替えるとキャッシュが毎回破棄される
  3. 温度・top_pを揃える: 生成パラメータの差異もキャッシュヒット率に影響する場合がある

Kimi-K2.5との公平な比較をするには

  • 出力トークン数、温度、top_p、stopシーケンス、stream有無を完全に一致させる
  • Thinking Tokenの扱いを統一する
  • 同一のハードウェア・スレッド数・KVキャッシュ設定で計測する