Parallel
If you want to run code in parallel, HPC is perfect, as you have a lot of resource available, to efficiently scale your work!
Important
The software or code you are using has to be capable to run in parallel. Not every software can do that and code has to be specifically written for it!
Automatic scaling from Slurm allocation
Some programs, will try to use all CPU a node (server) has available, when trying to run in parallel, but depending on your submission, you won't always have all CPUs per server available.
If you want to easily adjust your parallel program, to spawn processes based on your submission, you can do that using Slurm environment variables, set in every submission.
| Variable | Explanation |
|---|---|
SLURM_NNODES |
Amount of nodes (servers) your job is running on. |
SLURM_CPUS_ON_NODE |
Amount of CPU available per node (server). |
SLURM_NTASKS |
Amount of tasks available per server (server). |
Here an example with a simple parallel processing python script. The script creates eight processes that each sleep for four seconds:
import multiprocessing
import time
import os
slurm_threads = os.environ['SLURM_CPUS_ON_NODE']
data = ('A','B','C','D','E','F','G','H')
def sleeper(id):
print("Processs %s started" % id)
time.sleep(4)
print("Process %s finished" % id)
def mp_handler():
pool = multiprocessing.Pool(int(slurm_threads))
pool.map(sleeper, data)
if __name__ == '__main__':
mp_handler()
By saving the value of the environment variable SLURM_CPUS_ON_NODE into the python variable slurm_threads, we won't need to touch our python script anymore to upscale our work, but rather just adjust our submission.
This run will take 32 seconds:
This run will take 8 seconds:
This run will take 4 seconds:
OpenMPI Example
The example source code is written in C below and saved to a file called hello_mpi.c:
#include <stdio.h>
#include <mpi.h>
#include <unistd.h>
int main (int argc, char *argv[])
{
int threadid,totalthreads;
char hostname[80];
// Start MPI processes on each node
MPI_Init(&argc,&argv);
// Get thread ID from the MPI master process
MPI_Comm_rank(MPI_COMM_WORLD, &threadid);
// Get the number of processes launched by MPI
MPI_Comm_size(MPI_COMM_WORLD, &totalthreads);
// Get the hostname from the node running the task
gethostname(hostname,80);
// Print a statement to standard output
printf("Hello from process %i on machine %s, of %i processes\n", threadid, hostname, totalthreads);
MPI_Finalize();
return 0;
}
Compile the code above into an executable called hello_mpi:
You can now write a submission script to run your MPI program hello_mpi over multiple nodes. First you can copy a template from here and adjust as described below.
Adjust the --nodes to 2 to run the job across two servers and the --ntasks-per-node to 4 to spawn four processes per node, so eight in total. MPI will automatically spawn as many processes, as tasks are available in the allocation.
Run the program compiled with the mpirun utility:
Your output file will contain something like this:
Hello from process 0 on machine node001, of 8 processes
Hello from process 1 on machine node001, of 8 processes
Hello from process 2 on machine node001, of 8 processes
Hello from process 3 on machine node001, of 8 processes
Hello from process 6 on machine node002, of 8 processes
Hello from process 7 on machine node002, of 8 processes
Hello from process 4 on machine node002, of 8 processes
Hello from process 5 on machine node002, of 8 processes