mcpField
T
tao-run-on-slurm

tao-run-on-slurm

github.com/nvidiaクラウド・DevOps3.8k1.6k 回インストール今日更新
リポジトリ

tao-run-on-slurm について

tao-run-on-slurmは、SLURM管理下のリモートGPUクラスターでTAOの処理を実行するスキルです。SSHでジョブを投入・管理し、GPU割り当て前に共有ストレージへデータとコンテナイメージを準備します。

主な機能

  1. 01SSH経由でSLURMジョブを投入
  2. 02状態確認、ログ閲覧、ジョブ取消
  3. 03単一ノードと複数ノードの実行
  4. 04GPU割り当て前のイメージとデータ配置
  5. 05クラスターとSSHの事前確認

活用シーン

  1. 01共有Lustre上でTAO学習を実行
  2. 02リモートジョブの状態やログを確認
  3. 03投入済みまたは実行中のジョブを取消

インストール

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

$npx skills add https://github.com/nvidia/skills --skill tao-run-on-slurm

インストール後、Claude Code で/tao-run-on-slurmを入力して読み込まれたか確認します。

同梱ファイル

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

BENCHMARK.md
skill-card.md
skill.oms.sig
config/
skillspector-baseline.yaml
evals/
evals.json
references/
cosmos-slurm-guardrails.md
detailed-guide.md
skill_info.yaml
slurm-container-execution.md
slurm-preflight-storage.md
slurm-ssh-credentials.md

詳細

SLURM

スタンドアロンでインストールする場合 このセッションが TAO スキルバンクプラグインによって初期化されていない場合は、まず tao-setup スキルを実行してください(ホストの事前確認、認証情報、スキル間の検出)。

SLURM で管理されるクラスター向けのリモート GPU コンピューティングプラットフォームです。ジョブは SSH 経由で起動ホストからログインノードに送信され、共有ファイルシステム上にステージングされ、sbatch で送信されます。実行にはコンテナーサポート付きの srun が使用されます。

使用する場面

ユーザーが管理対象の GPU クラスター、共有 Lustre ストレージ、スケジューラーが管理する GPU 割り当てを利用できる場合は、SLURM を使用してください。エージェントマシンにしか存在しないローカルファイルには SLURM を使用しないでください。データと出力はクラスターからアクセスできる必要があります。

事前確認と SSH

SLURM_USER と SLURM_HOSTNAME がエクスポートされていること、およびログインホストへのパスワードなし SSH が機能することを確認してください(ssh -o BatchMode=yes)。 起動ホストに必要なのは ssh であり、ローカルの sbatch、srun、Enroot、Lustre マウントは必要ありません。選択したリモートのログイン/コンピュートフレームで、これらのスケジューラー、Pyxis、Enroot、共有ストレージの依存関係を事前確認してください。モデル固有のインスペクターは、インストール済みスキルから SSH stdin 経由でストリーミングできます。アドホックなソースパッチをステージングしたり、起動ホストを SLURM フレームとして扱ったりしないでください。 プライベートな nvcr.io イメージの場合は、クラスター上に ~/.config/enroot/.credentials を(クラスターとユーザーの組み合わせごとに)一度インストールしてください。Pyxis/Enroot はジョブ環境から NGC_KEY を読み取らないため、永続的な認証情報がないと、認証が必要なイメージのプルはジョブ開始時に "Could not process JSON input" というエラーで失敗します。NGC_KEY の値がシェル履歴、中間ファイル、チャット出力に残らないよう、printf | ssh のヒアドキュメントを使ってインストールしてください。その値を cat/echo で出力してはいけません。

事前確認に失敗した場合、エージェントはユーザーに Bash 経由でインストール/修正を許可するよう促します。例外は pip でインストール可能な Python の要件です。これらは自動的にインストールしてから、事前確認を再実行してください。

事前確認スクリプト、Enroot 認証情報のヒアドキュメント、前提となるキーの設定(キーペア、ssh-copy-id、known_hosts、コンテナーのキーのマウント、2FA の処理)、SSH 障害の修復を促すメッセージについては、references/slurm-ssh-credentials.md を参照してください。

実行 — 4 つの動詞

