Q4_K_MとQ8_0のCPU推論

MetaのLlama-4-Maverickは128 expertのMoEで、tokenごとの活性パラメータは17B級です。

EPYC 9175Fと768GB DDR5で、約290GBのQ4_K_Mと約426GBのQ8_0を同じ課題で比較しました。LLM導入で、処理量を優先するバッチと、コード修正の品質を重視する用途を分けるためです。

Llama-4-Maverick-17B-128E Instructをllama.cppで測りました。GPUのVRAMに収まらないモデルを、CPUと大容量メモリで使う構成です。

EPYCのZen 5 / Turinは12チャネルDDR5と大きなL3を持ち、1兆級を含む疎なモデルのCPU推論を検討する環境です。

目的

  1. Q4_K_MとQ8_0のPrefill/Decode速度を同一環境で比較
  2. TTFT(Time To First Token)の差を定量化
  3. 出力品質の差を実務タスクで評価
  4. バッチ処理とaider利用での使い分け基準を確立

実験環境

項目仕様
CPUAMD EPYC 9175F(Zen 5, 16C, L3 512MB)
メモリDDR5-6400 768GB(12ch)
GPU使用せず(CPU推論)
OSUbuntu 24.04 LTS
Runtimellama.cpp server(Podman rootless)
スレッド14
コンテキスト16,384

16コアに対し14スレッドにしました。帯域の飽和とOS・ネットワークIOの余裕を考慮した設定です。

モデル仕様

項目Q4_K_MQ8_0
アーキテクチャLlama-4-Maverick(MoE, 128E)同左
モデルサイズ約290GB約426GB
量子化精度4bit混合8bit

結果

速度比較

指標Q4_K_MQ8_0差分
PP速度(tok/s)65-6850-52Q4が約30%高速
TG速度(tok/s)21-2415-16Q4が約40%高速
TTFT(800-1000tok)12-17秒16-20秒Q4が3-5秒速い

Q4_K_M実測ログ

Prompt(tok)PP時間(s)PP速度(tok/s)Gen(tok)TG速度(tok/s)
81912.068.416523.7
1,10116.865.481421.3

Q8_0実測ログ

Prompt(tok)PP時間(s)PP速度(tok/s)Gen(tok)TG速度(tok/s)
81915.652.410416.6
1,00019.750.891615.2

メモリ挙動

  • Q4_K_M: mmap + page cacheで必要部分のみ常駐。prompt cache 1エントリあたり180-380MiB
  • Q8_0: buff/cacheに数百GBが載る。RSSは小さく見えるが正常(mmapの特性)
  • MoE(128E)のため、アクティブなエキスパートのみ頻繁に参照され、未使用ページは温まりにくい

重みはmmapとページキャッシュで読みます。freeのbuff/cacheに数百GBが見え、RSSが小さくてもllama.cppの異常ではありません。

128Eでは使うexpertを頻繁に読み、未使用ページは温まりにくくなります。

考察

速度差の原因

Q4_K_MはQ8_0の約68%(290GB / 426GB)です。tokenごとにexpertの重みを読むため、量子化で転送量を減らせます。

TG差40%はサイズ差32%を超えています。decodeのランダムアクセスで、cache missとメモリ待ちが増幅するという解釈です。

品質差の実感

今回Q8_0で良いと感じた点です。

  • 長い会話の文脈が安定
  • aiderでの破壊的編集が減る
  • 出力を安心して扱いやすい

差は大きくない場面もあります。雛形と要約はQ4_K_Mで対応でき、aiderのコードや文書雛形でも重大な誤りは少ない印象でした。差が目立つのは複雑なrepo操作と長文です。定量的な品質試験ではありません。

768GB RAM環境だからこそQ8_0が選択肢になる

768GBならQ8_0の426GBにKVとpage cacheも載せられます。この容量がある環境に限った選択です。

用途別の選択基準

今回の使い分けです。

  • 高回転のワンショット生成、Dagster/dbtのバッチ処理: Q4_K_Mが有力。速度40%差は処理量に直結する
  • aider運用、複雑なrepo操作、長文生成: Q8_0。破壊的編集のリスク軽減が速度差より重い
  • 日次ON/OFF運用: Q4_K_M。起動が速い
  • 常時稼働・常駐: Q8_0。品質安定性が長時間運用で効いてくる
  • ローカルナレッジ処理: 機密性の高い社内データをローカル内で構造化・蒸留するタスクでは両方が使える

この128EのCPU構成では、Q8_0も15-16 tok/sでした。

品質が重要な作業ではQ8_0、通常の高回転処理ではQ4_K_Mを使う方針です。

再現方法

Q4_K_M

  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/Llama-4-Maverick-17B-128E-Instruct-Q4_K_M.gguf \
  --jinja -c 16384 \
  --threads 14 --threads-batch 14 \
  -b 1024 -ub 256 \
  --parallel 1 --flash-attn on
  

Q8_0

同じコマンドでモデルをQ8_0へ変えます。

補足ノウハウ

MoEのmmap挙動

同じ話題ではexpertの再参照でmmap page cacheが温まります。話題が頻繁に変わる処理はpage faultが増える傾向です。

prompt cacheの効果

両方でLCP similarityによるprompt cacheが使えます。System Promptを固定すると2回目以降のTTFTを短縮できます。