Job arrays¶
Job arrays let you submit many instances of the same job with a single sbatch command. Each instance gets a unique index in the $SLURM_ARRAY_TASK_ID variable, which you use to select the corresponding input file, parameter, or dataset. SLURM manages them as a single entity, so they are easier to monitor and cancel than hundreds of individual jobs.
Use job arrays when you need to:
- Run the same program on many input files
- Sweep a parameter space (one value per task)
- Process independent datasets in parallel
Basic syntax¶
#!/bin/bash
#SBATCH --qos=regular
#SBATCH --job-name=array_job
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=1
#SBATCH --mem=4gb
#SBATCH --time=01:00:00
#SBATCH --array=0-9
#SBATCH --output=%x-%A_%a.out
#SBATCH --error=%x-%A_%a.err
echo "Array task ID: ${SLURM_ARRAY_TASK_ID}"
./process_input input_${SLURM_ARRAY_TASK_ID}.dat
sbatch array_job.slurm
This submits 10 independent tasks (indexes 0 through 9). Each one runs the same script but with a different value of $SLURM_ARRAY_TASK_ID.
Info
job-arrays are limited to 10.000 tasks per-job and indexes must be lower than 4.000.000
Output filenames¶
Use %A (array job ID) and %a (task index) in --output and --error to get separate files per task:
| Pattern | Expands to |
|---|---|
%A |
Array parent job ID (same for all tasks) |
%a |
Task index (unique per task) |
%x |
Job name |
Example: --output=%x-%A_%a.out produces array_job-123456_0.out, array_job-123456_1.out, etc.
Index patterns¶
#SBATCH --array=1-100 # indexes 1 through 100
#SBATCH --array=1-100%10 # same, but max 10 running simultaneously
#SBATCH --array=0,3,7,15 # specific indexes
#SBATCH --array=1-20,50-60 # ranges can be combined
The %N throttle is useful to avoid flooding the scheduler or a shared filesystem with too many concurrent jobs.
Common use cases¶
One input file per task¶
The simplest case: your input files are numbered and each task processes one.
#SBATCH --array=1-50
./simulate input_${SLURM_ARRAY_TASK_ID}.dat
This requires files named input_1.dat, input_2.dat, ..., input_50.dat.
Reading parameters from a file¶
When your inputs are not numbered or you want to sweep parameters, list them in a text file and use sed to pick the right line:
0.01 100 alpha
0.05 200 beta
0.10 500 gamma
0.50 1000 delta
#!/bin/bash
#SBATCH --qos=regular
#SBATCH --job-name=sweep
#SBATCH --array=1-4
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=1
#SBATCH --mem=4gb
#SBATCH --time=02:00:00
#SBATCH --output=%x-%A_%a.out
#SBATCH --error=%x-%A_%a.err
# Read the line corresponding to this task (line 1 for task 1, etc.)
PARAMS=$(sed -n "${SLURM_ARRAY_TASK_ID}p" params.txt)
RATE=$(echo $PARAMS | awk '{print $1}')
STEPS=$(echo $PARAMS | awk '{print $2}')
LABEL=$(echo $PARAMS | awk '{print $3}')
echo "Running with rate=${RATE}, steps=${STEPS}, label=${LABEL}"
./my_program --rate ${RATE} --steps ${STEPS} --output result_${LABEL}.dat
Tip
Start the array at 1 (not 0) when reading from a file, since sed -n "1p" gives the first line.
Processing a list of files¶
When your files have arbitrary names, list them and index into the list:
/scratch/${USER}/data/sample_A.fasta
/scratch/${USER}/data/sample_B.fasta
/scratch/${USER}/data/sample_C.fasta
#!/bin/bash
#SBATCH --qos=regular
#SBATCH --job-name=process
#SBATCH --array=1-3
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=4
#SBATCH --mem=8gb
#SBATCH --time=04:00:00
#SBATCH --output=%x-%A_%a.out
#SBATCH --error=%x-%A_%a.err
INPUT=$(sed -n "${SLURM_ARRAY_TASK_ID}p" filelist.txt)
echo "Processing: ${INPUT}"
./analyze --threads ${SLURM_CPUS_PER_TASK} ${INPUT}
Managing job arrays¶
Monitoring¶
# All tasks in an array
squeue -j 123456
# Only pending tasks
squeue -j 123456 -t PENDING
Cancelling¶
# Cancel the entire array
scancel 123456
# Cancel a specific task
scancel 123456_5
# Cancel a range of tasks
scancel 123456_[10-20]
Resubmitting failed tasks¶
If some tasks fail, check which ones and resubmit only those:
# Find failed tasks
sacct -j 123456 --format=JobID,State | grep FAILED
123456_3 FAILED
123456_7 FAILED
# Resubmit only the failed indexes
sbatch --array=3,7 array_job.slurm
Combining arrays with dependencies¶
You can chain a post-processing job that runs after all array tasks complete:
$ sbatch array_job.slurm
Submitted batch job 123456
$ sbatch --dependency=afterok:123456 postprocess.slurm
Submitted batch job 123457
The postprocess.slurm job will start only after all tasks in the array finish successfully.
Tips¶
Use arrays instead of loops
If you find yourself writing a bash loop that calls sbatch many times, replace it with a job array. Arrays are lighter on the scheduler, easier to manage, and simpler to resubmit on failure.
Throttle concurrent tasks
Use --array=1-1000%50 to limit to 50 tasks running at once. This prevents overloading shared resources like filesystems or license servers.
Combine with local scratch
If each task does heavy I/O, use /lscratch inside the array job. See Local scratch for I/O-intensive jobs.