背景

Llama-4-Scoutは16エキスパート、17B活性パラメータのMeta MoEです。128エキスパートのMaverickよりCPUキャッシュを使いやすいのではないかと考えました。

CPU(Q6_K / llama.cpp)とGPU(nvfp4 / vLLM)で速度、品質、メモリを比較しました。CPUは初回とキャッシュが温まった後を分けて測っています。

目的は、GPUなしの llama.cpp で oneshot 要約や fire-and-forget の冪等パイプラインを動かせるか確認することです。GPUのnvfp4も日常の開発支援として使えるか調べました。

目的

  1. CPU Q6_K推論の定常速度を実測(キャッシュ温後)
  2. GPU nvfp4推論のPrefill/Decode速度とVRAM配分を記録
  3. mmapページキャッシュとprompt cacheの効果を定量化
  4. 100kコンテキスト境界の実態を把握

実験環境

項目仕様
CPUAMD EPYC 9175F(Zen 5, 16C, L3 512MB)
メモリDDR5-6400 768GB(12ch)
GPUNVIDIA RTX PRO 6000 Blackwell Max-Q(96GB VRAM)
OSUbuntu 24.04 LTS

2構成

構成Runtime量子化配置ctx
A: CPUllama.cppQ6_K(3分割GGUF)全CPU8,192
B: GPUvLLM 0.14.0rc1nvfp4(NVIDIA ModelOpt)全GPU~110K

結果

構成A: CPU Q6_K(th=16, ctx=8K)

指標測定値備考
PP(Prefill)約40 tok/s2.5k-5kトークンでも安定
TG(Decode)16.3-17.5 tok/s16コア均一負荷、温度64℃固定

初回はmmapのページフォールト、全promptの評価、KV初期化が重なり遅くなりました。mmap では、起動直後に全重みがRAMへ読み込まれているとは限りません。

2回目以降はOSページキャッシュとprompt cacheで定常速度へ達しました。LCP(Longest Common Prefix)が一致する場合、f_keep > 0.7を確認しています。

Prefillは残りますが、固定prefixを再利用すると差分だけの処理になります。

構成B: GPU nvfp4(vLLM, Blackwell 96GB)

指標測定値レンジピーク備考
PP(Prefill)700-1,200 tok/s1,370 tok/s長文プロンプトで顕在化
TG(Decode)30-60 tok/s112 tok/sウォームアップ後安定

Prefix Cache Hit Rateは10-48%でした。48%ではTTFTが短くなりました。

GPUのPrefillは1,370 tok/sで、aiderの反復リファクタリングの待ち時間が短く感じました。日本語の技術文書とDjango/Python設計では、FP4でも指示に沿う出力を得られました。

VRAM内訳

項目占有量
モデル常駐約63.5 GiB
KVキャッシュ利用可能分約20.2 GiB
最大コンテキスト長約110,256 tokens

BF16相当のKVでは、1GPUの上限は約100kです。256k以上にはFP8 KVまたはTP=2が必要と整理しています。96GBでもモデルとKVが競合するため、ctxはその内訳で決めます。

比較サマリ

構成TG(tok/s)VRAM用途
A: CPU Q6_K16-170バッチ要約、F&Fパイプライン
B: GPU nvfp430-60~64GBaider、対話型コード生成

考察

CPUキャッシュ戦略の効果

CPUはキャッシュ温後に17 tok/sでした。今回の運用では次を重視しました。

  • --mlock で重みを物理メモリに固定します。
  • System Promptを固定し、LCPを一致させます。
  • 再起動を避け、キャッシュを使い続けます。

oneshot 要約や同じprefixを持つ冪等バッチは、CPUで処理する候補です。業務システムへのLLM導入でも、対話処理とバッチ処理を分けて考えられます。

16エキスパートの構造的優位性

Scoutは16、Maverickは128エキスパートです。EPYC 9175Fの1CCD=1Core配置では、選択するexpertが少ないとL3に作業領域が残りやすいという解釈です。キャッシュ効果の因果を直接測った比較ではありません。

CPU速度はScout 17、Maverick 21-24 tok/sでした。モデルサイズの影響が大きいと考えています。Scoutは動作を予測しやすい印象でした。

nvfp4の品質

Django/Pythonの設計、ボイラープレート、ロジックレビューでは使える品質でした。数学の厳密な推論はやや弱く感じましたが、指示追従と日本語出力は安定していました。

感想

CPU 17 tok/sとGPU 30-60 tok/sの差は体感できました。非対話型の処理をCPUに任せれば、GPUを別モデルへ使えます。

GPUの1,370 tok/s Prefillと48%のPrefix Cacheは、aiderの待ち時間を減らしました。

固定prefixのバッチをCPU、低遅延の対話をGPUへ分ける構成を考えています。

再現方法

CPU Q6_K

  numactl --cpunodebind=0 --membind=0 \
  podman run --rm -it \
  -p 8081:8080 --shm-size 16g --cap-add=SYS_NICE \
  -v "$MO":/models:ro,Z $IMG \
  --host 0.0.0.0 --port 8080 \
  -m /models/Scout-17B-Q6_K.gguf \
  --threads 16 --threads-batch 16 \
  --batch-size 2048 --ubatch-size 512 \
  --mlock --ctx-size 8192 --flash-attn on \
  --parallel 1 --jinja
  

GPU nvfp4(vLLM)

  vllm serve nvidia/Llama-4-Scout-17B-16E-Instruct-NVFP4 \
  --dtype auto --gpu-memory-utilization 0.88 \
  --max-num-seqs 1 --max-model-len 110000 \
  --enable-prefix-caching --trust-remote-code
  

補足ノウハウ

キャッシュが効かなくなる条件

元のメモでは、次をキャッシュが効かなくなる条件として整理しています。

  • prompt先頭のテンプレートやツール定義を1文字でも変えると、prompt cacheが無効になり全Prefillへ戻ります。
  • プロセス再起動でOSページキャッシュがパージされ、cold startのI/O待ちが再発します。
  • 上限に達すると古いpromptが破棄されます。

100kコンテキスト境界

nvfp4モデルは63.5 GiB、KVは約20 GiBでした。BF16 KVでは約110kが物理上限です。この記録では256k/512k向けにFP8 KV+TP=2へ広げる案を残しています。