Skip to content

SLURM workload manager

SLURM is the job scheduler and resource manager on all DIPC clusters. You write a batch script describing what resources you need and what to run, submit it with sbatch, and SLURM queues it until resources are available.

Batch scripts

A batch script is a shell script with #SBATCH directives that tell SLURM what resources to allocate. Here is a minimal example:

my_job.slurm
#!/bin/bash
#SBATCH --job-name=my_job
#SBATCH --partition=general
#SBATCH --qos=regular
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=1
#SBATCH --mem=4gb
#SBATCH --time=01:00:00
#SBATCH --output=%x.%j.out
#SBATCH --error=%x.%j.err

module load some_software/1.0

srun ./my_program < input.dat

Each #SBATCH line is a resource directive. SLURM reads them before executing the script body.

Common directives

Directive Example Description
--partition --partition=general Node pool to submit to (default: general)
--qos --qos=regular Quality of Service (see below)
--nodes --nodes=2 Number of nodes
--ntasks --ntasks=8 Total number of tasks (MPI processes)
--ntasks-per-node --ntasks-per-node=4 Tasks per node
--cpus-per-task --cpus-per-task=8 CPU cores per task (OpenMP threads)
--mem --mem=32gb Memory per node
--mem-per-cpu --mem-per-cpu=4gb Memory per CPU core
--time --time=1-00:00:00 Walltime limit (D-HH:MM:SS)
--gres --gres=gpu:2 Generic resources (e.g. GPUs)
--job-name --job-name=simulation Job name
--output --output=%x.%j.out File for stdout (%x = job name, %j = job ID)
--error --error=%x.%j.err File for stderr
--mail-user --mail-user=you@dipc.org Email for notifications
--mail-type --mail-type=END,FAIL When to send email (BEGIN, END, FAIL, ALL)

Estimating resources

If you do not know how much memory or time your jobs need, overestimate on the first runs and then use seff <jobid> on completed jobs to see actual usage. Tighten your requests accordingly (smaller requests get scheduled faster).

Submitting and running jobs

sbatch - batch submission

Submit a script to the queue:

sbatch my_script.slurm
Submitted batch job 123456

The job runs asynchronously. Output goes to the files specified with --output and --error (or slurm-<jobid>.out by default).

Environment propagation

By default, all environment variables from your shell are propagated to the job. To prevent unexpected behavior, add #SBATCH --export=NONE to your script and explicitly load modules inside it.

salloc interactive allocation

Request resources without a batch script. SLURM grants an allocation and drops you into a subshell:

$ salloc --qos=test --nodes=1 --mem=20gb --time=00:10:00
salloc: Granted job allocation 1999

$ srun hostname
hyperion-125

$ exit
salloc: Relinquishing job allocation 1999

To get a shell directly on the compute node, append srun --pty bash:

$ salloc --qos=test --time=00:10:00 srun --pty bash
salloc: Granted job allocation 1477543
salloc: Nodes hyperion-125 are ready for job
user@hyperion-125:~$

Info

With srun --pty bash, logging out from the compute node terminates the job. If you connect manually via SSH instead, the allocation persists after you disconnect from the node.

srun - direct execution

Run a command on allocated resources. Useful for quick tests:

$ srun --qos=test --mem=1gb --time=00:05:00 bash -c 'echo "Hello from $(hostname)"'
Hello from atlas-281

srun blocks until the command finishes. If your terminal disconnects, the job ends. For anything longer than a quick test, wrap srun in a batch script and use sbatch.

Within a batch script, srun is used to launch your program on the allocated resources. It automatically inherits the resource allocation from the #SBATCH directives.

Partitions and QoS

Each cluster organizes nodes into partitions and associates them with Quality of Service levels (QoS) that set limits on walltime, node count, and running jobs.

Partitions:

Partition Description
general (default) All publicly available nodes
preemption Nodes owned by specific groups, publicly available with restrictions
preemption-gpu A100 SXM4 nodes for small GPU jobs, preemptible

QoS for general and preemption partitions:

