Qwen3.5-397Bの速度とコード生成

Qwen3.5-397BをEPYCとコンシューマGPUで動かし、28回の連続推論を測定しました。総パラメータは397B、活性パラメータは17BのMoEです。通常はH100複数枚を使う規模ですが、ここではIQ4_NL量子化、cpu-moe、テンソルオフロードを組み合わせています。

常用できる速度かを確認し、LLM導入時の構成判断に使います。長文脈のコード生成では、WordPressライクなDjango CMSの仕様からプロジェクト骨格を生成しました。

測定項目

  1. IQ4_NL量子化での定常TG/PP速度を28回のランから統計的に把握
  2. ハイブリッドオフロード(cpu-moe / マルチGPUテンソルオフロード)の実行構成を記録
  3. コンテキスト長依存性と安定性を評価
  4. 400B級MoEの日常運用可能性を判定
  5. 長文脈コード生成タスク(Django CMS基盤)での品質評価

実験環境

項目仕様
CPUAMD EPYC 9175F(Zen 5, 16C, L3 512MB)
メモリDDR5-6400 768GB(12ch)
GPUNVIDIA RTX PRO 6000(96GB VRAM)
OSUbuntu 24.04 LTS
Runtimeik_llama.cpp(cpu-moe有効)
量子化IQ4_NL
コンテキスト最大262,144

結果

スループット統計(28回のラン)

指標Prefill (PP)Generation (TG)
最大値372.24 tok/s24.04 tok/s
最小値101.49 tok/s19.13 tok/s
平均(定常時)約160 tok/s約22.5 tok/s

代表的なラン

#PP(tok)TG(tok)PP速度(tok/s)TG速度(tok/s)合計(s)
14,69913314.2221.9515.5
31,1252,048161.6720.81105.4
81,1242,048154.7623.8293.3
1415,8662,048372.2422.98131.7
16550520117.7822.9127.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.py
  • apps/content/models.py / models_page.py / models_extra.py
  • apps/taxonomy/models.py
  • apps/media/models.py
  • apps/comments/models.py
  • apps/navigation/models.py
  • apps/seo/models.py
  • config/settings/base.py / dev.py / prod.py
  • config/urls.py / asgi.py / wsgi.py
  • manage.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つに分けます。

  1. 推論サーバー起動テンプレート
  2. CMS仕様書(概念マッピング + 非目標 + 実装順序を含む)
  3. 生成ログとレビュー結果

概念辞書、非目標、実装順序はCMS仕様書にまとめます。生成ログとレビュー結果を分けておくと、仕様への追従と修正箇所を確認しやすくなります。