🟢 🏥 実践 公開日: · 4 分で読めます ·

PyTorchが少数のテンプレートクラスから数千のテストを生成する仕組み――テストインフラストラクチャガイド

エディトリアルイラスト:PyTorchの自動テストとCIインフラストラクチャ最適化ツール

Red HatのRiya PuniaによるPyTorchブログ記事が、CI失敗時にTestMatmulCUDA.test_basic_cuda_float32のような名前が元のTestMatmul.test_basicと異なる理由を解説している。テストはインポート時にデバイスとdtypeの組み合わせを通じて動的に生成されるためだ。

🤖

この記事はAIにより一次情報源から生成されました。

PyTorch CIがTestMatmulCUDA.test_basic_cuda_float32のような名前で失敗を報告したとき、ソースコードを見てもそのクラスが見つからないことが多い。これはバグではない――意図的な設計だ。Red HatのRiya Puniaが2026年7月3日にPyTorchブログで公開した詳細なガイドが、このシステムの背後にあるメカニズムを解明している。

インポート時のテスト生成

PyTorchのテストインフラストラクチャの核心はtorch/testing/_internal/common_device_type.pyに定義されたinstantiate_device_type_tests()関数だ。この関数はテンプレートクラス――それ自体では実行できない――を受け取り、サポートされる各デバイスの具体的なクラスを実行時に生成する。

1つのメソッドtest_basicを持つテンプレートクラスTestMatmulは3つの具体的なクラスになる:TestMatmulCPUTestMatmulCUDATestMatmulMPS。各メソッドにはすべての関連するdtypeの組み合わせのサフィックスが付く:test_basic_cuda_float32test_basic_cuda_float16test_basic_cuda_bfloat16など。サポートされるデバイスにはCPU、CUDA、MPS(Apple Silicon)、XPU(Intel)が含まれ、dtypeはfloat16、float32、float64、bfloat16をカバーする。

命名規則は一貫している:<クラス名><デバイス>.<メソッド>_<デバイス>_<dtype>。この規則の知識はCIの失敗をデバッグするために不可欠だ。

よくある落とし穴:pytestフィルターでテンプレートクラスをターゲットにすること

Puniaが挙げる最もよくある間違いは、pytest -kフィルターに元のテンプレート名を使用することだ。pytest test/test_torch.py -k "TestMatmul"というコマンドは何も見つけない。なぜならクラスTestMatmulは実行時に実行可能なものとして存在しないからだ――存在するのはTestMatmulCPUTestMatmulCUDA、その他の生成されたバリアントのみだ。正しいターゲットはpytest test/test_torch.py -k "test_basic_cuda_float32" -xだ。

OpInfo:オペレーターのメタデータレイヤー

テストインフラストラクチャの第2の柱はOpInfo――各PyTorchオペレーターのテスト方法を記述する一元化されたエントリだ。torch/testing/_internal/opinfo/core.pyに定義され、グローバルオペレーターレジストリはtorch/testing/_internal/common_methods_invocations.pyにある。

各OpInfoエントリには:オペレーター名、呼び出しバリアント、サポートされるdtype、サンプル入力ジェネレーター、数値許容誤差、特定の組み合わせのスキップ条件が含まれる。@opsデコレーターでマークされたジェネリックテストテンプレートは、登録されたすべてのオペレーターを自動的にイテレートし、各組み合わせのテストを実行する――コードの重複なしに。

結果として、少数のテンプレートテストが数千の具体的なテストケースをカバーする。Puniaはこれを膨大な数のオペレーターとハードウェアターゲットを網羅するPyTorchのテストスイートの保守性を可能にする基本メカニズムとして示している。

主要ファイルの構造

Puniaはインフラストラクチャの基盤を構成する5つの主要ファイルを挙げている:

  • torch/testing/_internal/common_utils.py ― 共通テストユーティリティ、基底TestCaseクラス、run_tests()
  • torch/testing/_internal/common_device_type.pyinstantiate_device_type_tests()@dtypes@opsデコレーター
  • torch/testing/_internal/opinfo/core.py ― OpInfoエントリの定義とメタデータ
  • torch/testing/_internal/common_methods_invocations.py ― 全オペレーターのop_dbレジストリ
  • test/run_test.py ― シャーディングサポートを持つCIスタイルのランナー

CIの失敗をデバッグするには?

PyTorch CIはDr. CIを使用している――グループ化された失敗と失敗が記録されたシャード情報を自動的にプルリクエストにコメントするツールだ。Puniaが推奨するデバッグフロー:(1) Dr. CIコメントからシャード情報を取得し、(2) hud.pytorch.orgで特定のCIジョブのログを見つけ、(3) 生成されたテスト名を取得し、(4) 正確な生成された名前でローカルで再現する。

実行制御のための環境変数も利用できる:PYTORCH_TESTING_DEVICE_ONLY_FORは選択したデバイスにテストを制限し、PYTORCH_TEST_WITH_SLOWは遅いテストを含め、PYTORCH_TEST_WITH_DYNAMOtorch.compile下でのテストをカバーする。またEXPECTTEST_ACCEPTはスナップショットを使用するテストの記録された出力を自動的に更新する。

Puniaはもう1つのよくある間違いも警告している:dtype汎用テスト内でtorch.randn()を使用すること。torch.randn()は常にfloat32テンソルを生成する――bfloat16のために実行されるテストではこれは誤りだ。推奨される代替呼び出しはmake_tensor()で、生成されたテストから受け取るdtype引数を尊重する。

実践的な示唆

このガイドはPyTorchに貢献する人や珍しいCIの失敗をデバッグするすべての人を対象としているが、より広く適用できる:インポート時の動的テスト生成は、コードの爆発なしに組み合わせ空間をカバーする必要があるより大きなPythonプロジェクトに現れるパターンだ。テンプレートクラスと生成されたクラスの違いを理解することが、このようなシステムで生産的に作業するための第一歩だ。PyTorch具体的には、そのインサイトが「CIが不明な名前で失敗した」から「ローカルで再現できた」までの道のりをhud.pytorch.orgでの1回の検索に短縮する。

よくある質問

なぜCIのテスト名がソースコードに記載されている名前と一致しないのですか?
PyTorchはinstantiate_device_type_tests()関数を使用してインポート時に具体的なテストを生成します。テンプレートクラスTestMatmulのtest_basicメソッドは実行時にTestMatmulCPU、TestMatmulCUDA、TestMatmulMPSなどのクラスに展開され、test_basic_cuda_float32のようなメソッドになります。そのためソースコードのテンプレート自体は実行可能なクラスとして存在しません。
OpInfoとは何で、何のために使用されますか?
OpInfoは個々のオペレーターのテスト方法を一元的に記述するメタデータエントリです。サポートされるdtype、入力サンプル、許容誤差、スキップ条件などを含みます。@opsデコレーターを持つジェネリックテストテンプレートが自動的にすべての組み合わせを受け取りテストを実行するため、オペレーターごとのコードの重複が不要です。
CIで見られる失敗をローカルで再現するにはどうすれば良いですか?
Dr. CIコメントからシャード名を取得し、生成されたテスト名(例:TestMatmulCUDA.test_basic_cuda_float32)を見つけてpytest test/test_torch.py -k test_basic_cuda_float32 -xを実行してください。デバイスサフィックスなしのテンプレートクラス名ではテストが見つかりません。