LabHub
学习 学习路径 课程

HPC 与 Slurm

编写 sbatch 脚本

在 LabHub 中继续学习

한국어 원문으로 표시합니다.

목표

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(통과해야 함)와, 지시자를 일부러 뒤에 둔 잘못된 스크립트(실패해야 함) 양쪽으로 실행합니다.

참고

기본 골격

/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 이 아닌 값으로 끝나야 합니다.

첫 실행 명령 뒤의 지시자는 무시됩니다. 그것을 잡아내는 것이 이 검증기의 목적입니다.