HPC 와 Slurm · 작업 제출과 자원 요청 · 실습
sbatch 스크립트 작성
목표
sbatch 스크립트를 요구사항대로 작성하고, 배열 작업과 의존성 체인을 구성하고, #SBATCH 위치 오류를 잡아내는 검증기를 만듭니다.
왜 중요한가
#SBATCH 는 첫 번째 실행 가능한 명령이 나오기 전까지만 파싱됩니다. 그 뒤에 쓴 지시자는 평범한 주석이 되고 에러도 경고도 나지 않습니다. 그래서 GPU 를 요청했다고 믿었는데 CUDA 가 안 보이는 상황이 만들어지고, 사용자는 코드를 의심하며 시간을 씁니다. 이 오류는 사람이 눈으로 잡기 어렵고 스크립트로는 쉽게 잡힙니다.
그리고 배열 작업의 %N 제한을 빠뜨리면 100개 작업이 한꺼번에 큐를 채워 다른 사용자를 막습니다. 공유 클러스터에서 이건 사회적 문제이기도 합니다.
단계
1. /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 디렉터리도 만드세요.
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: 로 두 번째 작업을 제출하는 두 줄이 있어야 합니다.
8. /root/jobs/lint.sh 를 작성하세요. 첫 번째 인자로 sbatch 스크립트 경로를 받아 다음을 검사하고, 위반이 없으면 종료 코드 0, 있으면 0 이 아닌 값으로 끝나야 합니다.
- 규칙 1: 첫 줄이
#!로 시작해야 한다 - 규칙 2: 모든
#SBATCH줄이 첫 번째 실행 명령(주석도 빈 줄도 아닌 줄)보다 앞에 있어야 한다 - 규칙 3:
--job-name과--time지시자가 있어야 한다
채점기가 여러분의 train.sbatch(통과해야 함)와, 지시자를 일부러 뒤에 둔 잘못된 스크립트(실패해야 함) 양쪽으로 실행합니다.
참고
- 출력 패턴 치환자:
%j작업 ID,%x작업 이름,%A배열 부모 ID,%a배열 인덱스. - 의존성 예:
J1=$(sbatch --parsable prep.sh)다음 줄에sbatch --dependency=afterok:$J1 train.sh - 이 실습에서 실제로 sbatch 를 실행하지는 않습니다. 스크립트의 내용을 채점합니다.
- 흔한 실수 1: 지시자를
#SBATCH--time처럼 공백 없이 쓰는 경우.#SBATCH뒤에 공백이 필요합니다. - 흔한 실수 2: 8번 검증기가 빈 줄이나 주석을 '실행 명령' 으로 세어 정상 스크립트를 실패로 판정하는 경우.
단계 8개
- 기본 골격
- 자원 요청
- 시간과 파티션
- GPU 요청
- 배열 작업
- 환경변수와 srun
- 의존성 체인
- 스크립트 검증기