tao-run-on-slurm はプラットフォームのコンシューマーです。ssh + sbatch/squeue/sacct/scancel を使って spec-bundle を実行し、変更するのはジョブレコードのみです。ストレージはティア A(Lustre)です。データセットは送信前に共有パスへステージングし、Pyxis 経由で読み込みます。割り当て内で S3 から取得してはいけません(スケジューラーのアイドルタイムアウトにより GPU がアイドル状態のジョブが終了され、無駄になった時間分の料金が発生します)。$BANK = ${TAO_SKILL_BANK_PATH}、$LOGIN = 解決済みの SLURM_HOSTNAME です。

submit
  1. すでにステージ済みのものを再利用する — 決してやり直さない(ティア A):
    • イメージ: @@IMAGE@@ は Lustre 上の .sqsh です。存在する場合は既存のものを再利用します (ssh $LOGIN ls <sqsh>)。存在しない場合に限り、enroot import で一度だけ変換します (名前でキャッシュされます。references/slurm-container-execution.md を参照)。
    • データセット: すでに Lustre 上にあることを確認し(ssh $LOGIN test -e …)、そのパスを参照します。 tao-data-io でステージするのは、まだ存在しない小さな補助入力だけです。既存データを再ステージしたり、 アロケーション内でトレーニングセットをステージしたりしてはいけません。 その後、これらのパスを使って Lustre 上の <job_dir>/specs/spec.yaml に仕様を作成します。
  2. 認証情報 → サイドカー(インラインにはしない): 実行にセッション認証情報 (例:HF_TOKEN)が必要な場合は、Lustre 上のパーミッション 600 のサイドカーに書き込み、 終了時にテンプレートで完全消去します。NGC イメージのプルには、ジョブ環境変数ではなく 一度限りの ~/.config/enroot/.credentials を使用します(references/slurm-ssh-credentials.md を参照)。
    set -a; source /path/to/.env; set +a   # omit if already exported
    printf 'export HF_TOKEN=%s\n' "$HF_TOKEN" | ssh $LOGIN "umask 077; cat > <job_dir>/job_$JOB_ID.env"
    
  3. レコードを開く — ID を発行し、起動前に Lustre 上の results_dir を紐付ける:
    JOB_ID=$("$BANK/scripts/tao_job_record.py" open --platform slurm --image "$IMAGE" \
      --network-arch "$ARCH" --action "$ACTION" --storage-tier A --results-root "$SLURM_BASE_RESULTS_DIR")
    
  4. オプションのモデルライフサイクルを使用します。 検証済みの spec-bundle に execution がある場合、分散実行の意図をネイティブな SLURM/Pyxis にマッピングしながら、 順序とセマンティクスを維持します。ステージするのは、チェックサムで閉じた supporting_files だけです。汎用ライフサイクルとステージングの契約全体については、 references/slurm-container-execution.md を参照してください。
  5. templates/slurm/singlenode.sbatch.tmpl をレンダリングします。すべての @@<NAME>@@ を置換します (JOB_NAME=$JOB_ID、NUM_GPUS、CPUS_PER_TASK、TIME、LOG_DIR、 IMAGE、CONTAINER_MOUNTS=<RUNTIME_SUPPLIED_MOUNTS>、COMMAND=<共有ストレージ上の spec を読み込む bundle コマンド>、SBATCH_EXTRA= アカウント/パーティションの行、ENV_FILE= サイドカーのパスまたは 空欄、EXTRA_ENV= クラスターの NCCL 関連設定)→ <job_dir>/sbatch/job_$JOB_ID.sbatch。 送信前にリントと構文チェックを行います: redact_secrets.py lint <sbatch> が 成功し、bash -n <sbatch> も成功する必要があります。
  6. 送信し、RUNNING を記録します:
    SLURM_ID=$(ssh $LOGIN "sbatch --parsable <job_dir>/sbatch/job_$JOB_ID.sbatch")
    "$BANK/scripts/tao_job_record.py" mark "$JOB_ID" --state RUNNING --backend-ref "$SLURM_ID"
    

ゲートを通過せずに送信した場合、またはレコードを開かずに送信した場合、ID がないため起動できません。

