Qwen3.5-397Bのハイブリッド推論とCMS生成
Qwen3.5-397B IQ4_NLをEPYCとGPUで28回測定し、Django CMSの骨格生成を評価しました。LLM導入とWebシステム開発に向けた速度・構成・修正箇所の記録です。
Qwen3.5-397Bの速度とコード生成
Qwen3.5-397BをEPYCとコンシューマGPUで動かし、28回の連続推論を測定しました。総パラメータは397B、活性パラメータは17BのMoEです。通常はH100複数枚を使う規模ですが、ここではIQ4_NL量子化、cpu-moe、テンソルオフロードを組み合わせています。
常用できる速度かを確認し、LLM導入時の構成判断に使います。長文脈のコード生成では、WordPressライクなDjango CMSの仕様からプロジェクト骨格を生成しました。
測定項目
- IQ4_NL量子化での定常TG/PP速度を28回のランから統計的に把握
- ハイブリッドオフロード(cpu-moe / マルチGPUテンソルオフロード)の実行構成を記録
- コンテキスト長依存性と安定性を評価
- 400B級MoEの日常運用可能性を判定
- 長文脈コード生成タスク(Django CMS基盤)での品質評価
実験環境
| 項目 | 仕様 |
|---|---|
| CPU | AMD EPYC 9175F(Zen 5, 16C, L3 512MB) |
| メモリ | DDR5-6400 768GB(12ch) |
| GPU | NVIDIA RTX PRO 6000(96GB VRAM) |
| OS | Ubuntu 24.04 LTS |
| Runtime | ik_llama.cpp(cpu-moe有効) |
| 量子化 | IQ4_NL |
| コンテキスト | 最大262,144 |
結果
スループット統計(28回のラン)
| 指標 | Prefill (PP) | Generation (TG) |
|---|---|---|
| 最大値 | 372.24 tok/s | 24.04 tok/s |
| 最小値 | 101.49 tok/s | 19.13 tok/s |
| 平均(定常時) | 約160 tok/s | 約22.5 tok/s |
代表的なラン
| # | PP(tok) | TG(tok) | PP速度(tok/s) | TG速度(tok/s) | 合計(s) |
|---|---|---|---|---|---|
| 1 | 4,699 | 13 | 314.22 | 21.95 | 15.5 |
| 3 | 1,125 | 2,048 | 161.67 | 20.81 | 105.4 |
| 8 | 1,124 | 2,048 | 154.76 | 23.82 | 93.3 |
| 14 | 15,866 | 2,048 | 372.24 | 22.98 | 131.7 |
| 16 | 550 | 520 | 117.78 | 22.91 | 27.4 |
Run #14は15,866トークンの入力を42.6秒で処理し、22.98 tok/sで生成しました。約1.5万トークンのソースコードを40秒強で読み込めています。
コンテキスト依存性
- PP速度: 短いプロンプト(<1k)は100 tok/s台でした。入力が長くなると並列効率が上がり、300 tok/sを超えました。
- TG速度: 測定したコンテキスト長では21-24 tok/sでした。
ハイブリッドオフロード構成
単一GPU + cpu-moe構成
IMG=compute.home.arpa/ik_llama-cuda
MODEL=/models/.../IQ4_KSS/Qwen3.5-397B-A17B-IQ4_KSS-00001-of-00006.gguf
podman run --rm -it --device nvidia.com/gpu=all \
-p 8001:8080 --shm-size 16g --cap-add=SYS_NICE \
-v "$MO":/models:ro,Z "$IMG" \
--host 0.0.0.0 --port 8080 -m "$MODEL" \
-c 262144 --threads 13 --threads-batch 24 \
--jinja -b 2048 -ub 2048 -ngl 99 \
-fa on --no-mmap --cpu-moe
--cpu-moeでGPUに収まらないエキスパート計算をCPUへ移します。EPYC 9175Fの12ch DDR5でアクティブなエキスパートを供給し、GPUでAttentionを計算する構成です。
マルチGPUテンソルオフロード構成
2GPU構成では-otで正規表現に基づくレイヤー分散を指定します。
./build/bin/llama-server \
--model "$model" \
-fa on --ctx-size 135168 \
-ctk q8_0 -ctv q8_0 \
-ub 2048 -b 2048 -ngl 999 \
-ot "blk\.(0|1|2|...|12)\.ffn_(gate|up|down)_exps.*=CUDA0,\
blk\.(47|48|...|60)\.ffn_(gate|up|down)_exps.*=CUDA1" \
--cpu-moe --threads 24 --no-mmap --jinja
初期レイヤー(0-12)はCUDA0、終盤レイヤー(47-60)はCUDA1へ割り当て、中間はcpu-moeで処理します。VRAMの使用量を分散し、135kコンテキストを確保しました。
Django CMSの長文脈コード生成
評価内容
Qwen3.5-397B-A17Bに設計文書を渡し、WordPressの概念をDjangoへ対応させたCMS骨格を生成しました。仕様にはPosts/Pages、Categories/Tags、Comments、Media Library、Menus/Navigation、Drafts/scheduled publishing、Revision historyを含めています。
推論設定
IMG=compute.home.arpa/ik_llama-cuda
MO=/mnt/data/hf/hub/models--ubergarm--Qwen3.5-397B-A17B-GGUF
MODEL=/models/snapshots/.../IQ4_KSS/Qwen3.5-397B-A17B-IQ4_KSS-00001-of-00006.gguf
podman run --rm -it --device nvidia.com/gpu=all \
-p 8001:8080 --shm-size 16g --cap-add=SYS_NICE \
-v "$MO":/models:ro,Z "$IMG" \
--host 0.0.0.0 --port 8080 -m "$MODEL" \
-c 262144 --threads 13 --threads-batch 26 \
--jinja --temp 0.7 --repeat-penalty 1.2 \
--min-p 0.01 --top-p 0.95 --seed 317 --top-k 40 \
-b 2048 -ub 2048 -ngl 99 \
-fa on --no-mmap -ger
262kコンテキストに設定し、仕様の入力からコード生成までを1セッションで行いました。
概念の対応と対象外の指定
冒頭にWordPressとDjangoモデルの対応表を置きました。Post/Page -> content.Post/content.Page、Category/Tag -> taxonomy.Term、Post Meta -> content.PostMeta、Revision -> content.Revisionという対応です。後半のフィールド設計でも、この対応が保たれやすくなりました。
非目標(Out of Scope)はWordPress完全互換、Gutenberg再現、multisite UI parity、完全WYSIWYGです。対象外を示すことで、構造が必要以上に複雑になるのを抑えられました。
生成結果
生成ログには次のファイルが残っています。
apps/core/models.py/models_site.py/models_setting.pyapps/content/models.py/models_page.py/models_extra.pyapps/taxonomy/models.pyapps/media/models.pyapps/comments/models.pyapps/navigation/models.pyapps/seo/models.pyconfig/settings/base.py/dev.py/prod.pyconfig/urls.py/asgi.py/wsgi.pymanage.py/requirements.txt
Djangoプロジェクトの骨格と主要appのモデル定義をまとめて出力できました。
使えたモデル定義
- 仕様追従: Post、Term、Revision、SEOEntryのような大枠はかなりそのまま使えた
- 概念マッピング: WordPress的な操作感を残しつつ、Djangoのモデル設計として整合している
- 抽象モデル: TimeStampedModel、SoftDeleteModel、PublishableModel、SluggedModelの共通基盤が自然に出力された
- SEO制約: SEOEntryにpostまたはpageのいずれかに結び付くCheckConstraintまで生成していた
修正が必要だった箇所
- フィールド欠落: slug がPost生成途中で一度消え、後から差分で復元された
- ファイル配置のぶれ: Pageを最初は
models_page.pyに分け、その後models.pyに再統合する揺れが発生 - フィールド不整合: Comment.save()が
self.author_ipを参照しているのに、最初はauthor_ipフィールドが存在しなかった - ツール失敗: ctree_check、ctree_init、filesystem_create_directoryが複数回失敗し、write_fileにフォールバック
レビューする範囲
生成中にはツール失敗、親ディレクトリ不足、モデル定義の欠落、フィールド不整合が繰り返し起きました。
骨格を早く作れる一方で、出力全体をそのまま採用はできません。使える部分と修正が必要な部分をレビューで分ける必要があります。
考察
22 tok/sを支える構成
397Bのうち、トークンごとに動くのは17Bです。IQ4_NLでメモリ帯域の負荷を1/4以下に抑え、12チャネルDDR5でエキスパートを供給し、GPUでAttentionを計算します。この分担で約22 tok/sになりました。
IQ4_NL量子化の選択
397Bを量子化せずに配置するのは、この環境では難しいためIQ4_NLを選びました。28回のランでは明らかな品質低下は見えませんでしたが、品質差を定量評価した結果ではありません。
ウォームアップの必要性
初回数回は挙動が揺れました。TG速度が安定するまで2-3回のダミーリクエストを入れる方法が有効でした。常駐運用では起動時のウォームアップに組み込む想定です。
常用時の判断
22.5 tok/sは、今回の対話用途では十分な速度でした。非同期バッチにも使えると考えています。
約15kトークンのソースコードを入力しても、TG速度は21-24 tok/sでした。長いリポジトリ入力を扱う際の参考になります。
CMS生成では初期骨格を作れました。概念マッピング、非目標、実装順序を仕様に含めることが、生成内容を揃えるうえで役立ちました。
cpu-moeだけでも動作します。2GPUでは-otによる明示的なレイヤー分散を使い、スループットを上げる構成を採りました。
起動設定と次回の記録
KVキャッシュ量子化
135k-262kコンテキストではKVキャッシュのメモリ消費が増えます。-ctk q8_0 -ctv q8_0で量子化して抑えました。品質への影響は体感では小さく、定量比較はしていません。
サンプリングパラメータ
コード生成には--temp 0.7 --repeat-penalty 1.2 --min-p 0.01 --top-p 0.95 --top-k 40を使いました。temp 1.0では出力が創造的になる一方、冗長になりやすい傾向がありました。
起動設定・仕様・レビューを分ける
次回は記録を3つに分けます。
- 推論サーバー起動テンプレート
- CMS仕様書(概念マッピング + 非目標 + 実装順序を含む)
- 生成ログとレビュー結果
概念辞書、非目標、実装順序はCMS仕様書にまとめます。生成ログとレビュー結果を分けておくと、仕様への追従と修正箇所を確認しやすくなります。
