IQuest-Coder-40BのCPU・GPU・Aider比較
IQuest-Coder-V1-40BをCPU Q5_K_M、GPU nvfp4、Aider whole-editで計測しました。LLM導入と開発支援に向け、GPUの25–28 tok/sと長い入力・出力の待ち時間を比較します。
3構成の結果
IQuest-Coder-V1-40B を CPU(EPYC 9175F)、GPU(vLLM + nvfp4)、Aider の whole-edit で比較しました。開発パイプラインに使うため、入力と生成の速度、終端制御を確認しています。
今回の CPU 構成は長い入力の待ち時間が大きく、GPU は25–28 tok/sでした。GPU でも whole-edit は全ファイルの出力が長くなるため、待ち時間が増えました。
実験環境
| 項目 | 仕様 |
|---|---|
| CPU | AMD EPYC 9175F(Zen 5, 16C, L3 512MB) |
| GPU | NVIDIA RTX PRO 6000 Blackwell Max-Q(96GB VRAM) |
| メモリ | DDR5-6400 768GB(12ch) |
| OS | Ubuntu 24.04 LTS |
検証構成
| 構成 | Runtime | 量子化 | 配置 |
|---|---|---|---|
| A: CPU推論 | llama.cpp server(Podman) | Q5_K_M(GGUF) | CPU RAM |
| B: GPU推論 | vLLM | nvfp4 | GPU VRAM |
| C: Aider利用 | vLLM(Loop-Instruct variant) | nvfp4 | GPU VRAM |
CPU構成の待ち時間
IQuest-Coder-V1-40B-Instructは40B級のDense(非MoE)コーディング特化モデルです。MoEモデルと違い推論時に全パラメータを使うため、計算量がそのままモデルサイズに比例します。
最初に試したのは、IQuest-Coder-V1-40B-Instruct.q5_k_m.gguf を Podman 上の llama.cpp server を用いて、GPUを使わずにCPU(AMD EPYC 9175F, 16コア)のみで起動する構成です。コンテキスト長は 8192 に設定し、AiderやエージェントシステムなどTTFT(Time To First Token)と低レイテンシが求められる「待たない」パイプライン処理を想定していました。
CPU では次の問題を確認しました。
- CPU 使用率: Dense 40B は各 token で全層を計算し、コアが高い使用率を維持しました
- TTFT: 4k〜5k tokens を超える入力(例:
task.n_tokens=4640)では Prompt evaluation の待ち時間が長くなりました - SSD: ロードは短くなりましたが、生成と Prompt eval の速度はほぼ変わりませんでした
- batch 設定:
llama-serverのbatch-size 2048、ubatch-size 512は throughput 寄りで、低レイテンシ用途に合いませんでした
NUMA bind、スレッド指定、mlock は適用済みでした。この構成では、Dense 40B の CPU 処理が主な制約と考えています。
構成A 計測結果
| 項目 | 実測値 |
|---|---|
| TTFT(4k-5kプロンプト時) | 数十秒(体感破綻) |
| CPU使用率 | 全コア100%張り付き |
| 問題の本質 | 40B全層を毎トークン計算、省略不可 |
GPU(nvfp4)環境への移行と実測
CPUでの限界を踏まえ、GPUを利用した構成(vLLM + nvfp4)へと移行しました。比較対象として、111Bクラスの推論モデルである command-a-reasoning も並行して評価しています。
実測スループット
vLLMのログから得られた実測値は以下の通りです。
| 指標 | 実測値 |
|---|---|
| PP速度(Prompt throughput) | 1,100-2,300 tok/s |
| TG速度(Generation throughput) | 25-28 tok/s(安定) |
| KVキャッシュ使用率 | 2-12% |
| Prefixキャッシュヒット率 | 20-45% |
vLLMログからの連続計測(抜粋):
Engine 000: Avg generation throughput: 28.3 tokens/s, KV cache usage: 2.0%, Prefix cache hit rate: 22.8%
Engine 000: Avg generation throughput: 28.0 tokens/s, KV cache usage: 2.3%, Prefix cache hit rate: 22.8%
Engine 000: Avg generation throughput: 27.8 tokens/s, KV cache usage: 2.8%, Prefix cache hit rate: 22.8%
Engine 000: Avg generation throughput: 27.4 tokens/s, KV cache usage: 3.5%, Prefix cache hit rate: 22.8%
- Prompt throughput は約1100〜2300 tok/sでした
- Generation throughput は25〜28 tok/sで、111Bの command-a-reasoning より約2.3〜2.5倍速くなりました
- KV cache usage は2〜12%でした
- Prefix cache hit rate は20〜45%でした。system prompt と tool schema の固定で改善する余地があります
Running: 1 reqs の間は生成が続いていました。ログの「0 tok/s」は集計窓のタイミングと考えられ、ハングやデッドロックの兆候は見られませんでした。
TG 25–28 tok/sから見積もった、出力長ごとの待ち時間です。
- 200トークン: 約7-8秒
- 400トークン: 約14-16秒
- 800トークン: 約30秒
111Bモデルより半分以下の待ち時間です。agent やテスト生成に使う際の差になります。
Aider whole-edit形式での検証
Aider の whole-edit では、出力全体の長さが問題になりました。
| 指標 | 実測値 |
|---|---|
| TG速度 | 0.6-8 tok/s(不安定) |
| KVキャッシュ使用率 | 7-13%(急激に増加) |
| Prefixキャッシュヒット率 | 6%(ほぼ無効) |
whole-edit は全ファイルを生成します。repo-map と添付ファイルで入力も増え、KV cache が増加しました。毎回 context が変わるため、prefix cache hit rate は6%でした。
比較サマリ
| 構成 | TG速度(tok/s) | 実用判定 | 用途 |
|---|---|---|---|
| A: CPU Q5_K_M | 測定不能(TTFT破綻) | 不可 | - |
| B: GPU nvfp4 | 25-28 | 実用 | agent/テスト生成/CI |
| C: Aider whole-edit | 0.6-8 | 非実用 | - |
Performance Factor(PF)の定義
実務での体感に直結する指標として、モデル規模(パラメータ数)あたりの生成トークン数を「PF(Performance Factor)」として定義しました。
PF ≒ generation tok/s ÷ モデル規模(B)
| モデル | パラメータ | TG速度 | tok/s per B | 相対PF |
|---|---|---|---|---|
| command-a-reasoning | 111B | ~11 tok/s | 0.10 | 1.0 |
| IQuest-Coder-40B nvfp4 | 40B | 26-28 tok/s | 0.65-0.70 | ≈6.5-7.0 |
| 小型7B fp16 | 7B | 60-80 tok/s | 9-11 | 別枠 |
この PF では IQuest-Coder-40B が111B系の6〜7倍でした。サイズあたりの速度比較であり、推論品質や nvfp4 の正しさを単独で証明する指標ではありません。
考察
なぜDenseはCPUで厳しいのか
MoEモデル(例: Kimi-K2.5の活性32B)はトークンごとに一部のエキスパートだけ計算します。Denseは40B全層を毎回計算するため、計算量の削減が効きません。同じ「40B級」でもCPU推論の負荷は根本的に異なります。
12チャネルの EPYC 9175F でも、全層を読む Dense の負荷は大きくなります。MoE の一部 expert を L3 cache に残す方式とはアクセスが異なります。
| 項目 | Dense 40B | MoE 229B(活性10B) |
|---|---|---|
| 毎トークンの計算量 | 40B全層 | 10B相当 |
| L3キャッシュ活用 | 効かない(全層アクセス) | 効く(エキスパート局所性) |
| CPU推論のTG | 測定困難 | 10-37 tok/s |
| CPU推論の実用性 | 非実用 | バッチ用途で実用 |
Aider whole-editの構造的問題
whole-edit形式が遅い原因:
- ファイル全体を出力するためトークン数が膨大
- repo-map + 添付ファイルでpromptも肥大
- Prefixキャッシュヒット率が6%(変動するコンテキストのため)
- KVキャッシュが急速に膨張(7→13%)
対策はwhole-editを避けてdiff/patch形式に変更することです。出力トークン数を大幅に削減でき、生成速度の問題を構造的に回避できます。
モデル品質と制御性
Go の構造化した長いテストコードを生成できました。111B Reasoning モデルより、論理の誤りや原文にない補完が少ない例もありました。EOS(End of Sequence)と stop・max_tokens が効き、生成の終端を制御できました。
深い推論、証明、長い思考では command-a-reasoning を候補にしています。日常の生成では、速度と終端制御も比較します。
安定運用できている理由
安定して動いた構成の特徴は次の4点です。
nvfp4 × vLLM main/nightlyの組み合わせが成立しているstop / max_tokensが適切に効いている- Instruct 型らしく EOS が素直で、出力の終端制御がしやすい
agent-gatewayの設計と噛み合っている。特に non-stream 時だけ retrieval を差し込むような実装方針とも整合している
LLM導入では、モデルだけでなく serving と agent-gateway の組み合わせも確認する必要があります。
改善策の優先順位
同じ待ち時間の問題を調べる場合の候補です。
- GPU 配置
--device nvidia.com/gpu=allと--n-gpu-layers 999で GPU に載せます。今回の GPU は RTX PRO 6000 MAX-Q 96GBです。 - CPU 用の調整案
batch-sizeを512〜1024にします。ubatch-sizeを128〜256にします。- 履歴と repo-map を減らします。
- モデル縮小案 CPU が必要なら7B〜14Bを候補にします。
再現用の設定
GPU nvfp4(推奨構成)
vllm serve IQuestLab/IQuest-Coder-V1-40B-Instruct-nvfp4 \
--max-num-seqs 1 \
--max-model-len 32768
CPU Q5_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 "$MODEL" \
--jinja -c 8192 \
--threads 14 --threads-batch 14 \
-b 2048 -ub 512 \
--parallel 1 --flash-attn on
Aider設定の最適化
--edit-format diff: whole-editを避けて出力を削減temperature=0: greedy固定で生成を高速化- repo-mapと/add対象を最小限に
max_model_lenを必要最小に設定
結論と今後の展望
今回の環境では、IQuest-Coder-V1-40B + nvfp4 + vLLM は日常の生成に使う候補になりました。次の分担を検討しています。
- 日常(agent/aider/CI): IQuest-Coder-40B nvfp4を主候補にします
- 深い推論・設計レビュー: command-a-reasoning(サブ)
- バッチ処理(CPU常駐): MoEモデル(Kimi-K2.5等)
IQuest-Coder-40B を標準のルーティング先とし、難しい推論や設計レビューを command-a-reasoning に任せる案です。25–28 tok/sという速度だけで、全タスクの品質を判断したものではありません。
次は prompt を固定し、prefix cache hit rate を約40%から60%以上にすることを目標にします。p95 latency を基準とした SLO の調整も予定しています。