QoS
Priority Max walltime Max nodes/user Max running jobs/user Max submitted Max TRES
regular (default) 200 1 day 60 180
test 1000 10 min 2 2 2
long 200 2 days 25 40
xlong 200 8 days 20 20 200
serial 200 2 days 1000 2000 CPUs=1, GPUs=0, nodes=1

QoS for preemption-gpu partition:

QoS Priority Max walltime Max TRES
preemption-gpu (default) 200 8 days GPUs=3, nodes=1

Global submission limit

A global limit of 1000 submitted jobs applies across all QoSs (sum of all queued and running jobs). The serial QoS is an exception, allowing up to 2000.

Info

Do not specify QoSs from the general partition when submitting to preemption-gpu. Use the partition's default QoS.

Atlas EDR and Atlas FDR share a single SLURM instance: same partitions, same QoS limits. The key differences are:

  • Nodes: Jobs submitted from Atlas EDR login nodes run exclusively on EDR compute nodes, and jobs from Atlas FDR login nodes run on FDR compute nodes.
  • Storage: Each cluster has its own /scratch filesystem.
  • Software: The available module stack differs between EDR and FDR (see Atlas EDR and Atlas FDR).
  • GPUs: Only Atlas EDR has GPU nodes. Atlas FDR has no GPUs.
  • MPI launcher: On Atlas FDR, use mpirun instead of srun to launch MPI programs (see MPI template note below).

Partitions:

Partition Description
general (default) All publicly available nodes
preemption Nodes owned by specific groups, publicly available with restrictions

QoS:

QoS Priority Max walltime Max nodes/user Max running jobs/user Max submitted Max TRES
regular (default) 200 1 day 24 50
test 1000 10 min 2 2 2
long 200 2 days 24 20
xlong 200 8 days 12 10
serial 200 2 days 500 cpu=1, gpu=1, node=1

Tip

If your jobs require longer execution times or more nodes than these limits allow, contact support-hpc@dipc.org. Limits can be adjusted and custom QoS/partitions can be temporarily created.

The preemption partition

All clusters have a preemption partition containing nodes owned by specific research groups. These nodes are often idle and are made available to all users, with one condition: if the owner group submits a job that needs its nodes, preemption jobs running on those nodes will be canceled and requeued.

The submission procedure is:

#SBATCH --partition=preemption
#SBATCH --qos=regular       # use any QoS from the general partition

Design preemption-safe jobs

Jobs on the preemption partition can be killed and restarted at any time. If your code does not save checkpoints, it will start from scratch. See the requeuing policy section.

Job templates

These templates work on all clusters unless noted otherwise. Adjust --ntasks-per-node and --cpus-per-task to match the core count of your target nodes (see the specifications page of each cluster).

Where to run

Submit jobs from and direct output to your /scratch directory.

MPI

mpi_job.slurm
#!/bin/bash
#SBATCH --qos=regular
#SBATCH --job-name=mpi_job
#SBATCH --nodes=2
#SBATCH --ntasks-per-node=48
#SBATCH --cpus-per-task=1
#SBATCH --mem=200gb
#SBATCH --time=1-00:00:00
#SBATCH --output=%x.%j.out
#SBATCH --error=%x.%j.err

module load program/version

srun ./binary < input

This runs 96 MPI processes (2 nodes x 48 tasks/node). srun handles process placement and inherits the SLURM allocation automatically.

Atlas FDR: use mpirun instead of srun

Atlas FDR does not have full SLURM-MPI integration. On this cluster, replace the srun line with:

mpirun -np ${SLURM_NTASKS} ./binary < input

This applies to all MPI jobs on Atlas FDR, including hybrid MPI+OpenMP. On Hyperion and Atlas EDR, always prefer srun.

For more details on MPI compilation and execution, see MPI.

OpenMP

omp_job.slurm
#!/bin/bash
#SBATCH --qos=regular
#SBATCH --job-name=omp_job
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=48
#SBATCH --mem=200gb
#SBATCH --time=1-00:00:00
#SBATCH --output=%x.%j.out
#SBATCH --error=%x.%j.err

module load program/version

export OMP_NUM_THREADS=${SLURM_CPUS_PER_TASK}

srun ./binary < input

Always set OMP_NUM_THREADS from SLURM_CPUS_PER_TASK to ensure the thread count matches the allocation. See OpenMP for thread affinity and tuning.

