First calculation
Our goal on this page is to get a serial calculation to run on a compute node.
Note
For each example, the script and its Slurm job file must be in the same working directory before you submit.
Simple example to get started
If you are new to Slurm, start with this minimal Bash sanity check. It confirms that submission and output work before adding R, Python, C, or Fortran.
Simple Bash script (simple_bash.sh):
echo "hello from the bash script!"
Slurm script (simple_bash_job.sh) to run it on Saga:
#!/bin/bash
#SBATCH --account=<your-account>
#SBATCH --job-name=simple-bash
#SBATCH --partition=normal
#SBATCH --time=00:01:00
set -o errexit
set -o nounset
bash simple_bash.sh
Submit with:
$ sbatch simple_bash_job.sh
Now we continue with simple calculation examples in R, Python, C, and Fortran. For C and Fortran, we compile before execution. For simple examples, this can be done directly in the Slurm script.
# assumed to be simple.R
print("hello from the R script!")
# assumed to be simple.py
print("hello from the Python script!")
// assumed to be simple.c
#include <stdio.h>
printf("hello from the C script!\n");
return 0;
}
! assumed to be simple.f90
program simple
implicit none
print *, "hello from the Fortran script!"
end program simple
We can launch the R, Python, C, and Fortran examples on Saga with the
following job scripts.
Before submitting, adjust at least the line with --account to match your
allocation:
#!/bin/bash
#SBATCH --account=<your-account>
#SBATCH --job-name=example
#SBATCH --partition=normal
#SBATCH --mem=1G
#SBATCH --ntasks=1
#SBATCH --time=00:02:00
# it is good to have the following lines in any bash script
set -o errexit # make bash exit on any error
set -o nounset # treat unset variables as errors
module reset
module load R/4.2.1-foss-2022a
Rscript simple.R > simple.Rout
#!/bin/bash
#SBATCH --account=<your-account>
#SBATCH --job-name=example
#SBATCH --partition=normal
#SBATCH --mem=1G
#SBATCH --ntasks=1
#SBATCH --time=00:02:00
# it is good to have the following lines in any bash script
set -o errexit # make bash exit on any error
set -o nounset # treat unset variables as errors
module reset
module load Python/3.14.2-GCCcore-15.2.0
python simple.py
#!/bin/bash
#SBATCH --account=<your-account>
#SBATCH --job-name=example
#SBATCH --partition=normal
#SBATCH --mem=1G
#SBATCH --ntasks=1
#SBATCH --time=00:02:00
# it is good to have the following lines in any bash script
set -o errexit # make bash exit on any error
set -o nounset # treat unset variables as errors
module reset
module load foss/2022a
# compile and run inside the Slurm job
gcc -O2 simple.c -o simple_c
./simple_c > simple_c.out
#!/bin/bash
#SBATCH --account=<your-account>
#SBATCH --job-name=example
#SBATCH --partition=normal
#SBATCH --mem=1G
#SBATCH --ntasks=1
#SBATCH --time=00:02:00
# it is good to have the following lines in any bash script
set -o errexit # make bash exit on any error
set -o nounset # treat unset variables as errors
module reset
module load foss/2022a
# compile and run inside the Slurm job
gfortran -O2 simple.f90 -o simple_fortran
./simple_fortran > simple_fortran.out
Submit the example job scripts with:
$ sbatch <your_slurm_script>
Longer example
Here is a longer example that approximates pi using a Monte Carlo method. It runs 100 iterations, each throwing 2 million random points. This takes roughly 1 minute in R; C and Fortran will typically be faster.
The Python version uses NumPy, which runs array operations as compiled C code internally. This makes it faster than R here, and much faster than a plain Python loop would be. A pure Python implementation of the same calculation would be an order of magnitude slower than C or Fortran.
# assumed to be sequential.R
library(foreach)
# this function approximates pi by throwing random points into a square
# it is used here to demonstrate a function that takes a bit of time
approximate_pi <- function() {
# number of points to use
n <- 2000000
# generate n random points in the square
x <- runif(n, -1.0, 1.0)
y <- runif(n, -1.0, 1.0)
# count the number of points that are inside the circle
n_in <- sum(x^2 + y^2 < 1.0)
4 * n_in / n
}
foreach (i=1:100, .combine=c) %do% {
approximate_pi()
}
# assumed to be sequential.py
import numpy as np
def approximate_pi():
"""
Approximate pi by throwing random points in a unit square and
counting how many fall inside the unit circle.
Returns:
float: Approximation of pi.
"""
# Number of random points to generate
num_points = 2000000
# Generate random points in the square [-1, 1] x [-1, 1]
x = np.random.uniform(-1.0, 1.0, num_points)
y = np.random.uniform(-1.0, 1.0, num_points)
# Count how many points fall inside the unit circle
inside_circle = np.sum(x**2 + y**2 < 1)
# Approximate pi using the ratio of points inside the circle to total points
pi_approximation = (inside_circle / num_points) * 4
return pi_approximation
if __name__ == "__main__":
results = [approximate_pi() for _ in range(100)]
// assumed to be sequential.c
#include <stdio.h>
#include <time.h>
double approximate_pi(void) {
const int n = 2000000;
int n_in = 0;
for (int i = 0; i < n; i++) {
double x = (double)rand() / RAND_MAX * 2.0 - 1.0;
double y = (double)rand() / RAND_MAX * 2.0 - 1.0;
if (x * x + y * y < 1.0)
n_in++;
}
return 4.0 * n_in / n;
}
int main(void) {
srand(time(NULL));
for (int i = 0; i < 100; i++)
approximate_pi();
return 0;
}
! assumed to be sequential.f90
program sequential
implicit none
integer, parameter :: n = 2000000
integer :: i, j, n_in
real(8) :: x, y, pi
call random_seed()
do j = 1, 100
n_in = 0
do i = 1, n
call random_number(x)
call random_number(y)
x = x * 2.0d0 - 1.0d0
y = y * 2.0d0 - 1.0d0
if (x * x + y * y < 1.0d0) n_in = n_in + 1
end do
pi = 4.0d0 * n_in / n
end do
end program sequential
And the corresponding Slurm scripts.
Before submitting, adjust at least the line with --account to match your
allocation:
#!/bin/bash
#SBATCH --account=<your-account>
#SBATCH --job-name=example
#SBATCH --partition=normal
#SBATCH --mem=2G
#SBATCH --ntasks=1
#SBATCH --time=00:02:00
# it is good to have the following lines in any bash script
set -o errexit # make bash exit on any error
set -o nounset # treat unset variables as errors
module restore
module load R/4.2.1-foss-2022a
Rscript sequential.R > sequential.Rout
#!/bin/bash
#SBATCH --account=<your-account>
#SBATCH --job-name=example
#SBATCH --partition=normal
#SBATCH --mem=2G
#SBATCH --ntasks=1
#SBATCH --time=00:02:00
# it is good to have the following lines in any bash script
set -o errexit # make bash exit on any error
set -o nounset # treat unset variables as errors
module reset
module load Python/3.14.2-GCCcore-15.2.0
python sequential.py > sequential.pyout
#!/bin/bash
#SBATCH --account=<your-account>
#SBATCH --job-name=example
#SBATCH --partition=normal
#SBATCH --mem=2G
#SBATCH --ntasks=1
#SBATCH --time=00:02:00
# it is good to have the following lines in any bash script
set -o errexit # make bash exit on any error
set -o nounset # treat unset variables as errors
module reset
module load foss/2022a
gcc -O2 sequential.c -o sequential_c
./sequential_c > sequential_c.out
#!/bin/bash
#SBATCH --account=<your-account>
#SBATCH --job-name=example
#SBATCH --partition=normal
#SBATCH --mem=2G
#SBATCH --ntasks=1
#SBATCH --time=00:02:00
# it is good to have the following lines in any bash script
set -o errexit # make bash exit on any error
set -o nounset # treat unset variables as errors
module reset
module load foss/2022a
gfortran -O2 sequential.f90 -o sequential_fortran
./sequential_fortran > sequential_fortran.out
Next steps
R
To find available R modules:
module spider Rormodule spider bioconductorFor selecting the right module: Selecting the module to load
For installing additional R packages and running parallel R jobs: Installing R libraries
Python
Use
module spider Pythonto see available Python modulesConsider using containers to manage Python environments: Containers with GPU support
C and Fortran
For compiler options and optimization flags, see Compilers
For building more complex projects: Building scientific software