pt2-bug-basher について
Dynamo、Inductor、AOTAutograd、FX グラフに関する PyTorch 2 のコンパイル障害を調べるデバッグスキルです。環境確認から再現の最小化、テスト作成、原因分析、修正の検証までを案内します。
主な機能
- 01conda 環境と PyTorch の読み込み確認
- 02障害の再現と最小化
- 03コード調査前の回帰テスト追加
- 04エラー分類とコンパイル成果物の収集
- 05根本原因の分析とテスト検証
活用シーン
- 01torch.compile のグラフ中断の調査
- 02Inductor 障害の最小再現化
- 03コンパイルモデルの数値不一致の診断
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ pytorch/ pytorch --skill pt2-bug-basherインストール後、Claude Code で/pt2-bug-basherを入力して読み込まれたか確認します。
詳細
PT2 バグ退治
PyTorch 2 コンパイラースタック(Dynamo、Inductor、AOTAutograd、FX グラフ)のテスト失敗や実行時エラーをデバッグします。
ワークフローの概要
- 環境を確認する -- 使用する conda 環境をユーザーに尋ねます。
$CONDA_DEFAULT_ENVを確認して、環境が有効になっていることを確かめます。続いてpython -c "import torch; print(torch.__version__)"を実行し、torch をインポートできることを確認してバージョンを報告します。環境が有効になっていない場合、または torch をインポートできない場合は、そこで中断し、続行する前に正しい環境を有効にするようユーザーに依頼します。 - 再現する -- 一貫して失敗を再現できる状態にします。
- 最小化する -- 再現コードを、単独で実行できる最小限のケースまで縮小します。無関係なモデルのロジックを取り除き、最小限のテンソル形状を使い、バグを引き起こす特定の演算またはパターンを切り分けます。
- 単体テストを追加する -- コード検索や根本原因の調査に着手する前に行ってください。 バグを再現する失敗テストをコードベースに追加します。
test/dynamo/test_repros.py、test/inductor/test_torchinductor.py、test/export/test_export.pyなど、問題の内容に適した具体的なテストファイルに配置します。すでに大きくなりすぎているtest/dynamo/test_misc.pyは避けてください。バグの領域に合った、より具体的なテストファイルを探します。torch.testing._internal.common_utils.TestCaseとrun_testsを使用します。テストは修正前に失敗し、修正後に成功する必要があります。最初にテストを用意すると、何をもって「修正済み」とするのかが明確になり、コードベースを調べる際の指針になります。 - main で検証する --
EnterWorktreeを使って、mainをチェックアウトしたワークツリーを作成します。新しいテストファイルをワークツリーにコピーし、そこでテストを実行して、main で失敗することを確認します。main でテストが成功する場合は中断します。テストが適切なバグを捉えていないか、バグがすでに修正されている可能性があります。ExitWorktree(action: remove)でワークツリーを終了し、続行する前に作業ブランチへ戻ります。 - ログを収集する -- 適切な
TORCH_LOGSの設定で実行します。 - 分類する -- エラーのトリアージテーブルを使ってカテゴリを特定します。
- 生成物を調べる --
TORCH_COMPILE_DEBUG=1を使って FX グラフ、IR、生成コードを確認します。 - 根本原因を特定する -- エラーからコンパイルパイプラインをたどって原因を突き止めます。
- 修正する -- 修正を適用します。
- 検証する -- 新しい単体テストに加え、近接する関連既存テストも実行します(例:
is_exportingの動作を変更した場合は、既存のtest_is_exportingエクスポートテストも実行します)。pytest -kを使うと、名前で関連テストをすばやく実行できます。すべて成功するまで、タスクは完了ではありません。 - セルフレビューする -- 変更を提示する前に、
/pr-reviewスキルを使って自分の変更をレビューします。指摘された問題は修正します。 - 完了を祝う -- 変更内容を要約します。根本原因、変更した内容とその理由、追加・検証したテストを説明します。その後、ユーザーにバグを退治したことを伝えます。士気を高める、楽しくバリエーションのあるメッセージやイースターエッグ(しゃれ、引用、退治されたバグの ASCII アートなど)を添えます。毎回短く、違うものにしてください。
調査方針
meta_codesearch より直接ツールを優先する
コードを調べる際は Grep、Glob、Read を直接使用します。meta_codesearch エージェントは起動しないでください。時間がかかり、コストも高いためです。以下のアーキテクチャに関する知識と主要なソースファイルのセクションを参考にすれば、調べる場所は十分に分かるはずです。関数名を指定した Grep のほうが、常にすばやく見つけられます。
使用しているコンパイルモードを確認する
実装コードを読む前に、コンパイルモードを特定してください。コードの一部は共通していますが、重要な違いがあります。
torch.compile-- Dynamo と Inductor を使用します。tx.export=Falseで、_compiling_state_context()はありません。torch.export(strict) --tx.export=Trueで、_compiling_state_context()が有効です。torch.export(non-strict、デフォルト) --fullgraph_captureを介して Dynamo を使用しますが、tx.exportは strict の場合と異なることがあります。_compiling_state_context()が有効です。torch._export.config.use_new_tracer_experimentalを確認してください。この設定によって、使用されるコードパスが変わります。
トレース時とランタイム時を区別する
PT2 のバグの多くは、この2つを混同することで発生します。
- トレース時:Dynamo のシンボリックインタープリター内です。Dynamo は関数呼び出しをインターセプトし、定数畳み込みを行うことがあります(例:
is_exporting()→ConstantVariable(True))。 - ランタイム時:実際のテンソル、実際の Python 呼び出し、
torch.compiler._is_exporting_flagのようなモジュールレベルのフラグが対象です。
デバッグ時は、外部からモンキーパッチを適用するのではなく、ソースファイルに一時的な print() 文を直接追加してください。ディスパッチの連鎖により、モンキーパッチは信頼性に欠けるためです。
情報の収集
エラーの種類に応じて、適切な診断ツールを選択してください。
- 概要をすばやく確認:
TORCH_LOGS="+dynamo,graph_breaks,recompiles" python your_script.py - デバッグ情報一式:
TORCH_COMPILE_DEBUG=1 python your_script.py— FX グラフ、Inductor IR、生成されたコードを含むtorch_compile_debug/が作成されます - 生成コードのみ:
TORCH_LOGS="output_code" python your_script.py - 構造化トレース:
TORCH_TRACE=/path/to/trace python your_script.pyを実行し、その後tlparse /path/to/trace - シングルスレッド(pdb 用):
TORCHINDUCTOR_COMPILE_THREADS=1 python your_script.py
エラーのトリアージ
エラーメッセージとトレースバックを使って、失敗を分類してください。
| エラーパターン | カテゴリ | 移動先 |
|---|---|---|
Unsupported: ... またはログ内の graph break | グラフブレーク | グラフブレーク |
BackendCompilerFailed | Inductor/バックエンドのクラッシュ | バックエンドコンパイラーの失敗 |
RecompileError または cache_size_limit | 再コンパイル | 再コンパイル |
| 精度の不一致/数値出力の誤り | 精度 | 精度の問題 |
InternalTorchDynamoError | Dynamo のバグ | 内部エラー |
| セグメンテーションフォールトまたは CUDA IMA | ランタイムクラッシュ | ランタイムクラッシュ |
| Triton のアサーション/インデックスが範囲外 | Triton カーネルのバグ | Triton の失敗 |
カテゴリ別のデバッグ
グラフブレーク
グラフブレークによってコンパイル済みグラフが小さなサブグラフに分割され、パフォーマンスの低下や予期しない動作が発生することがあります。
診断:
TORCH_LOGS="graph_breaks" python your_script.py
主なファイル:
torch/_dynamo/exc.py--Unsupported例外クラスtorch/_dynamo/variables/-- グラフブレークの判断の大半が行われる場所
一般的な原因:
- サポートされていない Python の構文(データ依存の制御フロー、サポートされていない組み込み関数)
- トレースできないテンソル演算(入力に対するインプレース演算、サポートされていないデータ型)
- トレースできない関数の呼び出し
修正方法:
- グラフブレークのメッセージを読んで、サポートされていない演算を特定します
- 分解方法またはサポートされている代替手段があるか確認します
- その演算を実際にトレースできない場合は、
torch._dynamo.allow_in_graphの使用、またはユーザーコードの構成変更を検討します
バックエンドコンパイラの失敗
BackendCompilerFailed は、Inductor(または別のバックエンド)がコンパイル中にクラッシュしたことを意味します。
診断:
TORCHDYNAMO_REPRO_AFTER=aot TORCHDYNAMO_REPRO_LEVEL=2 python your_script.py
これは minifier_launcher.py を生成し、最小限の失敗グラフを切り分けます。
主要なファイル:
torch/_dynamo/repro/after_aot.py-- AOT 後の失敗に対する repro/minifiertorch/_inductor/-- バックエンド本体
修正アプローチ:
- minifier を実行して最小限の再現を取得する
- FX グラフ(
TORCH_COMPILE_DEBUG=1)を調査して、どの ops が関与しているかを理解する - それが lowering の問題(
torch/_inductor/lowering.py)、スケジューリングの問題、コード生成の問題のいずれであるかを確認する - エラーがコード生成にある場合は、生成された出力コードを確認する
再コンパイルの問題
過剰な再コンパイルは、ガードが具体的すぎてキャッシュミスが発生するときに起こります。
診断:
TORCH_LOGS="recompiles,recompiles_verbose,guards" python your_script.py
主要な設定:
torch._dynamo.config.recompile_limit(デフォルト: 8)torch._dynamo.config.fail_on_recompile_limit_hit--Trueに設定するとハードエラーになります
よくある原因:
- テンソルの形状を dynamic としてマークせずに変更している
- 呼び出し間で変化する Python のスカラー値
- 呼び出し間でのグローバル状態の変更
修正アプローチ:
- ログから再コンパイルの理由を読み取る
- 失敗しているガードを特定する
torch._dynamo.mark_dynamic()で該当する次元を dynamic としてマークするか、ガードの不安定さの原因を修正する
精度の問題
コンパイルされたモデルが、eager モードとは異なる数値結果を生成します。
診断:
TORCHDYNAMO_REPRO_AFTER=aot TORCHDYNAMO_REPRO_LEVEL=4 python your_script.py
これは fp64 リファレンスを用いてコンパイル済みと eager を比較し、精度が失敗した場合に再現をダンプします。
主要なユーティリティ:
torch/_dynamo/debug_utils.py--same_two_models()、backend_accuracy_fails()、cast_to_fp64()torch._dynamo.config.repro_tolerance(デフォルト: 1e-3)
修正アプローチ:
- minifier から最小限の失敗グラフを取得する
- fp64 精度で eager とコンパイル済みの出力を比較する
- ops を二分探索して、分岐している操作を見つける
- 既知の数値の問題(リダクションの順序、融合カーネル、dtype の昇格)を確認する
Dynamo の内部エラー
InternalTorchDynamoError は、Dynamo 自体のバグを示します。
診断:
TORCHDYNAMO_VERBOSE=1 python your_script.py
# or equivalently:
TORCH_LOGS="+dynamo" python your_script.py
主要なファイル:
torch/_dynamo/symbolic_convert.py-- バイトコードインタプリタtorch/_dynamo/variables/-- 変数追跡システムtorch/_dynamo/guards.py-- ガードの生成
修正アプローチ:
TORCHDYNAMO_VERBOSE=1で完全なスタックトレースを取得する- どのバイトコード命令または変数型がクラッシュを引き起こしたかを特定する
- 最小限の再現を作成する(エラーメッセージには minifier のパスが含まれていることが多い)
- 必要に応じて
TORCHINDUCTOR_COMPILE_THREADS=1と pdb でデバッグする
実行時のクラッシュ
コンパイルされたコードの実行中に発生するセグメンテーションフォールトや CUDA の不正メモリアクセスエラー。
診断(クラッシュを決定論的にする):
PYTORCH_NO_CUDA_MEMORY_CACHING=1 CUDA_LAUNCH_BLOCKING=1 python your_script.py
CUDA IMA の場合は、NaN チェックを追加する:
TORCHINDUCTOR_NAN_ASSERTS=1 python your_script.py
Inductor レベルの同期デバッグの場合:
torch._inductor.config.triton.debug_sync_kernel = True # sync after every kernel
torch._inductor.config.triton.debug_sync_graph = True # sync before/after graph
修正アプローチ:
PYTORCH_NO_CUDA_MEMORY_CACHING=1 CUDA_LAUNCH_BLOCKING=1でクラッシュを決定論的にする- 入力の不一致(形状、デバイス、dtype)かどうかを確認する
TORCH_LOGS="output_code"で生成されたカーネルコードを調査するTORCHINDUCTOR_NAN_ASSERTS=1を使用して、不正な値を生成している最初のカーネルを見つける- dynamic shapes の問題を確認する(歴史的に IMA のよくある原因)
Triton カーネルの失敗
Triton のアサーション失敗、または生成されたカーネルにおけるインデックスの範囲外アクセス。
診断:
TORCH_LOGS="output_code,schedule" python your_script.py
主要なファイル:
torch/_inductor/codegen/triton.py-- Triton のコード生成torch/_inductor/scheduler.py-- カーネル融合の決定
修正アプローチ:
output_codeログから生成された Triton カーネルを取得する- インデックス計算に off-by-one や誤ったストライド計算がないか確認する
- IR(
TORCH_COMPILE_DEBUG=1)を見て FX op まで遡って追跡する - 融合の決定が無効なインデックスの組み合わせを生み出していないか確認する
主要なソースファイル
| ファイル | 用途 |
|---|---|
torch/_dynamo/exc.py | 例外階層とエラーの書式設定 |
torch/_dynamo/debug_utils.py | ミニマイザーのサポート、精度チェック、入力のシリアライズ |
torch/_dynamo/repro/after_dynamo.py | Dynamo 段階の失敗に対する再現/ミニマイザー |
torch/_dynamo/repro/after_aot.py | AOTAutograd 後の失敗に対する再現/ミニマイザー |
torch/_dynamo/repro/aoti.py | AOTI の失敗に対する再現/ミニマイザー |
torch/_dynamo/config.py | Dynamo の設定(再現レベル、再コンパイルの上限) |
torch/_dynamo/variables/torch.py | Torch 関数の処理、トレース状態関数 |
torch/_dynamo/variables/higher_order_ops.py | HOP のトレース(cond、map など) |
torch/_dynamo/symbolic_convert.py | バイトコードインタープリター、InstructionTranslator |
torch/_dynamo/convert_frame.py | フレームのコンパイル、fullgraph_capture のエントリーポイント |
torch/_dynamo/functional_export.py | 新しいエクスポート用トレーサー(_dynamo_graph_capture_for_export) |
torch/_dynamo/eval_frame.py | torch._dynamo.export、optimize_assert |
torch/_export/_trace.py | エクスポートパイプライン(_export、_strict_export、_non_strict_export、_export_to_aten_ir) |
torch/_export/utils.py | _compiling_state_context() |
torch/compiler/__init__.py | is_compiling()、is_exporting()、ランタイムフラグ |
torch/_higher_order_ops/cond.py | torch.cond の実装とプロキシトレース |
torch/_higher_order_ops/utils.py | HOP 分岐のトレース用 reenter_make_fx |
torch/_inductor/config.py | Inductor の設定(デバッグフラグ、トレース設定) |
torch/_inductor/debug.py | DebugContext、グラフの可視化、IR ロギング |
torch/_logging/_registrations.py | 登録済みのすべてのログエイリアスとアーティファクト |
ミニマイザーの使用
ミニマイザーは、失敗するグラフを最小の再現例に縮小します。
# Step 1: Generate the minifier launcher
TORCHDYNAMO_REPRO_AFTER=aot TORCHDYNAMO_REPRO_LEVEL=2 python your_script.py
# Step 2: Run the minifier
python minifier_launcher.py minify
# Step 3: Run the minimized repro
python minifier_launcher.py run
精度の問題には、レベル 4 を使用します。
TORCHDYNAMO_REPRO_AFTER=aot TORCHDYNAMO_REPRO_LEVEL=4 python your_script.py