Slurm commands guide¶
Some definitions¶
Jobs, job steps and tasks¶
- A job is allocated defined resources (GPUs, CPU cores, RAM) for a defined time.
It is created with either
sbatch(non-interactive) orsalloc(interactive). A job can be subdivided into steps. -
A job step sub-allocates from the resources of the job. Job steps are created with the
srunwrapper command when it is called from inside a job1. By default a job step will consume all resources allocated to the job, but this can be changed.Steps often map to job phases
Steps most naturally map to phases of a job2: For example,
- Job step
.1might correspond to a stage-in of the dataset to$SLURM_TMPDIR - Job step
.2might run your distributed parallel Python program, and - Job step
.3might stage out the results to$SCRATCH.
- Job step
-
A job step can be further subdivided into tasks. A task is a specific instance of the command created in multiple copies by
srun. Every task has an associated ID within its step, a number$SLURM_PROCIDalso called a "rank" between0and$SLURM_NPROCS-1 inclusive.Tasks map to processes
A task most naturally maps to one of the main processes in a distributed program (but see 3). While a job/job step can be multi-node, each task will run on one and only one node.
In machine-learning work, it is very important to think carefully about how many times should something be done. Some things must be done once per job; others, once per node, once per GPU, or even once per CPU core. The number of tasks in a job step is a very important tool in deciding this. One way this can play out, when reusing the three-job-step example above:
Job step .1 – Dataset stage-in
Staging in a dataset should be done once per node, because $SLURM_TMPDIR
is a filesystem private to each node, but can be accessed by all processes
of that node.
Job step .2 – Distributed processing
The distributed program must run one main process per GPU, because with DDP, each process is mean to manage only one GPU.
Job step .3 – Results stage-out
$SCRATCH is shared by every node and every process can see it.
To avoid collisions, some jobs might arrange for only only one task overall to
write out the job's results.
Basic usage¶
The SLURM documentation provides extensive information on the available commands to query the cluster status or submit jobs.
Below are some basic examples of how to use SLURM.
Submitting jobs¶
Batch job¶
In order to submit a batch job, you have to create a script containing the main command(s) you would like to execute on the allocated resources/nodes.
Your job script is then submitted to SLURM with sbatch.
The working directory of the job will be the one where your executed sbatch.
Specifying directives
Slurm directives can be specified on the command line alongside sbatch or
inside the job script with a line starting with #SBATCH.
Interactive job¶
Workload managers usually run batch jobs to avoid having to watch its progression and let the scheduler run it as soon as resources are available. If you want to get access to a shell while leveraging cluster resources, you can submit an interactive jobs where the main executable is a shell with the srun or salloc commands.
Will start an interactive job on the first node available with the default
resources set in SLURM (1 task/1 CPU). srun accepts the same arguments as
sbatch with the exception that the environment is not passed.
Preserving your environment
To pass your current environment to an interactive job, add
--preserve-env to srun.
salloc can also be used and is mostly a wrapper around srun if provided
without more info but it gives more flexibility if for example you want to get
an allocation on multiple nodes.
Job submission arguments¶
In order to accurately select the resources for your job, several arguments are available. The most important ones are:
| Argument | Description |
|---|---|
-n, --ntasks=<number> |
The number of task in your script, usually =1 |
-c, --cpus-per-task=<ncpus> |
The number of cores for each task |
-t, --time=<time> |
Time requested for your job |
--mem=<size[units]> |
Memory requested for all your tasks |
--gres=<list> |
Select generic resources such as GPUs for your job: --gres=gpu:GPU_MODEL |
Request only what you need
Always consider requesting the adequate amount of resources to improve the scheduling of your job (small jobs always run first).
Request specific resources¶
The Mila cluster has many different types of nodes/GPUs. To request a specific type of node/GPU, you can add specific feature requirements to your job submission command.
To access those special nodes you need to request them explicitly by adding the
flag --constraint=<name>. The full list of nodes in the Mila Cluster can be
accessed at Node profile description.
Examples:
To request a machine with 2 GPUs using NVLink, you can use
To request a DGX system with 8 A100 GPUs, you can use
Checking job status¶
To display jobs currently in queue, use squeue and to get only your jobs type
Note
The maximum number of jobs able to be submitted to the system per user is 1000 (MaxSubmitJobs=1000) at any given time from the given association. If this limit is reached, new submission requests will be denied until existing jobs in this association complete.
Removing a job¶
To cancel your job simply use scancel
Partitioning¶
See the list of Mila cluster partitions. To request an unkillable job with 1 GPU, 4 CPUs, 10G of RAM and 12h of computation do:
You can also make it an interactive job using salloc:
Information on partitions/nodes¶
sinfo provides most of the
information about available nodes and partitions/queues to submit jobs to.
Partitions are a group of nodes usually sharing similar features. On a partition, some job limits can be applied which will override those asked for a job (i.e. max time, max CPUs, etc...)
To display available partitions, simply use
To display available nodes and their status, you can use
And to get statistics on a job running or terminated, use sacct with some of
the fields you want to display
User JobID JobName Partition State Timelimit Start End Elapsed NNodes NCPUS NodeList WorkDir
--------- ------------ ---------- ---------- ---------- ---------- ------------------- ------------------- ---------- -------- ---------- --------------- --------------------
my_usern+ 2398 run_extra+ batch RUNNING 130-05:00+ 2019-03-27T18:33:43 Unknown 1-01:07:54 1 16 node9 /home/mila/my_usern+
my_usern+ 2399 run_extra+ batch RUNNING 130-05:00+ 2019-03-26T08:51:38 Unknown 2-10:49:59 1 16 node9 /home/mila/my_usern+
Or to get the list of all your previous jobs, use the --start=YYYY-MM-DD flag. You can check sacct(1) for further information about additional time formats.
scontrol can be used to
provide specific information on a job (currently running or recently terminated)
JobId=43123 JobName=python_script.py
UserId=my_username(1500000111) GroupId=student(1500000000) MCS_label=N/A
Priority=645895 Nice=0 Account=my_username QOS=normal
JobState=RUNNING Reason=None Dependency=(null)
Requeue=1 Restarts=3 BatchFlag=1 Reboot=0 ExitCode=0:0
RunTime=2-10:41:57 TimeLimit=130-05:00:00 TimeMin=N/A
SubmitTime=2019-03-26T08:47:17 EligibleTime=2019-03-26T08:49:18
AccrueTime=2019-03-26T08:49:18
StartTime=2019-03-26T08:51:38 EndTime=2019-08-03T13:51:38 Deadline=N/A
PreemptTime=None SuspendTime=None SecsPreSuspend=0
LastSchedEval=2019-03-26T08:49:18
Partition=slurm_partition AllocNode:Sid=login-node-1:14586
ReqNodeList=(null) ExcNodeList=(null)
NodeList=node2
BatchHost=node2
NumNodes=1 NumCPUs=16 NumTasks=1 CPUs/Task=16 ReqB:S:C:T=0:0:*:*
TRES=cpu=16,mem=32000M,node=1,billing=3
Socks/Node=* NtasksPerN:B:S:C=1:0:*:* CoreSpec=*
MinCPUsNode=16 MinMemoryNode=32000M MinTmpDiskNode=0
Features=(null) DelayBoot=00:00:00
OverSubscribe=OK Contiguous=0 Licenses=(null) Network=(null)
WorkDir=/home/mila/my_username
StdErr=/home/mila/my_username/slurm-43123.out
StdIn=/dev/null
StdOut=/home/mila/my_username/slurm-43123.out
Power=
Or more info on a node and its resources
NodeName=node9 Arch=x86_64 CoresPerSocket=4
CPUAlloc=16 CPUTot=16 CPULoad=1.38
AvailableFeatures=(null)
ActiveFeatures=(null)
Gres=(null)
NodeAddr=10.252.232.4 NodeHostName=mila20684000000 Port=0 Version=18.08
OS=Linux 4.15.0-1036 #38-Ubuntu SMP Fri Dec 7 02:47:47 UTC 2018
RealMemory=32000 AllocMem=32000 FreeMem=23262 Sockets=2 Boards=1
State=ALLOCATED+CLOUD ThreadsPerCore=2 TmpDisk=0 Weight=1 Owner=N/A MCS_label=N/A
Partitions=slurm_partition
BootTime=2019-03-26T08:50:01 SlurmdStartTime=2019-03-26T08:51:15
CfgTRES=cpu=16,mem=32000M,billing=3
AllocTRES=cpu=16,mem=32000M
CapWatts=n/a
CurrentWatts=0 LowestJoules=0 ConsumedJoules=0
ExtSensorsJoules=n/s ExtSensorsWatts=0 ExtSensorsTemp=n/s
Useful commands¶
| Get an interactive job and give you a shell. (ssh like) CPU only | |
|---|---|
| Get an interactive job with one GPU, 2 CPUs and 12000 MB RAM | |
|---|---|
| start a batch job (same options as salloc) | |
|---|---|
| Re-attach a dropped interactive job | |
|---|---|
| status of all nodes | |
|---|---|
| List GPU type and FEATURES that you can request | |
|---|---|
| (Custom) List available gpus | |
|---|---|
| Cancel a job | |
|---|---|
| summary status of all active jobs | |
|---|---|
| summary status of all YOUR active jobs | |
|---|---|
| summary status of a specific job | |
|---|---|
| status of all jobs including requested resources (see the SLURM squeue doc for all output options) | |
|---|---|
| Detailed status of a running job | |
|---|---|
| Get the node where a finished job ran | |
|---|---|
| Find info about old jobs | |
|---|---|
| List of current and recent jobs | |
|---|---|
Special GPU requirements¶
Specific GPU architecture and memory can be easily requested through the
--gres flag by using either
--gres=gpu:architecture:number--gres=gpu:memory:number--gres=gpu:model:number
Example:
To request 1 GPU with at least 48GB of memory use
The full list of GPU and their features can be accessed here.
Example script¶
Here is a sbatch script that follows good practices on the Mila cluster:
-
Outside of a job, srun creates a job, not a job step; This is an overloaded use of
srunthat is confusing and that we discourage. ↩ -
Job steps usually run sequentially (subdivision in time), because a plain
srunwill use all the resources of a job, but job steps can also run in parallel ifsrunis given arguments that request few resources (subdivision in space and resources) that two steps can proceed in parallel. ↩ -
By far the most common configurations for the tasks of a job's main step will be:
- 1 task per GPU (
--ntasks-per-gpu=1), when launching every process of a distributed program directly withsrun, or - 1 task per node (
--ntasks-per-node=1), when launchingtorchrun/accelerateonce per node, and allowing these processes to decide the appropriate number of children processes themselves.
They lead to different strategies for orchestrating the distributed program's processes, and different environment-variable contents.
A less common configuration is
--ntasks-per-gpu=Nto do N:1 packing of processes onto a single GPU that they all share. ↩↩ - 1 task per GPU (
-
Even within a task, there are further levels of subdivision and parallelism possible: A process can create subprocesses ("workers"), and these processes can create multiple threads. However, these concepts are out of scope for SLURM and are more closely related to the Linux kernel's concept of threads, processes.
The SLURM concept of "task" must also not be confused with the Linux kernel's usage of the same terminology to refer to the basic unit of scheduling - roughly a thread. ↩