Hybrid MPI + OpenMP

hybrid_job.slurm
#!/bin/bash
#SBATCH --qos=regular
#SBATCH --job-name=hybrid_job
#SBATCH --nodes=2
#SBATCH --ntasks-per-node=4
#SBATCH --cpus-per-task=12
#SBATCH --mem=200gb
#SBATCH --time=1-00:00:00
#SBATCH --output=%x.%j.out
#SBATCH --error=%x.%j.err

module load program/version

export OMP_NUM_THREADS=${SLURM_CPUS_PER_TASK}

srun ./binary < input

This runs 8 MPI processes (4 per node), each with 12 OpenMP threads, using 48 cores per node total. On Atlas FDR, replace srun with mpirun -np ${SLURM_NTASKS} (see MPI note above). See MPI: Hybrid MPI+OpenMP for details.

GPU

GPU request syntax differs between clusters. Atlas FDR has no GPUs. For a complete guide including available hardware, constraints, and multi-GPU training, see GPU accelerators.

gpu_job.slurm
#!/bin/bash
#SBATCH --qos=regular
#SBATCH --job-name=gpu_job
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=8
#SBATCH --gres=gpu:1
#SBATCH --constraint=rtx3090
#SBATCH --mem=32gb
#SBATCH --time=04:00:00
#SBATCH --output=%x.%j.out
#SBATCH --error=%x.%j.err

module load CUDA/12.4.0

srun ./my_gpu_program

On Hyperion, use --gres=gpu:N for the number of GPUs and --constraint to select the type (rtx3090, a100-sxm4, a100-pcie, a6000).

gpu_job.slurm
#!/bin/bash
#SBATCH --qos=regular
#SBATCH --job-name=gpu_job
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=4
#SBATCH --gres=gpu:p40:1
#SBATCH --mem=32gb
#SBATCH --time=04:00:00
#SBATCH --output=%x.%j.out
#SBATCH --error=%x.%j.err

module load CUDA/11.7.0

srun ./my_gpu_program

On Atlas EDR, the GPU type goes directly in the --gres flag: --gres=gpu:p40:1 or --gres=gpu:rtx3090:2.

Node selection

Hyperion: microarchitecture constraints

Hyperion has three CPU microarchitectures. By default, SLURM ensures all nodes in a job share the same architecture (no mixing), but you can request a specific one:

#SBATCH --constraint=icelake
#SBATCH --constraint=cascadelake
#SBATCH --constraint=emerald

This constraint works with sbatch, srun, and salloc. Requesting a GPU type via --constraint implicitly selects the CPU architecture of those nodes. See GPU accelerators: GPU and CPU microarchitecture for the mapping.

Atlas EDR and Atlas FDR

These clusters have homogeneous CPU architectures within each cluster, so no microarchitecture constraint is needed. See the Atlas EDR specifications and Atlas FDR specifications for node details.

Job arrays

Job arrays submit multiple instances of the same job, each with a unique index. They are ideal when you need to run the same computation on many different inputs. See the Job arrays page for a full guide with practical examples.

Dependency chains

Start a job only after another job reaches a certain state:

$ sbatch first_job.slurm
Submitted batch job 1000

$ sbatch --dependency=afterok:1000 second_job.slurm
Submitted batch job 1001

Available dependency types:

Dependency Behavior
after:jobid Start after jobid begins execution
afterany:jobid Start after jobid terminates (any exit status)
afterok:jobid Start after jobid completes successfully
afternotok:jobid Start after jobid fails (non-zero exit)
singleton Start after any previous job with the same name and user terminates

The singleton dependency is useful for chaining restartable jobs: submit the same script multiple times and each instance waits for the previous one to finish.

Managing jobs

squeue - view the queue

# All your jobs
squeue -u $USER

# Only running jobs
squeue -u $USER -t RUNNING

# Only pending jobs
squeue -u $USER -t PENDING

# Jobs in a specific partition
squeue -u $USER -p preemption

scancel - cancel jobs

# Cancel a specific job
scancel 123456

# Cancel all your jobs
scancel -u $USER

