Running Jobs with Slurm
Learn how to create, submit, and monitor jobs using the Slurm workload manager.
Submit batch jobs to run applications on compute nodes
The cluster uses the Slurm workload manager for scheduling jobs on compute nodes. Running applications directly on login nodes is not permitted. Users must submit a batch script or request an interactive session via Slurm.
A batch script is a text file containing resource requirements (cores, time, memory) and the commands to run your application. Slurm uses directives beginning with #SBATCH to specify these requirements.
Quick Links
- Examples and templates
- Available resources
- Advanced
- Migrating from LSF?
Step 1: Create batch script
Serial job
The following batch script run_mycode.sh runs a serial application mycode.exe:
#!/bin/bash #SBATCH --job-name=mycode #SBATCH --output=stdout.%j #SBATCH --error=stderr.%j #SBATCH --ntasks=1 #SBATCH --mem=4G #SBATCH --time=02:00:00 ./mycode.exe
The #SBATCH directives specify job parameters:
- --ntasks=1 requests one CPU core
- --mem=4G requests 4 GB of memory per node
- --time=02:00:00 sets a 2-hour time limit
- --job-name sets the job name displayed by squeue
- --output and --error specify where stdout and stderr are written (%j is replaced by the job ID)
Parallel job
→ Read this note before submitting parallel jobs.
For a parallel application using 4 cores on a single node:
#!/bin/bash #SBATCH --job-name=mycode #SBATCH --output=stdout.%j #SBATCH --error=stderr.%j #SBATCH --nodes=1 #SBATCH --ntasks=4 #SBATCH --mem=8G #SBATCH --time=02:00:00 ./my_parallel_code.exe
Using --nodes=1 ensures all 4 tasks run on the same node. For MPI applications, use srun to launch:
srun ./my_mpi_code.exe
Advanced options
Step 2: Submit job
Batch job
Submit your batch script using sbatch:
sbatch run_mycode.sh
Slurm returns a job ID that you can use to monitor the job.
Interactive job
For GUI applications requiring display, use an HPC-VCL node.
For testing and debugging, start a short interactive session:
Production jobs should always use batch scripts. For testing, request an interactive session using salloc:
salloc --ntasks=4 --nodes=1 --time=00:30:00
This allocates 4 cores on one node for 30 minutes. Once allocated, you'll have a shell on a compute node.
For a serial job with exclusive node access:
salloc --ntasks=1 --exclusive --time=00:30:00
Interactive sessions should be kept brief. Idle sessions may be terminated per the Acceptable Use Policy.
Step 3: Monitor job
Job status
Use squeue to check your jobs:
$ squeue -u $USER JOBID PARTITION NAME USER ST TIME NODES NODELIST 12345 standard mycode unityID R 0:45 1 c001n01
Job states (ST): PD=pending, R=running, CG=completing.
The sq local command gives a focused view of each state, with the columns that actually matter for it — priority and the reason a job is waiting when pending, elapsed time against the wall limit when running:
$ sq --pend JobID User Partition QOS Priority Reason 1842001 unityID compute normal 18422 Resources $ sq --run JobID User Partition QOS Elapsed TimeLimit 1841190 unityID compute normal 18:22:47 3-00:00:00
For one job's full resource request and timestamps, use sj:
sj JOBID # request + state for a job sj JOBID_7 # an array task element squeue -j JOBID -l # native equivalent
→ Monitoring jobs and cluster status
Is a running job making progress?
squeue only shows that a job is running, not whether it is doing any work. Use sjs (local wrapper for the sstat command) to see live CPU, memory, and disk usage:
$ sjs 464645 464645 unityID, RUNNING, elapsed 4:44:21 alloc: cpu=12,mem=48000M,node=1,billing=23 Step NTasks AveCPU %CPU MaxRSS %Mem MaxDiskRead MaxDiskWrite 464645.batch 1 04:55:28 9% 9.24G 20% 181.72G 235.09G
Here %CPU of 9% means the job is using about 1 of its 12 requested cores. Add -r to re-sample and watch what changes, which is how you tell a busy job from a stuck one.
→ Is my running job making progress?
Cancel a job
Use scancel with the job ID:
scancel JOBID
To cancel all your jobs:
scancel -u $USER
Partition and node status
View partition information with si (local wrapper for sinfo command):
$ si Partition Architecture Avail Alloc Total compute Haswell 232 388 620 compute Broadwell 654 234 936 compute Cascadelake 468 364 896 gpu Genoa 72 56 128 $ si --gpus # report GPUs instead of cores Partition GPU Avail Alloc Total gpu RTX_2080 3 1 4 gpu A30 0 8 8 gpu H100 16 24 40
Idle hardware is not the whole story: a QOS group limit can stop your job even when Avail is non-zero. Add --qos to cap Avail by what a job under that QOS could actually claim right now, and to show the group limit and how much of it is already in use:
$ si --gpus --qos gpu Partition GPU GrpTRES Used Avail Alloc Total gpu H100 40 24 16 24 40
→ Choosing partitions, cores, and resources · The cluster status page provides detailed node availability.
Sample batch scripts
MPI job
#!/bin/bash #SBATCH --job-name=hydro #SBATCH --output=hydro.out.%j #SBATCH --error=hydro.err.%j #SBATCH --ntasks=32 #SBATCH --mem=16G #SBATCH --time=02:00:00 #SBATCH --partition=compute module load PrgEnv-intel srun ./hydro.exe
Runs an MPI code using 32 tasks for up to 2 hours. The srun command launches the MPI tasks across allocated nodes.
Hybrid MPI+OpenMP job
#!/bin/bash #SBATCH --job-name=chemtest #SBATCH --output=chemtest.out.%j #SBATCH --error=chemtest.err.%j #SBATCH --nodes=2 #SBATCH --ntasks-per-node=4 #SBATCH --cpus-per-task=8 #SBATCH --time=02:00:00 #SBATCH --exclusive module load openmpi-gcc export OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK srun ./chemtest.exe
Runs a hybrid code with 8 MPI tasks (4 per node) and 8 OpenMP threads per task. Uses --exclusive for dedicated node access. See hybrid jobs guide.
GPU job
#!/bin/bash #SBATCH --job-name=nnetworks #SBATCH --output=out.%j #SBATCH --error=err.%j #SBATCH --ntasks=1 #SBATCH --mem=32G #SBATCH --time=00:30:00 #SBATCH --partition=gpu #SBATCH --gres=gpu:a100:1 module load cuda ./nnetworks.exe
Runs a CUDA application using one A100 GPU. GPU type is required in the --gres directive (e.g., --gres=gpu:a100:1). Available types: a10, a30, a100, gtx1080, h100, h200, l40, l40s, p100, rtx_2080. See the GPU jobs guide and CUDA software page.
Command quick reference
Common commands
| Command | Description |
|---|---|
| sbatch script.sh | Submit batch job |
| squeue -u $USER | Show your jobs |
| scancel JOBID | Cancel a job |
| sinfo | Show partition status |
| salloc | Request interactive allocation |
| srun | Run parallel tasks |
| sacct -j JOBID | Job accounting info |
| seff JOBID | Job efficiency report |
Common directives
| Directive | Description |
|---|---|
| --job-name=NAME | Job name |
| --output=FILE | Stdout file (%j=jobid) |
| --error=FILE | Stderr file |
| --ntasks=N | Number of tasks |
| --nodes=N | Number of nodes |
| --time=HH:MM:SS | Time limit |
| --partition=NAME | Partition (queue) |
| --qos=NAME | Quality of Service (e.g., long for up to 10 days) |
| --account=NAME | Account to charge (defaults to your group) |
| --mem=SIZE | Memory per node |
| --constraint=NAME | Specific Node Feature/Architecture |
| --gres=gpu:TYPE:N | Request N GPUs of TYPE model |
Local commands
| Command | Description |
|---|---|
| si [--partition NAME] [--nodes] [--gpus] [--memory] [--all] [--drain] [--qos NAME] | One Avail / Alloc / Total table of a single resource per partition and architecture; by default CPU cores (Total = full deployed capacity). --nodes gives one row per node (multi-partition nodes listed once); --gpus reports GPUs with the GPU model as architecture (GPU nodes only); --memory reports memory in GiB (--gpus and --memory are mutually exclusive); --all also includes down nodes (adds a Down/Drain or State column); --drain lists only drained/draining nodes with the drain reason; --qos NAME caps Avail by the QOS's group limits and adds a GrpTRES column |
| sa [LOGIN] | Show Slurm associations (account, partition, default QOS, QOS list) for $USER or LOGIN |
| sq --pend / sq --run [-u LOGIN] [-q QOS] [--nodes] [--arch] [--tres] | Focused squeue views: pending jobs with priority and reason, or running jobs with elapsed time and wall limit. -u and -q filter by user and by QOS (both repeatable); --nodes adds the allocated nodelist and --arch the node architecture (with --run); --tres adds each job's allocated resources and a TOTAL line that sums to the Used column of si --qos. With no mode flag sq passes straight through to squeue. Ordinary users see only their own jobs |
| sj JOBID | Show a single job's resource request and metadata: partition, QOS, node/task/CPU counts, memory, GPU request, constraints, time limit, and submit/start/end times |
| sjs JOBID [-r [SECONDS]] [--all-steps] | Live resource usage for a running job: accumulated CPU (and what fraction of the allocated cores that represents), peak memory against the request, and peak disk read/write — a quick check on whether a job is progressing or stuck; -r re-samples every 30 seconds and shows what changed; --all-steps includes the .batch and .extern steps. Accepts an array element (JOBID_64) or a whole array (JOBID). See Is my running job making progress? |
| sqos [LOGIN] [-v] [-m [QOS]] [-u] | Show QOS available to $USER or LOGIN, with allowed partitions and wallclock / CPU / GPU / memory / GRES limits; -v adds priority, flags, and the source associations. -m QOS inverts the question and reports who holds a QOS — the accounts granted it, or with -u one row per user; -m alone lists every QOS with member counts |