Your first real job¶
This guide picks up where the Quick Start left off. You already have an account, can connect via SSH, and have submitted a simple "hello world" job. Now we will walk through a more realistic workflow: understanding what each directive does, submitting a real computation, and learning how to check and improve your resource requests.
1. Prepare your workspace¶
All job I/O should happen on /scratch. Move there and create a directory for this tutorial:
cd /scratch/$USER
mkdir first-job && cd first-job
2. Write a batch script¶
Create a file called matrix.slurm with the following content:
#!/bin/bash
#SBATCH --job-name=matrix
#SBATCH --partition=general
#SBATCH --qos=test
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=4
#SBATCH --mem=4gb
#SBATCH --time=00:05:00
#SBATCH --output=%x.%j.out
#SBATCH --error=%x.%j.err
echo "Job started on $(hostname) at $(date)"
# Load Python (the system python does not include numpy)
module load Miniforge3
# Generate a random matrix and compute its eigenvalues
python3 -c "
import numpy as np
n = 2000
A = np.random.rand(n, n)
vals = np.linalg.eigvals(A)
print(f'Computed {len(vals)} eigenvalues of a {n}x{n} matrix')
print(f'Largest eigenvalue (magnitude): {np.max(np.abs(vals)):.4f}')
"
echo "Job finished at $(date)"
What each directive means¶
| Directive | What it does |
|---|---|
--job-name=matrix |
A human-readable name; appears in squeue and in output filenames |
--partition=general |
The pool of nodes to use (default on all clusters) |
--qos=test |
Quality of Service: test allows short jobs (max 10 min) with high priority, ideal for testing |
--nodes=1 |
Number of physical nodes |
--ntasks=1 |
Number of independent processes (MPI ranks). 1 for serial or pure OpenMP jobs |
--cpus-per-task=4 |
CPU cores assigned to each task. Useful for multithreaded programs |
--mem=4gb |
Total memory for the job. Overestimate at first, then refine |
--time=00:05:00 |
Maximum walltime. The job is killed if it exceeds this |
--output=%x.%j.out |
Stdout file. %x = job name, %j = job ID |
--error=%x.%j.err |
Stderr file |
Choosing a QoS
Use test while developing and debugging your scripts. Once your job works correctly, switch to regular, long, or xlong depending on how much time you need. See Partitions and QoS for limits.
3. Submit and monitor¶
Submit the job:
sbatch matrix.slurm
Submitted batch job 123456
Check its status:
squeue -u $USER
JOBID PARTITION NAME USER ST TIME NODES NODELIST
123456 general matrix username R 0:02 1 hyperion-101
The ST column shows the state: PD (pending, waiting for resources) or R (running).
4. Check the results¶
Once the job finishes, it disappears from squeue. View the output:
cat matrix.*.out
Job started on hyperion-101 at Thu Mar 7 10:00:00 CET 2026
Computed 2000 eigenvalues of a 2000x2000 matrix
Largest eigenvalue (magnitude): 1000.1234
Job finished at Thu Mar 7 10:00:12 CET 2026
If something went wrong, check the error file:
cat matrix.*.err
5. Evaluate efficiency¶
After a job completes, use seff to see how well your resource requests matched actual usage:
seff 123456
Job ID: 123456
State: COMPLETED
Cores: 4
CPU Utilized: 00:00:10
CPU Efficiency: 41.7% of 00:00:24 core-walltime
Memory Utilized: 312.00 MB
Memory Efficiency: 7.6% of 4.00 GB
Understanding the numbers¶
CPU Efficiency is the ratio of actual CPU time used to the total CPU time allocated. In this example, the job requested 4 cores for ~6 seconds of walltime, so the total allocation was 4 x 6 = 24 core-seconds. The program only used 10 core-seconds of that, hence 41.7%. This is normal for a short numpy script that does not fully parallelize across all cores.
Memory Efficiency is the ratio of peak memory used to the memory requested. Here, the job used 312 MB out of 4 GB (7.6%), meaning the request was far too generous.
What is a good efficiency?¶
There is no universal threshold, but as a rule of thumb:
| Metric | Good | Worth investigating |
|---|---|---|
| CPU Efficiency | > 70% | < 50% consistently |
| Memory Efficiency | > 30% | < 10% consistently |
Low efficiency on a single short test run is not a problem. But if your production jobs consistently show low efficiency, you are wasting resources and waiting longer in the queue than necessary.
What to do¶
| If you see... | Try... |
|---|---|
| Low CPU efficiency with multiple cores | Reduce --cpus-per-task. Your program may not use all the cores you requested |
| Low memory efficiency | Reduce --mem. In this example, --mem=1gb would be more than enough |
| High memory efficiency (> 90%) | Increase --mem slightly to avoid being killed by the OOM killer |
| CPU efficiency > 100% | This can happen with hyperthreading; it is not a problem |
Why this matters
Requesting more resources than you need does not make your job faster. It makes it wait longer in the queue (fewer nodes can satisfy the request) and blocks resources for other users. Always check seff on your first runs and adjust.
6. Iterate and scale up¶
Now that you have a working, tested script:
- Switch to a production QoS: replace
--qos=testwith--qos=regular(orlong/xlongfor longer jobs). - Adjust resources based on
seffoutput. - Load your real software with
module load(see Environment modules). - Replace the python example with your actual computation.
For common job patterns (MPI, OpenMP, hybrid, GPU), see the ready-made job templates.
What's next¶
-
SLURM reference
Full reference: all directives, templates, job arrays, dependencies, and more.
-
Batch script generator
Build a batch script interactively by selecting your resources.
-
GPU jobs
How to request and use GPUs on Hyperion and Atlas EDR.
-
Environment modules
Load pre-installed software (compilers, libraries, applications).
-
Scientific software
Application-specific guides (VASP, GROMACS, Gaussian, PyTorch, etc.).