status
# sacct ANNOTATES states ("CANCELLED by 12345") and truncates them to the
# default column width, so a cancelled job reads back as "CANCELLED+" and
# matches nothing in the table below — reporting UNKNOWN instead of CANCELED.
# Widen the column, take the first word, drop the truncation marker.
st=$(ssh $LOGIN "sacct -j $SLURM_ID -X -n -o State%30" | awk '{print $1}' | tr -d '+')
# (use squeue while the job is still PENDING; sacct lags briefly after submit)
SLURM の状態用語
PENDINGPENDING
RUNNING / COMPLETINGRUNNING
COMPLETEDCOMPLETE(results_dir 内の status.json を確認)
FAILED / TIMEOUT / OUT_OF_MEMORYERROR(インフラ障害かプログラムの問題かを分類 → 再試行、M6)
NODE_FAIL / BOOT_FAILERROR、err_class=ERR_INFRA(--requeue でこれらのジョブを再投入)
CANCELLED / PREEMPTED / REVOKEDCANCELED
(見つからない)UNKNOWN

ネイティブのサブ状態は遷移の message に含まれます。選択した間隔でポーリングします。 キューでの待ち時間が長いのは通常のことです。経過時間を理由に停止しないでください。

logs
ssh $LOGIN "tail -n ${N:-200} <log_dir>/$JOB_ID-$SLURM_ID/main.out"   # SLURM auto-creates the %x-%j subdir
cancel
ssh $LOGIN "scancel $SLURM_ID"
"$BANK/scripts/tao_job_record.py" mark "$JOB_ID" --state CANCELED --source agent

すでに終了している SLURM ジョブも、キャンセル成功として扱います。

マルチノード(nodes > 1)

同じ4つの動詞に、submit時の追加項目が3つ加わります。

  1. 単一ノード用ではなく templates/slurm/multinode.sbatch.tmpl をレンダリングします。こちらは単一ノード用の厳密なスーパーセットであり(--nodes / --wait-all-nodes とランデブーブロックを追加します)、WORLD_SIZE はノード数です(TAOでの誤った命名です)。グローバルランク数に変更しないでください。
  2. まずNCCLプローブを実行します。実際のジョブの前に、コンテナのtorchrunで、タイムアウトを約120秒に設定して、低コストの2ノードall-reduce(scripts/nccl_allreduce_probe.py)を実行します。torchrunを呼び出す前に、TAOのランデブー値を TAO_NODE_COUNT=$WORLD_SIZE、TAO_GPUS_PER_NODE=$NUM_GPU_PER_NODE、TAO_NODE_RANK=$SLURM_PROCID として保持してください。torchrunは標準の WORLD_SIZE をグローバルプロセス数で上書きします。NCCL_PROBE_OK → 続行します。タイムアウト(collectiveが停止した場合)→ クラスターのNCCL設定を EXTRA_ENV に指定して、再度プローブを実行します。CS-OCI-ORDでは export NCCL_P2P_DISABLE=1(ノード内P2Pの停止)が該当し、多くの場合 NCCL_SOCKET_IFNAME=eth0 / NCCL_IB_DISABLE=1 も指定します。動作する環境設定はクラスターごとにキャッシュし、以降のジョブではプローブをスキップします。P2Pの停止は2つ以上のGPUを持つ単一ノードでも発生するため、gpus_per_node > 1 も条件に含めてください。
  3. Tier-A Lustre、サイドカー認証情報、記録、lintに変更はありません。
Cosmosバックエンドのガードレール

Cosmosコマンドをレンダリングする前に、references/cosmos-slurm-guardrails.md を読んでください。ここでは、イメージのステージング、プランナーのマテリアライズ、FrameworkおよびCosmos-RLの起動コントラクト、ワーカー/ランタイムの要件、終了/ステータスの処理について定義しています。

ストレージ

ローカルパスや file:// パスではなく、共有ファイルシステムのURIを使用してください。tao-core はリモートバックエンドでローカルパス/ファイルパスを拒否します。

  • Lustre上のユーザー指定データセットには lustre:///absolute/path を使用します。
  • マイクロサービスのメタデータには slurm:// パスが含まれることがあり、コンテナの起動前にLustreパスへ変換されます。

