mcpField
L
llm-serving-capacity-planner

llm-serving-capacity-planner

github.com/bbufクラウド・DevOps1.1k58 回インストール今日更新
リポジトリ

llm-serving-capacity-planner について

SGLang と vLLM の運用担当者向けに、サービング容量の計画や診断を支援するログ分析ツールです。ログの GPU メモリ使用量を分類し、指定したトークン長での同時リクエスト数を推定します。オプションでランク別の値やモデル設定も確認できます。

主な機能

  1. 01起動ログからメモリ値を抽出
  2. 02重み、KV、グラフ、オーバーヘッドを分類
  3. 03ランク別の nvidia-smi 値を比較
  4. 04リクエストのトークン長ごとに同時数を推定
  5. 05JSON レポートに対応

活用シーン

  1. 01GPU 構成でのリクエスト容量の推定
  2. 02メモリ関連の OOM 障害の調査
  3. 03設定変更による KV 容量の比較
  4. 04GPU 値とログ上のメモリ値の照合

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/bbuf/ai-infra-auto-driven-skills --skill llm-serving-capacity-planner

インストール後、Claude Code で/llm-serving-capacity-plannerを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
gpu-specs.json
log-patterns.md
scripts/
capacity_analyzer.py

詳細

LLM サービング容量プランナー

概要

サービングログに、GPU HBM の使用状況を説明するメモリ関連の行が十分に含まれている場合に使用します。アナライザーは SGLang/vLLM の起動ログを読み取り、重みの読み込み、KV プール、CUDA グラフ、フレームワークのオーバーヘッド、トークン容量の行を抽出して、一般的なトークン長における同時リクエスト数を推定します。

DeepSeek-V4.1 の場合、推定に 528 B/288 B を使用する前に、 KV レイアウトとページ割り当ての仕様 を確認してください。これらは保存されるトークンごとのペイロードとスケールの値であり、ページパディング後の割り当て量や、モデル全体の KV バイト数ではありません。ピン留めされたソースとログから、実際のプールレイアウト、圧縮率、共有状況を確認してください。

入力

分析を実行する前に、次の入力を収集または確認してください。

項目重要な理由入手方法ユーザーが指定しない場合のデフォルト
ログファイルのパス主な入力です。すべてのメモリデータはここから取得しますユーザーにサービング起動ログを尋ねます—(必須)
GPU の種類内訳検証に使用する HBM 合計量を特定しますユーザーに尋ねるか、ログから推定します可能な場合はログから自動検出
nvidia-smi の出力クロスチェック用に、ランクごとの実メモリを提供しますnvidia-smi --query-gpu=index,memory.used,memory.free --format=csv,noheader > smi.txt を実行して取得します—(任意ですが、推奨)
モデルの config.json理論上の KV キャッシュのバイト数計算と複製係数の分析が可能になりますユーザーにモデルの config.json のパスを尋ねます—(任意。指定がない場合はログデータを使用)
リクエストのトークン長同時実行数推定の分母を決定しますユーザーに尋ねます4096、6144、8192

ワークフロー

ステップ 1:サービングログを収集する

ユーザーから、SGLang または vLLM サービングインスタンスの起動ログを提供してもらいます。アナライザーが必要とする主なログ行は次のとおりです。

  • Load weight begin. avail mem=XX GB
  • server_args={'model_path': '...', 'tp_size': 8, ...}(解決済みパラメーター)
  • Load weight end. ... avail mem=X GB, mem usage=X GB.(重みのフットプリント)
  • DSV4 memory calculation: ... bytes_per_full_token=X, available_bytes=X GB, ... full_token=N
  • [label] KV Cache is allocated. dtype: ..., #tokens: N, K size: X GB, V size: Y GB(または KV size)
  • Mamba Cache is allocated. ... conv_state size: X GB, ssm_state size: Y GB
  • Memory pool end. avail mem=XX GB
  • Capture target|draft decode|verify|prefill CUDA graph end. elapsed=X s, mem usage=X GB, avail mem=X GB.
  • Post-capture KV sizing: KV cache allocated. ... KV size: X GB, avail mem=X GB(オプトイン)
  • max_total_num_tokens=XX, ... chunked_prefill_size=-1|N, ... available_gpu_mem=XX GB

