mcore-testing について
mcore-testingは、NVIDIA/Megatron-LMのコントリビューター向けテストガイドです。分散ユニットテスト、機能テスト、CIレシピの運用と、テストを残したまま一時停止する方法を説明します。
主な機能
- 01分散pytestユニットテストの手順
- 02エンドツーエンド機能テストの設定
- 03YAMLレシピの構造と制御
- 04不安定なテストのマーカーとスキップ規則
- 05CIの再試行と成果物の保存場所
活用シーン
- 01CIに近い条件でローカルテストを実行
- 02機能テストとゴールデン値を追加
- 03レシピを保ってテストを一時停止
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ nvidia/ skills --skill mcore-testingインストール後、Claude Code で/mcore-testingを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
BENCHMARK.mdskill-card.mdskill.oms.sigevals/evals.json詳細
テストガイド
先に知っておきたいテストの事実
テストを削除せずに無効化する方法について:
- 機能テストのレシピ項目は YAML に残し、
scopeに-brokenを付けて無効化します。たとえば、scope: [mr-github]をscope: [mr-github-broken]にします。 - ユニットテストのスキップには、代わりに pytest マーカーを使います。
@pytest.mark.flaky_in_devはデフォルトの開発環境で、@pytest.mark.flakyは LTS でスキップします。 - テストを見つけやすくし、簡単に再有効化できるようにすることが目的の場合、テストケースやレシピ項目を削除しないでください。
テストの構成
tests/
├── unit_tests/ # pytest, 1 node × 8 GPUs, torch.distributed runner
├── functional_tests/ # end-to-end shell + training scripts
│ └── test_cases/
│ └── {model}/{test_case}/
│ ├── model_config.yaml # training args
│ └── golden_values_{env}_{platform}.json
└── test_utils/
├── recipes/
│ ├── h100/ # YAML recipes for H100 jobs
│ └── gb200/ # YAML recipes for GB200 jobs
└── python_scripts/ # helpers (recipe_parser, golden-value download, …)
テストの実行方法
GitHub Actions ランナーは launch_nemo_run_workload.py を呼び出し、このスクリプトが nemo-run を使って DockerExecutor コンテナを起動します。リポジトリは /opt/megatron-lm にバインドマウントされ、トレーニングデータは /mnt/artifacts にマウントされます。
ユニットテストは torch.distributed.run を通じてディスパッチされます。
- ランク 0 と 3 の出力は stdout に tee されます。それ以外のすべてのランクはログファイルにのみ書き込みます。
- ランクごとのログファイルは
{assets_dir}/logs/1/に出力され、実行後に GitHub アーティファクトとしてアップロードされます。
機能テストは tests/functional_tests/shell_test_utils/run_ci_test.sh によって実行されます。pytest による検証ステップを実行するのはランク 0 のみです。すべてのランクのトレーニング出力はアーティファクトとしてアップロードされます。
不安定な失敗の自動再試行:launch_nemo_run_workload.py は、既知の一時的な失敗パターン(NCCL タイムアウト、ECC エラー、セグメンテーション違反、HuggingFace への接続障害など)に対して、実際の失敗と判定する前に最大 3 回 再試行します。
レシピ YAML の構造
レシピは tests/test_utils/recipes/ にあり、tests/test_utils/python_scripts/recipe_parser.py によって解析されます。各ファイルでは、直積となる products ブロックが個別のワークロード仕様に展開されます。
type: basic
format_version: 1
maintainers: [mcore]
loggers: [stdout]
spec:
name: "{test_case}_{environment}_{platforms}"
model: gpt # maps to tests/functional_tests/test_cases/{model}/
build: mcore-pyt-{environment}
nodes: 1
gpus: 8
n_repeat: 5
platforms: dgx_h100
time_limit: 1800
script_setup: |
...
script: |-
bash tests/functional_tests/shell_test_utils/run_ci_test.sh ...
products:
- test_case: [my_test]
products:
- environment: [dev, lts]
scope: [mr-github]
platforms: [dgx_h100]
主な実行時プレースホルダー:{assets_dir}、{artifacts_dir}、{test_case}、{environment}、{platforms}、{n_repeat}。
テストを削除せずに無効化する
レシピ YAML のテストケースを一時的に無効化するには、scope の値に -broken を付けます。項目を削除しないでください。
# before (test runs in CI)
scope: [mr-github]
# after (test is skipped; entry preserved for easy re-enable)
scope: [mr-github-broken]
ユニットテストをローカルで実行する
すべてのユニットテストは torch.distributed グループを初期化するため、どの実行にも GPU アクセスが必要であり、torch.distributed.run を通す必要があります。
# Full suite
uv run python -m torch.distributed.run --nproc-per-node 8 -m pytest -q \
tests/unit_tests
# Single file
uv run python -m torch.distributed.run --nproc-per-node 8 -m pytest -q \
tests/unit_tests/models/test_gpt_model.py
# Single test
uv run python -m torch.distributed.run --nproc-per-node 8 -m pytest -q \
tests/unit_tests/models/test_gpt_model.py::TestGPTModel::test_constructor
# Filter by name substring
uv run python -m torch.distributed.run --nproc-per-node 8 -m pytest -q \
tests/unit_tests -k optimizer
マーカーフィルター
# Exclude flaky tests during development
uv run python -m torch.distributed.run --nproc-per-node 8 -m pytest -q \
tests/unit_tests -m "not flaky and not flaky_in_dev"
# Include experimental tests
uv run python -m torch.distributed.run --nproc-per-node 8 -m pytest -q \
tests/unit_tests --experimental
CI との実行条件の一致
CI のバケットで発生した失敗を正確に再現するには、tests/unit_tests/run_ci_test.sh を使います。個別に実行する場合は、上記の torch.distributed.run の直接実行方法を推奨します。
注意点
pyproject.tomlではaddopts = --durations=15 -s -rAが設定されています。stdout はキャプチャされないため(-s)、複数ランクの実行中は出力が混在します。特定のランクをデバッグするときは、--capture=fdで上書きしてください。tests/unit_tests/conftest.pyは/opt/dataにテストデータがあるか確認し、見つからない場合はダウンロードを試みます。標準コンテナの外で実行する場合は、手動で用意するか、データに依存するテストをスキップしてください。
ユニットテストの追加
tests/unit_tests/<category>/test_<name>.pyを作成します。tests/unit_tests/conftest.pyのフィクスチャを使います。- 必要に応じてマーカーを付けます。
@pytest.mark.internal—legacyタグではスキップされます@pytest.mark.flaky_in_dev—dev環境(CI のデフォルト)ではスキップされます(標準パイプラインをブロックせずに不安定なテストを無効化する場合に使用します)@pytest.mark.flaky—lts環境ではスキップされます@pytest.mark.experimental—latestタグでのみ実行されます
- ローカルで確認します(上記の「ユニットテストをローカルで実行する」を参照)。
- 専用の CI バケットが必要なテストの場合は、
tests/test_utils/recipes/h100/unit-tests.yamlに項目を追加します。
機能テスト/統合テストの追加
-
tests/functional_tests/test_cases/<model>/<test_name>/を作成します。 -
MODEL_ARGS、ENV_VARS、TEST_TYPEを指定してmodel_config.yamlを作成します。 -
tests/test_utils/recipes/h100/に YAML レシピを追加します(必要に応じてgb200/にも追加します)。必須フィールド:scope、environment、platform、n_repeat、time_limit。 -
PR をプッシュし、ラベル 「Run functional tests」 を追加して、全テストを実行します。
-
実行が成功したら、正解値をダウンロードします。
python tests/test_utils/python_scripts/download_golden_values.py \ --source github --pipeline-id <run-id> -
ダウンロードした正解値をコミットします。
よくある問題
| 問題 | 原因 | 解決方法 |
|---|---|---|
| ローカルではテストに合格するが、CI では失敗する | 環境またはデータパスが異なる | DATA_PATH、DATA_CACHE_PATH、および environment タグ(dev と lts)を確認します |
| コード変更後に正解値が一致しない | 数値的なリグレッション | クリーンな実行後に download_golden_values.py で新しい正解値をダウンロードします |
cicd-integration-tests-gb200 がトリガーされない | GB200 のジョブにはメンテナー権限が必要 | メンテナーにトリガーを依頼するか、Run functional tests ラベルを追加します |