# Cancel all your pending jobs
scancel -t PENDING -u $USER

sacct - job accounting (completed jobs)

After a job finishes, sacct shows what actually happened:

sacct -j 123456 --format=JobID,JobName,MaxRSS,Elapsed,State,NodeList

sstat - live job statistics

For a currently running job:

sstat --format=JobID,AveCPU,AveRSS,MaxRSS -j 123456

seff - efficiency report

Quick summary of CPU and memory efficiency for a completed job:

$ seff 123456
Job ID: 123456
State: COMPLETED
Cores: 48
CPU Utilized: 12:34:56
CPU Efficiency: 87.5%
Memory Utilized: 24.5 GB
Memory Efficiency: 51.0% of 48.00 GB

Tip

Run seff on your completed jobs regularly. If CPU efficiency is consistently low, you may be requesting too many cores. If memory efficiency is very low, reduce --mem to let your jobs schedule faster.

Warning

seff numbers are only meaningful for successfully completed jobs. Do not use them for running or failed jobs.

Local scratch for I/O-intensive jobs

Every compute node has a local disk mounted at /lscratch. It is faster than the shared /scratch filesystem because I/O does not travel over the network. Use it when your job reads or writes many small files (e.g., molecular dynamics restarts, image datasets, temporary databases).

The pattern is simple: copy your input to /lscratch at the start of the job, run there, and copy the results back to /scratch at the end.

lscratch_job.slurm
#!/bin/bash
#SBATCH --qos=regular
#SBATCH --job-name=io_job
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=8
#SBATCH --mem=16gb
#SBATCH --time=06:00:00
#SBATCH --output=%x.%j.out
#SBATCH --error=%x.%j.err

WORKDIR=/lscratch/${USER}/${SLURM_JOB_ID}
mkdir -p ${WORKDIR}

# Copy input data to local disk
cp /scratch/${USER}/project/input.dat ${WORKDIR}/

# Run from local disk
cd ${WORKDIR}
srun ./my_program < input.dat

# Copy results back to shared storage
cp ${WORKDIR}/output.dat /scratch/${USER}/project/

# Clean up
rm -rf ${WORKDIR}

Warning

/lscratch is local to each node and is not shared between nodes. Do not use it for multi-node MPI jobs that need shared file access. Also, if your job is killed (timeout, preemption, node failure), the cleanup step will not run and files on /lscratch will remain until the next reboot.

Tip

Use $SLURM_JOB_ID in the directory name to avoid collisions if multiple jobs run on the same node.

Requeuing policy

If a node fails (freeze, reboot, memory error), SLURM will attempt to requeue your job by default. This is useful for checkpoint-based workflows but dangerous otherwise, because the restarted job will overwrite output files.

To prevent automatic requeuing:

#SBATCH --no-requeue

Warning

Add #SBATCH --no-requeue to your batch scripts unless your code is specifically designed to resume from checkpoints.

SLURM environment variables

These variables are available inside your batch script at runtime:

Variable Description
SLURM_JOB_ID Job ID
SLURM_JOB_NAME Job name
SLURM_SUBMIT_DIR Directory from which the job was submitted
SLURM_JOB_NODELIST List of nodes assigned to the job
SLURM_NNODES Number of nodes
SLURM_NTASKS Total number of tasks
SLURM_CPUS_PER_TASK CPUs per task
SLURM_ARRAY_JOB_ID Job array parent ID
SLURM_ARRAY_TASK_ID Job array task index

Use these to make your scripts portable. For example, export OMP_NUM_THREADS=${SLURM_CPUS_PER_TASK} ensures your thread count always matches the allocation regardless of what you requested.

Job states

State Meaning
PENDING Waiting in queue for resources
RUNNING Executing on compute nodes
COMPLETED Finished successfully (exit code 0)
FAILED Terminated with non-zero exit code
TIMEOUT Exceeded the walltime limit
CANCELLED Cancelled by user or administrator
NODE_FAIL Terminated due to a node failure
PREEMPTED Terminated because a higher-priority job needed the resources

Troubleshooting

My job has been PENDING for a long time

Check why SLURM is holding your job:

squeue -j <jobid> -o "%.18i %.30j %.10R"

