pupyMPI is a pure python MPI implementation for educational use. This document does not in any way try to explain general MPI concepts, but it merely a reference manual to pupyMPI.
pupyMPI requires python version 2.6 or later, due to some process management tool in the subprocess module. It’s not tested with python 3.
You should ensure pupyMPI is in your PYTHONPATH, which can be done like:
export PYTHONPATH=/path/to/pupympi/:$PYTHONPATH
Some installations do not have Python 2.6 as the global default Python installation. You can verify this by doing this after the command line:
ssh localhost python -V
In case it is not, find the path to Python 2.6 and remember it:
which python2.6
You will need to tell pupyMPI where to find Python2.6, and you’ll do this by adding the parameter --remote-python=path_to_python2.6 to mpirun.py
You also need SSH access to one or more hosts. This may just be localhost, as long as you’re just testing. SSH must have been set up to allow direct access (see http://linuxproblem.org/art_9.html).
You might already be familiar with MPI for C or FORTRAN. However, pupyMPI differs from a C/FORTRAN implementation in several different regards. The most important are:
Create a file called pupympi_test1.py and add the following code to it:
from mpi import MPI
mpi = MPI()
if mpi.MPI_COMM_WORLD.rank() == 0:
mpi.MPI_COMM_WORLD.send(1, "Hello World!")
else:
message = mpi.MPI_COMM_WORLD.recv(0)
print message
mpi.finalize()
From the command line, run mpirun -c 2 pupympi_test1.py.You should receive the message: “Hello World!” If you did not you might have run into one of these problems:
- pupyMPI complains about a Python version problem You probably need to be explicit about your Python, as mentioned above. You’ll also probably have to kill stuck Python processes by killall python (or killall Python)
- Command not found Make sure pupyMPI is in your PYTHONPATH. It should be installed as an egg or module. It is also possible to start pupyMPI by cd’ing to the root directory and try this instead PYTHONPATH=. bin/mpirun -c 2 /path/to/pupympi_test1.py
- SSH password prompt Ensure password-less access
- No message appears and your script hangs ctrl-c, kill all Python processes and use the -d parameter in addition to the others. You will get a metric ton of output.
The above test example introduce the MPI_COMM_WORLD communicator holding all the started processes.
Unlike the previous example it’s possible to filter which type of message you want to receive based on a tag. A very simple example:
from mpi import MPI
from mpi.constants import MPI_SOURCE_ANY
mpi = MPI()
world = mpi.MPI_COMM_WORLD
rank = world.rank()
RECEIVER = 2
if rank == 0:
TAG = 1
world.send(RECEIVER, "Hello World from 0!", tag=TAG)
elif rank == 1:
TAG = 2
world.send(RECEIVER, "Hello World from 1!", tag=TAG)
elif rank == 2:
FIRST_TAG = 1
SECOND_TAG = 2
msg1 = world.recv(MPI_SOURCE_ANY, tag=FIRST_TAG)
msg2 = world.recv(MPI_SOURCE_ANY, tag=SECOND_TAG)
print msg1
print msg2
else:
# disregard other processes
pass
mpi.finalize()
The above example will always print the message from rank 0 before the one from rank 1. The first recv call will accept messages from any rank, but only with the correct tag. This is a very usefull way to group data and let different subsystems handle it.
When you specify tags they should all be possitive integers. The internal MPI system use negative integers as tags so they are in principle allowed, but the behaviour of the system if you mix negative tags with anythin else than the normal recv and send is undefined.
There exist a special tag called MPI_TAG_ANY that will match any other tag.