データセットのルートパス(モデルスキルが必須ファイルへマッピングします)またはspecキーの直接指定パスのどちらも受け付けます。SSH接続が成功した後、スクリプトを生成する前に、ログインホストから必須の各データセットパスに対して test -e を実行してください。失敗した場合は、実際のトレーニングジョブで失敗するスクリプトを生成せずに停止し、修正したパスまたはステージング済みのデータを依頼してください。ルートモードと直接specモード、バックエンドの詳細、結果ディレクトリのデフォルトについては、references/slurm-ssh-credentials.md を参照してください。

コンテナの実行

tao-core はPyxis/Enrootを介してTAOコンテナを実行します。

  1. spec、環境、クラウドメタデータ用のコンパクトなJSONファイルを、<job_dir>/specs、<job_dir>/env、<job_dir>/meta にステージングします。
  2. GPUジョブの前に、srun -n1 -p <conversion_partition> enroot import を使用してDockerイメージをキャッシュ済みのSQSHイメージに変換します。これはイメージごとに1回発生するコストであり、任意の最適化ではありません。下記のAcquire the image off the GPU allocationを参照してください。
  3. <job_dir>/sbatch/job_<job_id>.sbatch にsbatchスクリプトを書き込みます。
  4. sbatch --export=ALL <script> を送信します。
  5. srun --container-image=<image> --container-mounts=<RUNTIME_SUPPLIED_MOUNTS> でコンテナを実行します。

受け付けるイメージ形式:/path/to/image.sqsh、registry#image:tag、docker://registry#image:tag、通常の registry/image:tag(必要に応じてPyxis形式に変換されます)。SQSHへの変換はイメージ名ごとにキャッシュされます。:latest イメージでは、force_reconvert_latest が有効でない限り、キャッシュ済みのSQSHが再利用されます。

GPU 割り当ての外でイメージを取得する

GPU を使えるのは、計算が始まったときではなく、割り当てが始まった時点からです。 トレーニング前にジョブが行う処理は、レジストリーイメージのプル、変換、データセットの取得など、すべてアイドル状態で課金され、クラスターの GPU アイドル監視機能からも見える GPU 上で実行されます。TAO イメージを初めてプルして Enroot で変換するには数分かかります。その間にジョブが終了させられる可能性があり、費用も発生します。

そのため、GPU ジョブの開始時点でイメージがローカルの .sqsh になっている必要があります。docker:// や registry#image:tag の URI をそのまま srun --container-image= に渡すと、Pyxis が割り当ての中でプルと変換の両方を行います。これがまさに避けるべき落とし穴です。CPU パーティションで一度だけ変換し、その後のすべてのジョブで生成されたファイルを指定してください。

# One-time per image, on CPU — costs no GPU time.
ssh $LOGIN "test -e <sqsh>" || \
  ssh $LOGIN "srun --chdir=/tmp -n1 -c4 --mem=7200M \
    -p <cpu_partition> -t <minutes> \
    bash -c 'set -Eeuo pipefail
      export TMPDIR=/tmp
      export ENROOT_TEMP_PATH=/tmp/enroot-tao-\${SLURM_JOB_ID}
      export SLURM_ENROOT_TEMP_PATH=\${ENROOT_TEMP_PATH}
      mkdir -p \"\${ENROOT_TEMP_PATH}\"
      cd /tmp
      enroot import -o <sqsh> docker://<registry>#<image>:<tag>'"

# Every GPU job then references the file, never the registry.
srun --container-image=<sqsh> ...

データにも同じルールが適用されます。割り当ての中で取得するのではなく、投入前に Lustre にステージングしてください(tier A)。

CS-OCI-ORD の変換では、cpu_long、4 CPU、7200M メモリ、排他的でないノード、ノードローカルの Enroot 一時パスを使用し、少なくとも 120 分を確保します。実行リファレンスには、根拠と QOSGrpMemLimit からの復旧手順が記録されています。

変換が不完全な場合は自動的に検出されます。SQSH は hsqs マジックで検証されるため、切り詰められたファイルは、気づかれないまま使用されるのではなく、拒否されます。変換は一度だけ実行され、以降はイメージ名をキーにキャッシュされます。