The NODELIST(REASON) column shows the cause. Common reasons:

Reason What it means What to do
Priority Other jobs have higher priority (fair-share). See Job priority and scheduling for how this is computed Wait; your priority increases over time
Resources Not enough free nodes/cores/memory right now Wait, or reduce your request
ReqNodeNotAvail A node you requested (or that matches your constraints) is unavailable, e.g. in DRAIN for maintenance Wait; SLURM picks the job up once the node returns. If the cluster looks free but the reason persists, see the reason looks stuck below
QOSMaxJobsPerUserLimit You hit the max running jobs for this QoS Wait for running jobs to finish
QOSMaxNodePerUserLimit You are using the max nodes allowed Wait or reduce --nodes

The reason reflects the last scheduling cycle in which SLURM evaluated your job, not a live state. If it appears to disagree with the current state of the cluster, see the next entry.

If the reason is Resources and the cluster is not particularly busy, your request may be too large for any single node. For example, requesting 256 GB of memory on nodes that have 192 GB will never schedule.

The reason in squeue looks stuck or outdated

The reason field shown by squeue is not real-time state. SLURM records it the last time it evaluated your job during a scheduling cycle, and refreshes it only the next time the scheduler looks at that specific job. Until then the field keeps the old reason, even if the underlying condition (e.g. a node in DRAIN for maintenance, a busy partition) is no longer in effect. The Slurm documentation makes this explicit: the field reports "the reason that was encountered by the attempted scheduling method" (squeue man page, JOB REASON CODES section).

All pending jobs remain in the queue and are continuously considered every scheduling cycle, regardless of what the reason reads. The field is descriptive, not prescriptive: it does not hold your job back.

To check the actual state of the nodes you requested:

scontrol show node <nodename> | grep State
sinfo -N -o "%N %T"

<nodename> accepts ranges, e.g. hyperion-[252-254,257].

Common base states:

State Allows new jobs? Notes
IDLE Yes No jobs running
MIXED Yes Some CPUs in use, others free
ALLOCATED Yes (when CPUs free up) All listed CPUs already in use
COMPLETING No (transient) Jobs finishing; will become IDLE or MIXED shortly
DRAIN, DRAINING, DRAINED No Reserved for maintenance or admin action
DOWN, FAIL, NOT_RESPONDING No Node is unhealthy or offline
RESERVED Only matching reservations Held for an advance reservation

A node in MIXED or ALLOCATED is not blocked: it simply has work on it. SLURM will start your job there as soon as enough resources free up, in the order set by priority and backfill. You may also see flags appended such as +PLANNED (the node is being held for a higher-priority job; backfill can still place yours there if it fits in the gap) or +RESERVED.

If the reason still looks stale and you would like it refreshed sooner, contact us at support-hpc@dipc.org with the job ID; we can nudge the scheduler to re-evaluate it.

My job failed immediately with exit code 1

Check the error file (<jobname>.<jobid>.err) for the actual error. Common causes:

  • Module not found: the software is not available on this cluster or the version string is wrong. Run module spider <name> to check.
  • File not found: input files are not where the script expects them. Remember that the job runs from $SLURM_SUBMIT_DIR (the directory where you ran sbatch).
  • Permission denied: you may be trying to write to a read-only filesystem. On Atlas, /dipc is not accessible from compute nodes.
My job was killed with signal 9 (exit code 137)

The job exceeded its memory allocation and was killed by the kernel (OOM killer). Increase --mem or --mem-per-cpu and resubmit. Use sacct -j <jobid> --format=JobID,MaxRSS,State to see how much memory was actually used before the kill.

SLURM rejects my job with 'Invalid account'

Your user account is not associated with a SLURM account on this cluster. Contact support-hpc@dipc.org with your username and the cluster name.

See also

  • GPU accelerators


    GPU hardware inventory and SLURM mechanics per cluster.

    GPU guide

  • PyTorch distributed training


    Distributed deep learning with PyTorch.

    PyTorch

  • MPI


    Compiling and running MPI applications.

    MPI guide

  • OpenMP


    Threading and affinity.

    OpenMP guide

  • Compilers


    Available compilers and optimization flags.

    Compilers