MPI#

Often, a parallel algorithm requires moving data between the engines. One way is to push and pull over the DirectView. However, this is slow because all of the data has to get through the controller to the client and then back to the final destination.

A much better option is to use the Message Passing Interface (MPI). IPython’s parallel computing architecture was designed from the ground up to integrate with MPI. This notebook gives a brief introduction to using MPI with IPython.

Requirements#

  • A standard MPI implementation like OpenMPI or MPICH.

    For Debian/Ubuntu these can be installed with

    $ sudo apt install openmpi-bin
    

    or

    $ sudo apt install mpich
    

    Alternatively, OpenMPI or MPICH can also be installed with Spack: the packages are openmpi or mpich.

  • mpi4py

Starting the engines with activated MPI#

Automatic start with mpiexec and ipcluster#

This can be done with, for example

$ pipenv run ipcluster start -n 4 --profile=mpi

For this, however, a corresponding profile must first be created; see configuration.

Automatic start with PBS and ipcluster#

The ipcluster command also offers integration in PBS. You can find more information about this in Starting IPython Parallel on a traditional cluster.

Example#

The following notebook cell calls psum.py with the following content:

from mpi4py import MPI
import numpy as np

def psum(a):
    locsum = np.sum(a)
    rcvBuf = np.array(0.0,'d')
    MPI.COMM_WORLD.Allreduce([locsum, MPI.DOUBLE],
        [rcvBuf, MPI.DOUBLE],
        op=MPI.SUM)
    return rcvBuf
[1]:
import ipyparallel as ipp

c = ipp.Client(profile='mpi')
view = c[:]
view.activate()
view.run('psum.py')
view.scatter('a',np.arange(16,dtype='float'))
view['a']
[1]:
[array([0., 1., 2., 3.]),
 array([4., 5., 6., 7.]),
 array([ 8.,  9., 10., 11.]),
 array([12., 13., 14., 15.])]
[2]:
%px totalsum = psum(a)
[2]:
Parallel execution on engines: [0,1,2,3]
[3]:
view['totalsum']
[3]:
[120.0, 120.0, 120.0, 120.0]