従来の ServerArgs(...)、Memory profiling:、Capture cuda graph end. も、古いログや非公開ブランチのログでは引き続き受け付けられます。これらは現在の main が出力するものではありません。

現在の vLLM V1 のログでは、代わりに次の情報が示されます。

  • Initial free memory: ...; Requested memory: ...(DEBUG のみ)
  • Model loading took ... GiB
  • Available KV cache memory: ... GiB
  • Graph capturing finished ... took ... GiB
  • <device> KV cache size: ... tokens, Maximum concurrency for ... tokens per request: ...x
  • Free memory on device (F/T GiB) ... Current kv cache memory in use is K GiB(INFO)
  • CUDA graph pool memory: A GiB (actual), E GiB (estimated), ...
  • Initial free memory X GiB, reserved Y GiB memory for KV Cache ...(明示的な KV バイト数)
  • Maximum concurrency for ... tokens per request: ...x

ログが実行中のインスタンスから取得される場合は、起動時に stdout/stderr をファイルへリダイレクトして収集してください。

ステップ 2:任意で nvidia-smi のデータを取得する

ランクごとのメモリを比較する場合:

docker exec <container> nvidia-smi --query-gpu=index,memory.used,memory.free --format=csv,noheader > smi.txt
ステップ 3:アナライザーを実行する
python3 skills/llm-serving-capacity-planner/scripts/capacity_analyzer.py \
  --log-file /path/to/sglang.log \
  --nvidia-smi-file /path/to/smi.txt \
  --gpu h200 \
  --config-json /path/to/config.json

JSON 出力の場合(自動化向け):

python3 skills/llm-serving-capacity-planner/scripts/capacity_analyzer.py \
  --log-file /path/to/sglang.log \
  --format json
ステップ 4:結果を確認して解釈する

アナライザーには、次の情報が表示されます。

  1. メモリ内訳表:各カテゴリ(重み、KV プール、CUDA グラフ、フレームワーク、その他)の GiB、MiB、割合、算出根拠
  2. ランクごとの比較:すべての TP ランクにおける nvidia-smi のデータ
  3. KV プールの詳細:プール構成、KV データ型、複製係数、トークンあたりのバイト数の計算
  4. 同時実行数の推定:トークン長ごとの最大同時リクエスト数
  5. チューニングに関する注記:容量を増やせる可能性がある設定変更

vLLM の場合、レポートには vLLM Startup Evidence セクションも含まれます。ログに存在しない値は不明のままにし、SGLang 固有のフィールドに置き換えないでください。

使用する場面

  • LLM サービングインスタンスの起動後に、GPU メモリの分配状況を把握する場合
  • 異なる --mem-fraction-static の値と、それが KV プール容量に与える影響を比較する場合
  • デプロイ容量を計画する場合:所定の GPU 構成で同時に処理できるリクエスト数を確認します
  • OOM の問題を調査する場合:最も多くのメモリを使用しているカテゴリを特定します
  • fp8 KV キャッシュや EP で同時実行数を改善できるか評価する場合

主な概念

mem-fraction-static

調査対象の SGLang ソースでは、モデル読み込み前の空きメモリからランタイム用の余裕を確保します。headroom = pre_model_load_memory * (1 - mem_fraction_static) です。KV の予算は、現在の空きメモリからこの余裕と、モデル固有のその他の予約分を差し引いて算出されます。post_weight_free * fraction ではありません。キャプチャ後にプールのサイズが更新されることもあります。最終的にログに記録された容量とランク単位の根拠を使用してください。ソースの仕様を参照してください。

デフォルト値は、ハードウェアと構成に基づいて自動的に決定されます。server_args={...} から解決済みの値を確認してください。値を下げると、KV 容量と引き換えにランタイム用の余裕が増えます。値が記載されていない場合に 0.88 と推測しないでください。

KV ヘッドの複製