変換に失敗しても、レジストリーイメージにフォールバックしてはいけません。 一見手軽な復旧方法として、docker://… を srun に渡して Pyxis に処理させる方法がありますが、それではプル処理が GPU 割り当ての中に戻ってしまいます。変換はそのコストを避けるために行うものであり、しかもこの方法を使うのは、すでに何かがうまくいっていないときです。変換に失敗した場合や、変換結果が切り詰められている場合は致命的なエラーとして扱い、CPU パーティションで修正してから再投入してください。

診断方法:ジョブの出力が予想外に遅い場合は、実際に --container-image= に渡された値を確認してください。.sqsh のパスではなくレジストリー URI が指定されている場合、GPU 上でプルが行われています。

監視とキャンセル

  • スケジューラーの状態は、保存されている SLURM ジョブ ID を使って squeue/sacct から取得します。TAO のターミナル状態は、共有結果フォルダー内の status.json から取得します。
  • チャット監視が有効な間は、ターミナル状態ではないジョブ(PENDING、RUNNING、またはその他の状態)について、指定された間隔でポーリングを続けてください。30 分などの一定の経過時間を過ぎたからといって停止しないでください。共有 GPU パーティションでは、キューの待ち時間が長くなるのは通常のことです。
  • チャット監視が有効な場合、SLURM ジョブがターミナル状態になるまでは、ターミナル状態ではないジョブに対する最終応答を送信しないでください。最終応答は監視を切り離す操作です。ユーザーが切り離し/停止を依頼した場合、またはジョブがターミナル状態になった場合にのみ使用してください。
  • ログは SSH 経由で <job_dir>/slurm-logs/<slurm_job_name>-<slurm_job_id>/main.out および .err から読み取ります。
  • backend_details.slurm_metadata.slurm_job_id を検索し、SSH 経由で scancel <slurm_job_id> を実行してキャンセルします。ジョブが見つからない場合や、すでに終了している場合は、キャンセルが成功したものとして扱います。

状態のマッピング:

  • PENDING -> Pending
  • RUNNING または COMPLETING -> Running
  • COMPLETED -> status.json を確認
  • FAILED、BOOT_FAIL、DEADLINE、OUT_OF_MEMORY、NODE_FAIL -> ログが再試行可能なインフラストラクチャのパターンに一致する場合は再試行し、それ以外は Error
  • CANCELLED、PREEMPTED、REVOKED -> Canceled
  • TIMEOUT -> Error
  • SUSPENDED、STOPPED -> Running(引き続きスケジューラーが管理しており、再開される可能性があります。ネイティブのサブ状態は遷移メッセージに含まれます。docker の paused と同じ規則です)

必須入力

SLURM の受付時に以下を確認してください。認証情報の全リスト、マイクロサービスのスキーマキー、デフォルト値については、references/slurm-ssh-credentials.md を参照してください。

  • SLURM_USER(必須):ログインノードの SSH ユーザー名。
  • SLURM_HOSTNAME(必須):フェイルオーバー用の、カンマ区切りのログインホスト名。
  • SLURM_PARTITION(必須):GPU ジョブの送信先となるパーティションのリスト。パッケージのデフォルトは polar,polar3,polar4,grizzly で、いずれも 4 時間キューとして扱われます。
  • SSH_KEY_PATH(推奨、起動前に必要):非対話型の公開鍵認証に使う秘密鍵。問題解決時にはまずこれを確認し、SSH_AUTH_SOCK のエージェントソケットによる代替手段より優先してください。
  • SLURM_BASE_RESULTS_DIR(任意):共有ファイルシステムのベースパス。デフォルトでは、実行時に指定・検証される共有ストレージのルートを使用します。
  • SLURM_ACCOUNT(通常、サイトのポリシーで必須):#SBATCH --account に指定するアカウント。

ユーザーから、サイトでアカウントが必要だと言われた場合、カスタムの結果保存ルートを希望した場合、またはデフォルト値の上書きなしではワークフローを進められない場合を除き、初回の受付時に SLURM_ACCOUNT や SLURM_BASE_RESULTS_DIR を確認しないでください。

リソースのデフォルト値

tao-core のデフォルト値:

  • num_nodes:1
  • num_gpus:4
  • max_num_gpus_per_node:8
  • cpus_per_task:16
  • time_hours:4
  • timeout_hours:3.8
  • max_time_hours:4
  • container_mounts:実行時に指定される、明示的なソースからターゲットへのマウント設定
  • use_requeue:true
  • use_sqsh:true

