llm-pipeline-analysis について
LLM 推論の Chrome trace を分析するツール群です。モデル設定と境界カーネルを使ってカーネルをレイヤーに分類し、パスやレイヤー種別の比較に役立つ時間集計、カーネル詳細、Perfetto の移動範囲を出力します。
主な機能
- 01レイヤー別の時間とカーネル分類
- 02コールドスタートと定常パスの区別
- 03レイヤー間のカーネル詳細と差分
- 04Perfetto 移動用の時間範囲を出力
活用シーン
- 01時間を要するレイヤー種別の特定
- 02コールドスタートと定常パスの比較
- 03詳細分析する代表レイヤーの選定
- 04Perfetto で特定レイヤーへ移動
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ bbuf/ ai-infra-auto-driven-skills --skill llm-pipeline-analysisインストール後、Claude Code で/llm-pipeline-analysisを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
scripts/layer_kernel_breakdown.pylayer_timeline_analyzer.pymodel_profiles.pyperfetto_time_mapper.py詳細
LLM パイプライン分析
概要
トレース全体のプロファイラー概要では粗すぎる場合に使用します。スクリプトは Chrome-trace JSON ファイルを読み込み、層境界のアンカーカーネルを見つけ、 カーネルをフォワードパスと層にグループ化し、Perfetto でのナビゲーションや 詳細なタイミング分析に使えるタイミングテーブルを出力します。
使用する場面
- どの層が最も大きな割合を占めるかを知る必要がある場合
- モデルに交互に現れる層タイプがある場合(例:DeepSeek-V4 のように
compress_ratiosを持つモデル、または Qwen3.8-27B のようなハイブリッド GDN/GQA スタック) - コールドスタートと定常状態のフォワードパスを比較する必要がある場合
- Perfetto UI で特定の層に移動する必要がある場合
- 詳細分析の対象となる代表的な層を選ぶ必要がある場合
アーティファクトから入力を確認する
モデル設定、フェーズ、ランク/デバイス、TP/EP/DP を、実行マニフェスト、
サーバー引数、トレースから特定します。分析内容を変える不足情報のみを確認します。
TP-0 はランクを示すもので、TP のワールドサイズではありません。不明な実行を
TP8/EP8 やデコード BS1 とみなさないでください。投機的リクエストの BS と
ターゲット検証の M は異なります。設定がない場合は、明示的なプロファイルと
検証済みの層数を使用します。
モデルプロファイル
スクリプトは ModelProfile を使って、層境界の検出とカーネルの分類を行います。
プロファイルは config.json から自動推定するか、--profile で選択します。
| プロファイル | アンカーカーネル | ブロック数/層 | 自動推定条件 |
|---|---|---|---|
dsv4_csa_hca | mhc_pre_big_fuse | 2 | DeepSeek-V4、または圧縮へのフォールバック |
dsv41 | 明示的に検証されたアンカー | 1(サブレイヤー用に上書き) | V4.1 のテキスト/ラッパーの識別情報、または KV ソース層 |
dsv3_mla | 明示的なバックエンドアンカー、または残差境界 | バックエンドに依存 | 識別情報に基づくディスパッチ後の均質な MLA |
mla_dsa | 検証済みの残差境界 | 2 | GLM-5/5.2/5.3、V3.2、DSA MLA |
kimi_k3 | 明示的な attn_res_fused(SGLang)/attn_res_fwd_online_v2_kernel(vLLM) | 2 + 出力集約/パス 1 回 | K3/注意機構の残差を持つ Kimi linear |
glm5_next | mhc_pre_big_fuse | 2 | GLM-5.3-Flash |
hy_v4 | Triton フォールバックでの明示的な ihc_pre_stage2(hpc シンボルはトレース確認が必要) | 2 | Hy4 |
qwen4_exp | 明示的な grouped_gemma_rmsnorm | 2 | Qwen3.8-Flash-Next(vLLM では norm が融合される場合があります) |
nemotron_h | 明示的な残差 norm | 1 | 設定上、1 つの Mamba/注意機構/MoE ブロックが各層に対応 |
longcat_flash | 明示的な残差境界 | 4 | LongCat-Flash アーキテクチャ |
gemma4 | 明示的な _gemma_qkv_rmsnorm_kernel(SGLang CUDA) | 1 | Gemma4 のテキスト/ラッパーの識別情報 |
generic_addnorm | 検証済みの fused-add RMSNorm または allreduce 融合 | 2 | その他の設定済みモデル |
generic | 明示的なアンカー。残差候補のみ | 1、残差候補の場合は 2 | 設定がない場合のフォールバック |
推定前に、ネストされた text_config、language_config、llm_config をフラット化します。
モデルの識別情報は kv_lora_rank より優先されます。K3、GLM-5 Next、
Hy4、dots3、LongCat を均質な V3 MLA として扱ってはいけません。
層数は設定から読み取ります。V4 Flash は 43 層、Pro は 61 層、V4.1 は 40 層です。
これらのアンカーファミリーは、バックエンドとフェーズに関する注意事項を含め、
SGLang/vLLM のソースで検証済みです。TensorRT-LLM/TokenSpeed の周期性については、
別途トレースによる根拠が必要です。
前提条件
- Chrome-trace JSON 形式(
.jsonまたは.json.gz)のtorch.profilerトレース - モデルの
config.json(プロファイル推定、compress_ratiosなどに使用) - トレースに、認識可能な層境界アンカーカーネルが含まれていること
(プロファイルから自動検出するか、
--anchor-kernelで指定します)
レイヤー境界の検出
スクリプトでは、アンカーとなるカーネルをレイヤー境界マーカーとして使用します。アンカーとレイヤー構造は、アクティブな ModelProfile によって決まります。
まず、ステージ境界におけるモデルの残差の種類を確認します。SGLang では、python/sglang/srt/layers/layer_boundary/factories.py を通じて、attention/FFN の境界(add-norm、gated、iHC、mHC、post-norm、stream)が定義されています。バックエンドのディスパッチによって、実際に見える境界カーネルが決まります。
V4 では現在、各ハーフの開始位置が mhc_pre_big_fuse* です。attention-pre と FFN-pre の順で、レイヤーあたり 2 つのアンカーがあります。post+pre の融合により、SGLang のトークン数が少ないトレースでは mhc_post_tilelang がなくなります。この古いアンカーは、未融合であることが確認済みのトレース、または 32 トークンを超えるパスに限って使用してください。V4.1 では前のサブレイヤーの pre-mix を使用し、レイヤー間のこの融合パスを無効にするため、常に明示的なアンカーの証拠が必要です。FlashMLA の flash_fwd_mla_combine はバックエンドと分割数に依存します。SM100 の SGLang V3 では、デフォルトで TRT-LLM MLA が使用されますが、DSA モデルでは DSA が使用されます。
すべてのスクリプトで、--blocks-per-layer K --anchor-offset I --pid PID --device D を指定できます。I は選択した GPU で検証済みの最初のレイヤーアンカーであり、カウントから推定した値ではありません。ランクやデバイスが混在する場合や、カウントを N*K で割った余りがある場合は拒否されます。カウントが割り切れることは必要条件ですが、十分条件ではありません。対象/ドラフトの各フェーズ、MTP/DSPARK のパス、TBO のマイクロバッチをあらかじめ分離してください。K3 の追加の出力集約については、これらのタイミング解析スクリプトでフェーズを絞り込んだトレースが必要です。レイヤー追跡ヘルパーでは、追加アンカーを明示的にサポートしています。選択した最後のパスは、選択した GPU イベントの境界で終了します。この境界自体が、完全なパスの終端であることを確認する必要があります。アンカーは移動の目安となる区間であり、別ストリームのカーネルがその区間と重なることがあります。
コンパイル済みの vLLM トレースでは、ノームが Inductor カーネルに変換される場合があります。明示的なノームのカスタムオペレーションまたは eager 実行を使用して短いマッピング用トレースを取得し、実際に測定したトレース上で attention/バックエンドのアンカーを確認してください。
ソース監査 2026-10-05:SGLang V4 ディスパッチ、 mHC カーネル、 vLLM mHC ディスパッチ。
スクリプト
1. layer_timeline_analyzer.py — レイヤーごとのタイムラインとクラスター統計
# Show all forward passes summary (cold-start vs steady-state)
python3 scripts/layer_timeline_analyzer.py \
--trace /path/to/TP-0.trace.json.gz \
--config /path/to/config.json \
--show-all-passes
# Detailed per-layer breakdown for a specific forward pass
python3 scripts/layer_timeline_analyzer.py \
--trace /path/to/TP-0.trace.json.gz \
--config /path/to/config.json \
--fwd-pass 5
# Auto-select the first relatively stable pass window
python3 scripts/layer_timeline_analyzer.py \
--trace /path/to/TP-0.trace.json.gz \
--config /path/to/config.json
スクリプトの出力:
- レイヤーごとの実時間、合計時間、カテゴリ別の内訳(MLA、MoE、GEMM、NCCL、MHC、Hadamard)
- 種類別(CSA_C4、HCA_C128、HASH など)にグループ化したレイヤークラスターの統計
- コールドスタートから定常状態への推移を示す全パスの概要
定常状態の自動選択では、レイヤー 0 のタイミング変化が 5% 以内に収まる状態が 2 レイヤー連続することを条件とします。絶対レイテンシのしきい値は使用しないため、同じルールを異なるモデルサイズやアクセラレーターに適用できます。安定したウィンドウが見つからない場合は、--fwd-pass を明示的に選択してください。
2. layer_kernel_breakdown.py — レイヤーごとのカーネル詳細と計算フロー
# Single layer kernel dump
python3 scripts/layer_kernel_breakdown.py \
--trace /path/to/TP-0.trace.json.gz \
--config /path/to/config.json \
--fwd-pass 5 --layer 3
# Compute flow format (with model architecture summary and category column)
python3 scripts/layer_kernel_breakdown.py \
--trace /path/to/TP-0.trace.json.gz \
--config /path/to/config.json \
--fwd-pass 5 --layer 3 --format compute-flow
# JSON export
python3 scripts/layer_kernel_breakdown.py \
--trace /path/to/TP-0.trace.json.gz \
--config /path/to/config.json \
--fwd-pass 5 --layer 3 --format json
# Compare two layers side-by-side
python3 scripts/layer_kernel_breakdown.py \
--trace /path/to/TP-0.trace.json.gz \
--config /path/to/config.json \
--fwd-pass 5 --layer 2 --compare-layer 3
出力形式:
--format text(デフォルト):グループ化した概要と、簡略名および割合を含む、所要時間順の上位ホットカーネル--format compute-flow:モデルアーキテクチャの概要と、Category、%、ts_rel(ms)の各列を含むカーネルごとのホット度テーブル--format json:所要時間順の、機械可読な単一の JSON ドキュメント。--compare-layerを指定すると、primary、comparison、kernel_diffが含まれます- 2 つのレイヤーを比較する場合のカーネル差分(それぞれのレイヤーに固有のカーネル)
3. perfetto_time_mapper.py — Perfetto UI の時間ナビゲーション
# Show all forward pass time ranges in Perfetto
python3 scripts/perfetto_time_mapper.py \
--trace /path/to/TP-0.trace.json.gz \
--config /path/to/config.json
# Layer-level time ranges for a specific forward pass
python3 scripts/perfetto_time_mapper.py \
--trace /path/to/TP-0.trace.json.gz \
--config /path/to/config.json \
--fwd-pass 5 --layers 2,3,38,42
スクリプトの出力:
- Perfetto 相対秒単位のフォワードパスの時間範囲
- compress_ratio ラベル付きのレイヤーごとの開始/終了時刻
ワークフロー
ステップ 1:定常状態のフォワードパスを特定する
python3 scripts/layer_timeline_analyzer.py \
--trace $TRACE --config $CONFIG --show-all-passes
「all-passes」テーブルを確認します。最初のパスはコールドスタートです(トークン数が少ない状態)。 スクリプトで選択された最初の相対安定性ウィンドウを使用するか、計測時間が変化し続ける場合は パスを明示的に選択します。
ステップ 2:定常状態のパスにおけるレイヤーごとの内訳
python3 scripts/layer_timeline_analyzer.py \
--trace $TRACE --config $CONFIG --fwd-pass 5
以下を特定します。
- どのレイヤータイプが支配的か(CSA_C4、HCA_C128、HASH のいずれか)
- レイヤータイプごとの MLA/MoE/GEMM/NCCL の割合
- 次の最適化対象として最適なレイヤータイプ
ステップ 3:代表的なレイヤーの計算フロー
ボトルネックの種類ごとに 1 つずつ、代表的なレイヤーを 1〜2 個選択してから、次を実行します。
# Human-readable compute flow table
python3 scripts/layer_kernel_breakdown.py \
--trace $TRACE --config $CONFIG \
--fwd-pass 5 --layer 3 --format compute-flow
# JSON export
python3 scripts/layer_kernel_breakdown.py \
--trace $TRACE --config $CONFIG \
--fwd-pass 5 --layer 3 --format json > /tmp/layer3_detail.json
--format compute-flow の出力には、以下が含まれます。
- 上部のモデルアーキテクチャの概要
- カーネルのホット度をレイヤーごとに示すテーブル(
# | Half | Category | Simplified Name | dur(us) | % | ts_rel(ms) | Input Dims) - デフォルトでは、行は
dur(us)の降順に並びます。ts_rel(ms)を使うと、カーネルのトレース位置に移動できます。
ステップ 4:レイヤータイプを比較する(任意)
python3 scripts/layer_kernel_breakdown.py \
--trace $TRACE --config $CONFIG \
--fwd-pass 5 --layer 2 --compare-layer 3
2 つのレイヤータイプ間のカーネルの正確な違いが表示されます。
ステップ 5:Perfetto UI で移動する(任意)
python3 scripts/perfetto_time_mapper.py \
--trace $TRACE --config $CONFIG \
--fwd-pass 5 --layers 2,3,38,42
出力された時間範囲を使って、Perfetto 内の該当箇所に直接移動します。
レイヤータイプの分類
スクリプトは config.json のフィールドに基づいてレイヤーを分類します。
| 設定フィールド | 値 | レイヤータイプ | 説明 |
|---|---|---|---|
compress_ratios[i] | 0 | SWA_ONLY | ウィンドウのみのアテンション。コンプレッサー/インデクサーなし |
compress_ratios[i] | 4 | CSA_C4 | コンプレッサー + Lightning インデクサー(Hadamard/paged-MQA/top-k)+ スパースアテンション |
compress_ratios[i] | 128 | HCA_C128 | コンプレッサー + すべての圧縮済み行とウィンドウ。インデクサーなし |
compress_ratios[i] | 2 / 1 | V41_C2 / V41_C1 | ソースレイヤーのコンプレッサー/インデクサー。他のレイヤーは KV/インデックスを共有 |
i < num_hash_layers | — | +HASH | 最初の N レイヤーにおけるハッシュルーティング。FIRST/FINAL と組み合わせ可能 |
i == 0 / N-1 | — | +FIRST / +FINAL | 位置フラグ。アテンション/ルーティング処理を置き換えることはありません |
V4 Flash/Pro は L0〜2 をハッシュルーティングします。V4.1 にはハッシュレイヤーがありません。KV ソースレイヤーは
[2,8,14,20]、インデックスソースは [2,8,14,20,24,28,32,36]、候補ソースは
20、Engram レイヤーは [1,14] です。代表レイヤーを選ぶ際は、これらの役割フィールドを使います。
Pro は ratio-128 のレイヤーから始まるため、最初の 2 つが SWA だと仮定しないでください。
K3 の KDA レイヤー ID は 1 始まりですが、GLM-5 Next は 0 始まりの KDA ID を使用します。
カーネルカテゴリ
カーネルは、アクティブな ModelProfile のルールに基づいて分類されます。(DSv4)と記されたカテゴリは
dsv4_csa_hca プロファイルに固有です。すべてのプロファイルには、共通カテゴリが含まれます。
| カテゴリ | マッチパターン | プロファイル | 典型的な割合(DSv4) |
|---|---|---|---|
| ★ MLA アテンション | flash_fwd_splitkv_mla | DSv4, DSv3 | 21-33% |
| ★ MoE 融合 | fused_moe_kernel | DSv4, DSv3 | 11-17% |
| ● NCCL AllReduce | 大文字と小文字を区別しない allreduce、all_reduce、cross_device_reduce、reduce_scatter、NCCL/Lamport | universal | 5-8% |
| GEMM fp8 | deep_gemm | universal | 12-25% |
| GEMM bf16 | nvjet | universal | 11-13% |
| Hadamard Xform | hadamard | DSv4 | 0-2.4% |
| インデクサーキャッシュ | indexer | DSv4 | 0-0.1% |
| Paged MQA | paged_mqa_logits | DSv4 | 0-1.8% |
| MHC | mhc_pre_gemm_sqrsum、mhc_pre_big_fuse、mhc_post_tilelang | DSv4 | 10-15% |
| C4/C128 プリフィル | c4_prefill、c128_prefill | DSv4 | 0-0.3% |
| RMSNorm | 大文字と小文字を区別しない rms_?norm、layernorm | universal | 1-2% |
| FP8 量子化 | quant、Quant | universal | 1-2% |
| TopK | topk | universal | 0-0.7% |
| RoPE | deepseek_rope、fused_norm_rope | DSv4, DSv3 | 1-2% |
| アクティベーション | silu_mul_clamp、act_and_mul | universal | 0-0.5% |
| その他 | — | universal | 2-5% |
報告チェックリスト
以下を含めてください。
- トレースのメタデータ:トレースのパス、モデル設定のパス、GPU の種類、TP/EP
- モデルアーキテクチャの概要(
config.jsonより):- モデル名、num_layers、hidden_size、num_attention_heads、num_key_value_heads、head_dim
- アテンションの種類(例:csa_hca)、Q/O LoRA のランク
- MoE の設定:num_experts、topk、num_shared_experts、intermediate_size
- MHC の設定(該当する場合)
- NSA の設定(該当する場合):index_n_heads、index_head_dim、index_topk、qk_rope_head_dim、sliding_window
- compress_ratios の分布(CSA_C4 / HCA_C128 / SWA_ONLY / HASH レイヤーの数)
- バッチごとのフォワードパスの概要表(
layer_timeline_analyzer.py --show-all-passesより):- 列:Fwd#、Start(s)、End(s)、Duration(ms)、Avg Layer(ms)、First Layer(ms)、Notes
- コールドスタートと定常状態のパスを特定します
- 選択したフォワードパス:インデックスと選択理由(コールドスタートか定常状態か)
- レイヤーごとの実時間と合計所要時間の表(
layer_timeline_analyzer.py --fwd-pass Nより):- 列:L、c_r、Type、Wall(ms)、SumDur(ms)、MLA、MoE、GEMM、NCCL、MHC、Hadam、AR#、K#
- 各行は 1 つのレイヤーを表し、レイヤーの種類を示すラベルを付けます
- レイヤークラスターの統計表(種類ごとにグループ化):
- 列:Cluster、#、Avg Wall(ms)、Avg Sum(ms)、MLA%、MoE%、GEMM%、NCCL%、MHC%、Hadam%
- ボトルネックとなるレイヤーの種類と、次に調査すべき対象を特定します
- 選択した代表的なレイヤーの計算フロー表:
layer_kernel_breakdown.py --format compute-flowによって生成されます- 列:
# | Half | Category | Simplified Name | dur(us) | % | ts_rel(ms) | Input Dims - デフォルトでは、上位のホットカーネル(
dur(us)の降順)に従って行を並べます - JSON へのエクスポートも可能です(
--format json)
- 要求された場合は Perfetto UI の時間範囲
- 1 行の要約:ボトルネックとなるレイヤーの種類と、次に調査すべき対象