標準的な GQA/MHA では、各ランクに max(1, num_key_value_heads // tp_size) 個の KV ヘッドが格納されます。TP がヘッド数を超える場合、すべてのランクにヘッド一式が複製されるのではなく、ヘッドがランクのサブグループ間で複製されます。kv_heads=4, tp=8 の場合、各ランクには 1 個のヘッドが格納されます。kv_heads=1, tp=8 の場合は、8 つすべてのランクにその 1 個のヘッドが格納されます。MLA では、代わりに潜在表現と RoPE キーが複製されます。理論計算では、構成されたすべてのレイヤーがそのランクに存在すると仮定します。パイプライン並列処理では、ランクごとのレイヤー数を使用してください。

SWA(スライディングウィンドウアテンション)圧縮

DeepSeek-V4 などのモデルは、CSA(Compressed Sliding Attention)と HCA(Hierarchical Context Attention)をスライディングウィンドウとともに使用します。これにより、完全なアテンションに基づく理論計算と比べて、トークンあたりの KV キャッシュのバイト数が減少します。ログに報告される bytes_per_full_token には、すでにこの圧縮が反映されています。

レポートのチェックリスト

次の項目を含めてください。

  1. サービング構成:モデル、GPU、TP/PP/EP、mem-fraction-static、kv-cache-dtype
  2. メモリ内訳表:カテゴリ/GiB/MiB/割合/算出根拠
  3. ランクごとの nvidia-smi 比較:TP ランクごとの使用メモリと空きメモリ
  4. KV プールの詳細:プールサイズ、bytes_per_full_token、KV データ型、複製係数、トークンあたりの理論上の KV 計算(config.json が指定されている場合)
  5. 同時実行数の推定表:リクエストのトークン長/トークン上限/リクエスト上限/最大同時実行数
  6. 空きメモリと構成に基づくチューニングに関する注記

2026-08-23 ランタイムに関する注記

SGLang v0.5.18 では、コンパイル済みカーネルのキャッシュが SGLANG_CACHE_DIR に集約されます。アップグレード後の初回起動では、Triton/FlashInfer/DeepGEMM/Inductor が一度再コンパイルされるため、「その他」のメモリが増え、起動に時間がかかることがあります。チェックポイントのステージングを重ねて行う設定(--startup-weight-load-mode overlap)によっても、起動時のメモリ推移が変わります。重みのページ読み込みと CUDA グラフのキャプチャが重なる場合があるため、重みの読み込み時間が短くても、重みのメモリ使用量が小さいとは判断しないでください。

既知の制限事項

制限事項詳細回避策
フレームワーク固有のチェックポイントSGLang と vLLM では公開されるメモリチェックポイントが異なるため、一部のフィールドは一対一で比較できません不明なフィールドは不明として報告し、共通する明示的な情報のみを比較します
SWA 圧縮モデルCSA/HCA アテンションでは、モデル設定からトークンごとの KV バイト数を個別に計算できません。フレームワーク内部の SWA ウィンドウパラメーターが必要ですログの bytes_per_full_token をそのまま使用します
DeepGEMM JIT メモリDeepGEMM JIT コンパイルメモリはログに明示的に記録されないため、アナライザーは「その他」に分類します正確に計上するには、nvidia-smi の合計値と比較します
PP(パイプライン並列処理)メモリの内訳はランクごとです。PP 構成では、ステージ間でメモリ量に偏りが生じる場合があります各 PP ステージで --target-rank を指定します
MoE エキスパートバッファーエキスパートルーティング用の追加バッファーを割り当てるフレームワークもありますが、個別には報告されません割り当てのタイミングに応じて、「モデルの重み」または「その他」に含まれます

参考資料

  • references/log-patterns.md:メモリ分析で使用するログ行のパターンとその意味。
  • references/gpu-specs.json:h20、h100、h200、b200 の各エイリアスに対応する GPU HBM 仕様。
  • scripts/capacity_analyzer.py:中核となる分析スクリプト。

メモリ容量の情報源

同梱のハードウェアテーブルには、使用可能な GiB ではなく、ベンダー公称の GB 最大値が記録されています。 nvidia-smi の使用量と空き容量、または vLLM のログに記録された合計値を優先してください。B200 には DGX の 180GB SKU が記録されています。 ほかの Blackwell SKU では異なる場合があります。DGX Spark の 128GB はシステムと共有するメモリであり、専用 HBM ではありません。L20 の公式 SKU は 48GB です。名前から l20n の容量を推定しないでください。GB200 には物理パッケージの最大容量である 192GB が記録されています。実際に導入された SKU とカスタム SKU の容量は、実測した合計値を確認する必要があります。新たに追加されたハードウェアの各エントリーには、公式情報源の URL が保存されています。

コメント