티스토리 뷰
처음에 슬럼을 셋업할 때 슬럼이 뭘 하는 서비스인지 몰라서 굉장히 헤맸었다. 어떤 기능이 작동해야 되는지 알 수 없으니 설치가 제대로 됐는지 체크조차 못했다. 따라서 슬럼 설치법을 알아보기 전에 슬럼에 어떤 기능이 있는지 간단하게 알아보자.
Job 제출
리소스 매니저를 사용하고자 하는 이유이다. 슬럼에게 리소스를 요청하면 임의의 노드에 있는 원하는 리소스를 정해진 시간 동안 쓸 수 있게 해준다. 이 리소스를 쓸 수 있는 세션 같은 개념이 있는데, 이를 job(잡, 작업)이라 한다.
사용할 CPU 개수, MEM 크기, GPU 개수를 명시하여 리소스 매니저에게 제출하면 자리가 났을 때 할당시켜준다. 각 리소스의 크기를 명시하는 방법은 다양하다. 아래 세 명령어(srun, sbatch, salloc)들은 대부분의 argument를 공유한다. 명령어 한 줄 외워놓으면 셋 다 자유자재로 쓸 수 있다. 그리고 슬럼 뿐만 아니라 다른 리소스 매니저의 명령어들도 비슷하다. 각 매니저 별 명령어들 공통점/차이점을 비교하는 자료들은 많으니 패스하겠다.
srun: 리소스 잡고 명령어 하나만 실행
srun --gres=gpu:4 --cpus-per-gpu=12 --mem=100G -p debug [명령어]
- nvidia-smi, python hello.py 등 명령어 하나를 실행시킬 수 있다
- 명령어 자리에 --pty bash를 주게 되면 리소스가 할당된 쉘 세션을 열 수 있다. 디버깅 용도로 쓰게 된다.
- 위 코드는 debug라는 파티션에서 GPU 4개, CPU 48개(=12x4), RAM 100GiB를 잡고 명령어를 실행시키라는 뜻이다.
- 노드를 명시하지 않았으므로 debug 파티션 소속의 비어있는 아무 노드에서 실행되게 된다.
- 보통 --pty bash 주고 디버깅 용도로 사용한다.
아래는 여러 가지 사용 방법이다.
# 인터렉티브 쉘 실행: bash 대신 다른 쉘을 사용해도 된다.
srun --gres=gpu:4 --cpus-per-gpu=12 --mem=100G -p debug --pty bash
# nvidia-smi만 실행
srun --gres=gpu:4 --cpus-per-gpu=12 --mem=100G -p debug nvidia-smi
# 파이썬 스크립트 실행
# 이 때, 사용하려는 노드에서도 스크립트 파일에 접근할 수 있어야 한다.
# 그래서 보통 스크립트 파일은 모든 노드에서 접근 가능한 NAS 안에 넣어놓는다.
# 상대경로로도 사용가능하다. 이때 pwd는 해당 job을 제출한 경로이다.
srun --gres=gpu:4 --cpus-per-gpu=12 --mem=100G -p debug python /mnt/hyogun/repos/mmaction2/train.py
# 노드 지정: ariel-v1이라는 노드만 사용할 것이라고 명시한다.
# ariel-v1이라는 이름은 slurm.conf에서 정의해주면 된다.
srun --gres=gpu:4 --cpus-per-gpu=12 --mem=100G -p debug -w ariel-v1 --pty bash
salloc: 리소스를 잡기만 하기
- 얘도 본래 디버깅 용도이지만 srun에 비해 활용도가 낮다.
- srun과의 차이점이라 하면 -N [노드개수] 옵션을 통해 노드를 여러 개 할당받은 상태에서 인터렉티브하게 작업할 수 있다.
- Multi-node CPU job을 돌릴 떄 자주 쓰는 것 같던데 나는 아직 salloc과 친숙하지 않다. 웬만해선 srun으로 해결되는 것 같다.
sbatch: batch job을 스크립트로 제출
인터렉티브가 아니고 background에서 돌아가는 job 집합을 batch job이라 한다. 보통 한번에 대량으로 제출하기에 batch라는 이름이 붙은 것 같다(뇌피셜). Job에 필요한 옵션들과 실행 명령어를 일반적인 쉘 스크립트로 작성하면 된다. 확장자는 통상적으로 .sh나 .sbatch를 사용한다. 개인적으로 sbatch가 더 나은 것 같다. 왜냐면
- 제출용 스크립트(.sbatch)와 일반 스크립트(.sh)를 구분할 수 있다.
- Slurm용 스크립트라는 정보를 준다.
의 이유가 있다. 보통 일반 스크립트를 sbatch 파일에 source 등의 방식으로 import 하는 식으로 많이 쓴다. 일반 스크립트는 보통 데이터셋 세팅, 환경변수 셋팅, 학습 완료 후 visualization 작업 등의 용도로 사용한다.
sbatch job 제출용 스크립트를 알아보자.
#!/bin/bash
#SBATCH -J hello_slurm # Job 이름
#SBATCH -p batch # Job에 사용하는 파티션 (slurm.conf 게시글에서 설명)
#SBATCH --gres=gpu:2 # Job에 사용할 리소스 (GPU)
#SBATCH --cpus-per-gpu=4 # Job에 사용할 리소스 (CPU)
#SBATCH --mem-per-gpu=10G # Job에 사용할 리소스 (RAM)
#SBATCH -t 1:00:00 # 1 hour # 이 job이 리소스를 물고 있을 최대 시간
#SBATCH -o slurm/logs/slurm-%A_%a-%x.out # 해당 스크립트가 실행됐을 때 stdout이 기록될 파일
# 여기까지 마스터에서 실행
####################################################
# 여기부터 할당된 노드에서 실행됨
# sbatch 하는 시점에 해당 env가 활성화돼있으면
# 자동으로 env var들을 inherit 하기 때문에 안 해줘도 됨
# conda activate my_env
hostname # 무슨 노드에 배치됐는지 표시
python train.py # 스크립트 실행
exit 0 # explicit 하게 job을 끝내 잠재적인 completing 문제가 생기는 것을 방지
한 줄 씩 알아보자
- 먼저 shebang으로 시작을 해서 해당 스크립트를 실행시킬 executable을 설정해준다.
- 이후 SBATCH가 붙은 줄은 주석이 아니고 슬럼에게 옵션을 전달하는 줄이다. 마스터가 SBATCH 줄들까지만 실행하고 job을 생성한 다음 이후 할당된 노드에서 나머지가 실행된다. Job 옵션은 case-sensitive이다.
- -J, --job-name: Job 이름을 설정한다.
- -p, --partition: 사용할 파티션을 설정한다. 파티션 개념은 이후에 자세히 설명할 예정이다.
- --gres: GRES(General RESource)라고 슬럼에서 정의한 개념이다. GPU를 명시한다.
- --cpus-per-gpu: 사용할 CPU 개수를 GPU를 기반으로 명시한다. --cpus 등 다른 방법들도 많지만 딥러닝 할 때는 이 옵션이 가장 편한 것 같다.
- --mem-per-gpu: RAM을 명시한다. 10G는 10GiB를 뜻한다. 단위가 없으면 MiB로 인식한다.
- -t, --time: Job을 사용할 시간을 명시한다. 1:00:00은 1시간, 1-0은 1일, 30은 30분을 의미한다. 정확한 포맷은 공식 독스에 나와있다. 시간은 어차피 최대로 땡겨서 명시하면 되는 것 아닌가??? 라고 생각할 수도 있을 것이다. 하지만 아니다. 슬럼은 backfill이라는 스케줄링 알고리즘을 사용하는데, 대기 중인 작업 중 간단해보이는 작업이 있으면 새치기 시켜준다. 시간이 적으면 새치기 할 수 있을 확률이 높아진다. 예상시간 x 120% 정도로 설정하는 것을 추천한다.
- -o: 작업 중 발생하는 stdout 로그들을 저장할 수 있다.
- 단일 파일이 아니고 위와 같이 디렉토리도 같이 명시했다면 해당 디렉토리가 무조건 존재해야한다. 위의 경우에는 slurm/logs가 존재해야 한다.
- Job을 제출한 경로에서 상대경로로만 찍힌다. 절대경로로 찍어도 job을 제출한 곳 pwd 뒤에 append 시킨다.
- -e를 따로 명시하지 않으면 에러 로그도 같이 찍힌다.
- %A, %a, %x등은 슬럼에서 제공하는 해당 job의 정보를 담고있는 변수들이다. 공식 독스 참조
- -e: 에러 로그들이 여기에 찍힌다. 따로 이 옵션을 명시하지 않으면 -o에 명시된 파일에 같이 찍힌다.
자세한 옵션은 공식 독스에 자세히 나와있다.
아래는 내가 실제로 사용하는 스크립트 예시이다. SLURM_ARRAY_JOB_ID 등은 슬럼에서 job이 할당되고 나서 부여해주는 환경변수이다. 이 마저도 공식 독스에 나와있다.
#!/bin/bash
#SBATCH -J closed_k2b-tsm-locality
#SBATCH -p batch_vll
#SBATCH --gres=gpu:8
#SBATCH --cpus-per-gpu=12
#SBATCH --mem-per-gpu=37G
#SBATCH -t 4-0
#SBATCH -w vll3
#SBATCH --array 0-8
#SBATCH -o slurm/logs/slurm-%A_%a-%x.out
current_time=$(date +'%Y%m%d-%H%M%S')
# overleaf table 기준
project='cdar'
task='03_simnreal' # table name
subtask='021_closed_k400_babel' # column
backbone='01_tsm'
model='010_source_only' # row
add_on='locality'
extra_setting='default' # 'default' if none
path_experiment="${project}/${task}/${subtask}/${backbone}/${model}/${add_on}/${extra_setting}"
workdir="work_dirs/train_output"
workdir="${workdir}/${path_experiment}"
workdir="${workdir}/${SLURM_ARRAY_JOB_ID}__${SLURM_JOB_NAME}/${SLURM_ARRAY_TASK_ID}/${current_time}"
local_indices=(0 1 2 3 4 5 6 7 DELETE) # None as random
local_index="${local_indices[SLURM_ARRAY_TASK_ID]}"
index_arg=$([ "$local_index" = 'DELETE' ] && echo 'model.forward_kwargs._delete_=True' || echo "model.forward_kwargs.index=$local_index" )
lr=1e-3
config='configs/recognition/cdar/03_simnreal/021_closed_k400_babel/01_tsm/010_source_only/k2b_tsm_local.py'
N=$SLURM_GPUS_ON_NODE
calibed_lr="$(perl -le "print $lr * $N / 4")"
OMP_NUM_THREADS=${N} MKL_NUM_THREADS=${N} torchrun --nproc_per_node="${N}" --master_port=$((10000+RANDOM%20000)) tools/train.py "$config" \
--launcher pytorch --seed "$SLURM_ARRAY_TASK_ID" \
--work-dir "$workdir" \
--validate --test-last --test-best \
--cfg-options \
optimizer.lr="$calibed_lr" \
log_config.interval=10 evaluation.interval=1 \
"$index_arg"
# shellcheck source=../../../../_extract_backbone_tsm.sh
source slurm/cdar/03_simnreal/_extract_backbone_tsm.sh
# shellcheck source=../../../../_tsne.sh
source slurm/cdar/03_simnreal/_tsne.sh
source /data/hyogun/send_slack_message_mmaction.sh
exit 0
Job은 제출된 시점에 slurmctld(Slurm Controller Daemon)이 복사해서 가지고 있는다. slurmctld가 실행되고 있는 마스터 노드의 별도의 저장 공간에 올라간다. 따라서 Job을 제출하고 나서 스크립트를 수정해도 제출된 job에는 영향이 없다. 하지만 파이썬 스크립트는 아직 읽지 않은 시점이기에 파이썬 코드를 수정하면 영향이 있다.
로깅
sinfo
scontrol show job
scontrol show node
scontrol show part
squeue
Job 조작
scancel JOBID
scontrol update
scontrol hold/release
scontrol requeue JOBID
그 외
scontrol wait_job JOBID
scontrol write batch_script JOBID
job을 제출하고 스크립트를 수정하면 어떻게 될까?
Advanced
job array
sbatch나 salloc 안에서 srun
job dependency
scontrol로 job update 하기
singularity 기반으로 docker 컨테이너 sudo 없이 돌리기
파이썬 기반으로 slurm job을 제출해주는 초강력 패키지: submitit
---
다음 게시글
- job array
- slurm.conf 톺아보기
- 하드웨어 셋업
- deepops 설치
- accounting
중 하나
'[infra] > Slurm' 카테고리의 다른 글
Slurm | Slurm이란? (12) | 2022.08.20 |
---|