sbatchスクリプトの作成
한국어 원문으로 표시합니다.
목표
sbatch 스크립트를 요구사항대로 작성하고, 배열 작업과 의존성 체인을 구성하고, #SBATCH 위치 오류를 잡아내는 검증기를 만듭니다.
왜 중요한가
#SBATCH 는 첫 번째 실행 가능한 명령이 나오기 전까지만 파싱됩니다. 그 뒤에 쓴 지시자는 평범한 주석이 되고 에러도 경고도 나지 않습니다. 그래서 GPU 를 요청했다고 믿었는데 CUDA 가 안 보이는 상황이 만들어지고, 사용자는 코드를 의심하며 시간을 씁니다. 이 오류는 사람이 눈으로 잡기 어렵고 스크립트로는 쉽게 잡힙니다.
그리고 배열 작업의 %N 제한을 빠뜨리면 100개 작업이 한꺼번에 큐를 채워 다른 사용자를 막습니다. 공유 클러스터에서 이건 사회적 문제이기도 합니다.
단계
/root/jobs디렉터리를 만들고/root/jobs/train.sbatch를 만드세요. 첫 줄은#!/bin/bash이고, 이어서--job-name=resnet-train,--output=/root/jobs/logs/%x-%j.out,--error=/root/jobs/logs/%x-%j.err세 지시자를 넣으세요./root/jobs/logs디렉터리도 만드세요.- 같은 파일에 자원 요청을 추가하세요.
--nodes=1,--ntasks=1,--cpus-per-task=8,--mem=64G - 시간과 파티션을 추가하세요.
--time=04:00:00,--partition=gpu - GPU 요청을 추가하세요.
--gres=gpu:a100:2 /root/jobs/sweep.sbatch를 만드세요. 배열 작업이고--array=1-20%4,--output=/root/jobs/logs/%A_%a.out을 포함해야 하며, 본문에서SLURM_ARRAY_TASK_ID를 사용해야 합니다.train.sbatch의 본문에 다음을 넣으세요.set -euo pipefail로 시작하고,SLURM_CPUS_PER_TASK환경변수를 사용하고,srun으로 실행하는 줄이 있어야 합니다./root/jobs/pipeline.sh를 만드세요.--parsable로 첫 작업 ID 를 받아 변수에 담고,--dependency=afterok:로 두 번째 작업을 제출하는 두 줄이 있어야 합니다./root/jobs/lint.sh를 작성하세요. 첫 번째 인자로 sbatch 스크립트 경로를 받아 다음을 검사하고, 위반이 없으면 종료 코드 0, 있으면 0 이 아닌 값으로 끝나야 합니다.- 규칙 1: 첫 줄이
#!로 시작해야 한다 - 규칙 2: 모든
#SBATCH줄이 첫 번째 실행 명령(주석도 빈 줄도 아닌 줄)보다 앞에 있어야 한다 - 규칙 3:
--job-name과--time지시자가 있어야 한다 채점기가 여러분의train.sbatch(통과해야 함)와, 지시자를 일부러 뒤에 둔 잘못된 스크립트(실패해야 함) 양쪽으로 실행합니다.
- 규칙 1: 첫 줄이
참고
- 출력 패턴 치환자:
%j작업 ID,%x작업 이름,%A배열 부모 ID,%a배열 인덱스. - 의존성 예:
J1=$(sbatch --parsable prep.sh)다음 줄에sbatch --dependency=afterok:$J1 train.sh - 이 실습에서 실제로 sbatch 를 실행하지는 않습니다. 스크립트의 내용을 채점합니다.
- 흔한 실수 1: 지시자를
#SBATCH--time처럼 공백 없이 쓰는 경우.#SBATCH뒤에 공백이 필요합니다. - 흔한 실수 2: 8번 검증기가 빈 줄이나 주석을 '실행 명령' 으로 세어 정상 스크립트를 실패로 판정하는 경우.
기본 골격
/root/jobs 디렉터리를 만들고 /root/jobs/train.sbatch 를 만드세요. 첫 줄은 #!/bin/bash 이고, 이어서 --job-name=resnet-train, --output=/root/jobs/logs/%x-%j.out, --error=/root/jobs/logs/%x-%j.err 세 지시자를 넣으세요. /root/jobs/logs 디렉터리도 만드세요.
shebang 다음 줄부터 지시자를 씁니다. 이름과 출력/에러 경로가 기본입니다.
자원 요청
같은 파일에 자원 요청을 추가하세요. --nodes=1, --ntasks=1, --cpus-per-task=8, --mem=64G
노드, 태스크, 태스크당 CPU, 메모리 네 가지를 지정합니다.
시간과 파티션
시간과 파티션을 추가하세요. --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: 로 두 번째 작업을 제출하는 두 줄이 있어야 합니다.
작업 ID 만 출력하는 옵션이 있습니다. 성공했을 때만 이어지게 하세요.
스크립트 검증기
/root/jobs/lint.sh 를 작성하세요. 첫 번째 인자로 sbatch 스크립트 경로를 받아 다음을 검사하고, 위반이 없으면 종료 코드 0, 있으면 0 이 아닌 값으로 끝나야 합니다.
- 규칙 1: 첫 줄이
#!로 시작해야 한다 - 규칙 2: 모든
#SBATCH줄이 첫 번째 실행 명령(주석도 빈 줄도 아닌 줄)보다 앞에 있어야 한다 - 규칙 3:
--job-name과--time지시자가 있어야 한다 채점기가 여러분의train.sbatch(통과해야 함)와, 지시자를 일부러 뒤에 둔 잘못된 스크립트(실패해야 함) 양쪽으로 실행합니다.
첫 실행 명령 뒤의 지시자는 무시됩니다. 그것을 잡아내는 것이 이 검증기의 목적입니다.