起動処理では、パッケージのデフォルトである、最大実行時間 4 時間、子プロセスのタイムアウト 3.8 時間を必ず使用してください。12 時間にしてはいけません。ユーザーが SLURM_TIME_HOURS にそれより長い時間を指定した場合は、送信前に選択したパーティションが対応していることを確認してください。パッケージのデフォルトのパーティションリスト polar,polar3,polar4,grizzly の場合、4 時間を超える要求は受け付けず、ユーザーが実際により長い実行時間を希望するときに限り、別のパーティションを求めてください。

max_num_gpus_per_node 以上の場合は、ノードを専有で割り当て、合計 GPU 数からノード数を算出してください。

マルチノードとリトライ

マルチノードジョブ(num_nodes > 1)では、レンダリングされた templates/slurm/multinode.sbatch.tmpl が sbatch ディレクティブを設定し、 PyTorch 分散のランデブー環境変数をエクスポートします: WORLD_SIZE、NUM_GPU_PER_NODE、 NODE_RANK、MASTER_ADDR、MASTER_PORT(29500)。TAO のエントリポイントは WORLD_SIZE + NUM_GPU_PER_NODE を読み取り、内部で torchrun を構築します。Cosmos-RL は コントローラー、ポリシー、ロールアウトワーカーに対して特別なマルチノードロール処理を行います。 NCCL プローブのゲートとクラスターごとの環境キャッシュについては、上記の ### Multi-node (nodes > 1) 送信サブセクションを参照してください。

SLURM ジョブの入力には S3 ではなく Lustre を使用してください。 GPU の割り当ては ジョブがディスパッチされた瞬間に開始されるため、スクリプトの冒頭で長時間の s3:// ダウンロードを行うと 割り当てを浪費し、GPU アイドルによりジョブが強制終了される可能性があり、いずれにしても課金されます。 まずトレーニングデータを共有ファイルシステムにステージングし、lustre:///... として参照してください。 S3/HF/NGC の事前フェッチは小規模な補助入力(チェックポイント、設定)には問題ありませんが、 トレーニングデータセットには適していません。K8s/Brev はこのスケジューラーアイドルの制約を共有しません。

インフラ障害(NODE_FAIL、BOOT_FAIL、NCCL トランスポートタイムアウト、 CUDA ドライバー初期化の失敗、GPU/IB リンクダウン、OOM キラーによるノード回収、Xid エラー)が発生した場合、ログからインフラかプログラムかを分類し、ステージングされたワークロードを再送信する前に --retry-of を付けて新しいリトライレコードを作成します(M6)。通常のトレーニング失敗は 即座に表面化するため、壊れた仕様がリトライ 予算を消費することはありません。#SBATCH --requeue は SLURM_USE_REQUEUE=true によりデフォルトで有効になっているため、SLURM 自体が NODE_FAIL または プリエンプション時にエージェントレベルの再送信より先にジョブを再キューイングします。Cosmos などの ワークロード契約では --no-requeue が必要になる場合があります。

空の sbatch --parsable レスポンスや SSH 切断は曖昧なものとして扱ってください: 正確なジョブ名で照合し、盲目的に送信せず、継承されたノード除外を検証してください。 参照されている実行ガイドに完全な決定表が定義されています。 完全なマルチノードの環境変数/sbatch ディレクティブの詳細と表、クラスター要件、 Lustre-not-S3 ルールの全文、障害モードのチェックリストについては references/slurm-container-execution.md を参照してください。

参照

  • references/slurm-ssh-credentials.md — プリフライトスクリプト、SSH/キー設定、 enroot 認証情報、完全な認証情報リスト、バックエンドの詳細、ストレージルール、 SSH 修復プロンプト。
  • references/slurm-container-execution.md — コンテナ実行手順、 モニタリング、ステータスマッピング、キャンセル、マルチノードの詳細、 Lustre-not-S3、リトライ、障害モード。
  • references/slurm-preflight-storage.md — 拡張プリフライト/ストレージノート。
  • references/cosmos-slurm-guardrails.md — Cosmos Framework および Cosmos-RL の起動とステータスのガードレール。
  • references/detailed-guide.md — 分割された参照のナビゲーションマップ。

コメント