UA Research Computing

HPC Examples

Python Multiprocessing

Overview

The Python multiprocessing package is a popular way to distribute a workflow over multiple CPUs on a single node. In this example, we’ll be spreading 1000 processes over multiple CPUs using a pool of workers. The example will be submitted multiple times with varying numbers of CPUs allocated to each workflow to demonstrate the speedup. This workflow is an example of an embarrassingly parallel calculation.

For more information on the multiprocessing package, see the Python documentation.

Python Script

#!/usr/bin/env python3

import os, time
from multiprocessing import Pool

num_cpus=int(os.environ["SLURM_CPUS_ON_NODE"])
print("Running a pool with %s workers"%num_cpus)

def f(x):
    # The sleep will allow us to get a sense of the speedup given by using multiprocessing
    time.sleep(1)
    return x*x

if __name__=="__main__":
    with Pool(num_cpus) as p:
        data = range(1,1000)
        # p.map takes an interable, maps it onto a function, and executes the processes
        # distributed over the allocated CPUs using the pool of workers
        output = p.map(f,data)

Submission Script

#!/bin/bash
#SBATCH --job-name=Sample_Multiprocessing
### Stick to 1 task for python multiprocessing and request
### CPUs using the --cpus-per-task option
#SBATCH --ntasks=1
### Set cpus-per-task below to the number of processes 
#SBATCH --cpus-per-task=1
#SBATCH --nodes=1             
#SBATCH --time=05:00:00   
#SBATCH --partition=standard
#SBATCH --account=YOUR_GROUP

module load python/3.6
time python3 multiprocess.py

Submitting the Job and Output

For this example, we’ll submit the job a few times with different CPU allocations to get an idea of the speedup we get from using multiprocessing

In each case below, the submission script has been modified to set --cpus-per-task=N where N is the number of CPUs allocated to the job.

One CPU

[netid@wentletrap ~]$ sbatch -o 1-process.out submit.slurm
Submitted batch job 2104919
[netid@wentletrap ~]$ cat 1-process.out 
Running a pool with 1 workers

real	16m40.404s
user	0m0.340s
sys	0m0.134s

Five CPUs

[netid@wentletrap ~]$ sbatch -o 5-processes.out submit.slurm 
Submitted batch job 2104965
[netid@wentletrap ~]$ cat 5-processes.out 
Running a pool with 5 workers

real	3m20.701s
user	0m0.131s
sys	0m0.075s

Twenty CPUs

[netid@wentletrap ~]$ sbatch -o 20-processes.out submit.slurm 
Submitted batch job 2104966
[netid@wentletrap ~]$ cat 20-processes.out 
Running a pool with 20 workers

real	0m52.485s
user	0m0.108s
sys	0m0.091s