TT Lab
はじめる
学ぶ 学習パス コース

HPCとSlurm

sbatchスクリプトの作成

TT Labで続きを見る

目標

sbatchスクリプトを要件どおりに作成し、配列ジョブと依存関係のチェーンを構成して、#SBATCHの位置の誤りを検出する検証ツールを作ります。

なぜ重要なのか

#SBATCHは、最初の実行可能なコマンドが現れる前までしかパースされません。その後ろに書いたディレクティブはただのコメントになり、エラーも警告も出ません。そのため、GPUを要求したと思い込んでいるのにCUDAが見えないという状況が生まれ、ユーザーはコードを疑って時間を使います。このミスは人が目で見つけにくく、スクリプトなら簡単に見つけられます。

また、配列ジョブの%Nの制限を抜かすと、100個のジョブが一度にキューを埋めて他のユーザーを妨げます。共有クラスターでは、これは社会的な問題でもあります。

ステップ

  1. /root/jobsディレクトリを作成し、/root/jobs/train.sbatchを作成してください。1行目は#!/bin/bashで、続けて--job-name=resnet-train、--output=/root/jobs/logs/%x-%j.out、--error=/root/jobs/logs/%x-%j.errの3つのディレクティブを入れてください。/root/jobs/logsディレクトリも作成してください。
  2. 同じファイルにリソースの要求を追加してください。--nodes=1、--ntasks=1、--cpus-per-task=8、--mem=64G
  3. 時間とパーティションを追加してください。--time=04:00:00、--partition=gpu
  4. GPUの要求を追加してください。--gres=gpu:a100:2
  5. /root/jobs/sweep.sbatchを作成してください。配列ジョブで、--array=1-20%4と--output=/root/jobs/logs/%A_%a.outを含める必要があり、本文でSLURM_ARRAY_TASK_IDを使う必要があります。
  6. train.sbatchの本文に次を入れてください。set -euo pipefailで始まり、SLURM_CPUS_PER_TASK環境変数を使い、srunで実行する行が必要です。
  7. /root/jobs/pipeline.shを作成してください。--parsableで最初のジョブIDを受け取って変数に入れる行と、--dependency=afterok:で2つ目のジョブを投入する行の、2行が必要です。
  8. /root/jobs/lint.shを作成してください。最初の引数でsbatchスクリプトのパスを受け取り、次を検査します。違反がなければ終了コード0、あれば0以外の値で終了する必要があります。
    • ルール1: 1行目が#!で始まっていること
    • ルール2: すべての#SBATCH行が、最初の実行コマンド(コメントでも空行でもない行)より前にあること
    • ルール3: --job-nameと--timeのディレクティブがあること 採点ツールが、あなたのtrain.sbatch(通過する必要があります)と、ディレクティブをわざと後ろに置いた誤ったスクリプト(失敗する必要があります)の両方に対して実行します。

参考

基本の骨格

/root/jobsディレクトリを作成し、/root/jobs/train.sbatchを作成してください。1行目は#!/bin/bashで、続けて--job-name=resnet-train、--output=/root/jobs/logs/%x-%j.out、--error=/root/jobs/logs/%x-%j.errの3つのディレクティブを入れてください。/root/jobs/logsディレクトリも作成してください。

shebangの次の行からディレクティブを書きます。名前と、出力・エラーのパスが基本です。

リソースの要求

同じファイルにリソースの要求を追加してください。--nodes=1、--ntasks=1、--cpus-per-task=8、--mem=64G

ノード、タスク、タスクあたりのCPU、メモリの4つを指定します。

時間とパーティション

時間とパーティションを追加してください。--time=04:00:00、--partition=gpu

時間の形式は時:分:秒です。パーティションは、前のラボで作成したものを使ってください。

GPUの要求

GPUの要求を追加してください。--gres=gpu:a100:2

GRESの形式は名前:タイプ:個数です。前のラボで定義したタイプを使ってください。

配列ジョブ

/root/jobs/sweep.sbatchを作成してください。配列ジョブで、--array=1-20%4と--output=/root/jobs/logs/%A_%a.outを含める必要があり、本文でSLURM_ARRAY_TASK_IDを使う必要があります。

範囲の後ろにパーセントを付けて、同時に実行する数を制限できます。出力パターンには、配列の置換指定子を入れてください。

環境変数とsrun

train.sbatchの本文に次を入れてください。set -euo pipefailで始まり、SLURM_CPUS_PER_TASK環境変数を使い、srunで実行する行が必要です。

タスクあたりのCPU数を環境変数で読み取って使うと、リソースの要求とコードが自動で一致します。

依存関係のチェーン

/root/jobs/pipeline.shを作成してください。--parsableで最初のジョブIDを受け取って変数に入れる行と、--dependency=afterok:で2つ目のジョブを投入する行の、2行が必要です。

ジョブIDだけを出力するオプションがあります。成功したときだけ続くようにしてください。

スクリプトの検証ツール

/root/jobs/lint.shを作成してください。最初の引数でsbatchスクリプトのパスを受け取り、次を検査します。違反がなければ終了コード0、あれば0以外の値で終了する必要があります。

最初の実行コマンドより後ろのディレクティブは無視されます。それを見つけ出すのが、この検証ツールの目的です。