Design and Interface Overview
=============================

MPI for Python provides an object oriented approach to message
passing and is based in the MPI-2 C++ bindings. However, some
abstractions (like ``Port`` class) and functionalities (like sending
and receiving streams in ``Port`` instances) are added in order to
emulate OOMPI library interface.

The design is simple but effective. The MPI module consists of Python
code defining all constants, class hierarchies and functions. This
code calls simpler functions from extension modules written in C,
which provide access to native MPI-1/MPI-2 handles, constants and
function in the C side.

Following pyMPI and Pypar approaches, any Python object to be
transmitted is first serialized at sending processes using the
standard Python module ``cPickle``. After that, string data is
communicated (using ``MPI_CHAR`` datatype). Finally, received strings
are unpacked and the original objects are restored at the reciever
processes.

The pickling/unpickling appoach can impose important overheads in
memory as well as processor usage, specially in the case of
communication of objects containing big memory buffers, like long
strings or NumPy arrays. In latest releases, MPI for Python was
improved to support direct communication of any object exporting
single-segment buffer interface. This new feature, and the posibility
of constructing user-defined datatypes describing complicated memory
layouts, enables the implementation of many numerical applications
directly in Python with negligible overhead, almost as fast as
compiled C/C++/Fortran codes.

The interface was designed with focus in translating MPI syntax and
semantics of standard MPI-2 bindings for C++ to Python. Any user of
the standard C/C++ MPI bindings should be able to use this module
without need of learning a new interface.


Communicators
-------------

Class ``Comm`` is a base class for ``Intracomm`` and ``Intercomm``
classes.  Method ``Is_inter()`` (also ``Is_intra()``, nonstandard but
provided for convenience) is defined for communicator objects and can
be used to determine the particular communicator class.

Two predefined intracommunicators instances are available:
``COMM_WORLD`` and ``COMM_SELF`` (or ``WORLD`` and ``SELF``, provided
for convenience), which are in fact communicators obtained by
duplication of ``MPI_COMM_WORLD`` and ``MPI_COMM_SELF``. The original
predefined MPI communication domains can be accessed via
``__COMM_WORLD__`` and ``__COMM_SELF__`` instances, but this is
discouraged in order to avoid any message conflicts with other modules
calling MPI functions.

Communicator size and process rank can be respectively obtained with
``Get_size()`` and ``Get_rank()`` methods. Module constants ``rank``
and ``size`` are convenience shortcuts for ``COMM_WORLD.Get_rank()``
and ``COMM_WORLD.Get_size()``.

Communicator comparisons can be done with (static) method
``Compare()`` of ``Comm`` class, which returns a value in module
constants ``IDENT``, ``CONGRUENT``, ``SIMILAR`` or ``UNEQUAL``.

New communicator instances can be obtained with method ``Clone()`` of
``Comm`` objects, methods ``Dup()`` and ``Split()`` of both
``Intracomm`` and ``Intercomm`` objects, and methods
``Create_intercomm()`` and ``Merge()`` of ``Intracomm`` and
``Intercomm`` objects respectively. Set operations with ``Group``
objects like like ``Union()``, ``Intersect()`` and ``Difference()``
are fully supported, as well as the creation of new communicators from
groups.

Virtual topologies (``Cartcomm`` and ``Graphcomm`` classes, which are
derived from ``Intracomm`` class) are fully supported. New instances
can be obtained from intracommunicators with factory methods
``Create_cart()`` and ``Create_graph()`` of ``Intracomm`` class.

Point-to-Point Communications
+++++++++++++++++++++++++++++

Methods ``Send()``, ``Recv()`` and ``Sendrecv()`` of ``Comm`` class
provide support for blocking point-to-point communications.

Non-blocking communications are only supported for objects exporting
the single-segment buffer interface. ``Request`` instances are
returned by ``Isend()`` and ``Irecv()`` methods of ``Comm``
class. Persistent communications are also supported. ``Prequest``
instances are returned by ``Send_init()`` and ``Recv_init()`` methods
of ``Comm`` class.

Collective Communications
+++++++++++++++++++++++++

Methods ``Bcast()``, ``Scatter()``, ``Gather()``, ``Allgather()`` and
``Alltoall()`` of communicator objects provide support for collective
communications. Global reduction operations ``Reduce()``,
``Allreduce()``, ``Scan()`` and ``Exscan()`` are supported, but they
are naively implemented for reductions of general Python objects.



One-Sided Communications
------------------------

Class ``Win`` provides all the MPI-2 features for one-sided
communications (also known as *remote memory access (RMA)* ). Methods
``Put()``, ``Get()``, and ``Accumulate()`` can be used for remote
writes, reads, and reductions. All synchronization calls (fence,
active target, and lock) are fully supported.



I/O
---

Class ``File`` provides all the MPI-2 features for parallel
input/output. All data access operations, for all kind of positioning
(explicit offsets, individual file pointers, and shared file
pointers), synchronism (bloking, nonblocking, and split collective),
and coordination (noncollective and collective) are fully supported.



Environmental Management
------------------------

- *Initialization and Exit*

  Module functions ``Init()`` and ``Finalize()`` provide MPI
  initialization and exit respectively. Module functions
  ``Is_initialized()`` and ``Is_finalized()`` provide the respective
  tests for initialization and finalization.

- *Implementation Information*

     + The MPI version number can be retrieved from module
       function ``Get_version()``. It returns the tuple
       ``(version,subversion)``.

     + Communicator attributes are not currently
       supported. However, ``MPI_COMM_WORLD`` standard attributes
       can be accessed from module constants ``TAG_UB``,
       ``HOST``, ``IO`` and ``WTIME_IS_GLOBAL``.  Module function
       ``Get_processor_name()`` and module constant
       ``PROCESSOR_NAME`` can be used to access the processor
       name.

- *Timers*

  MPI timer functionality is available through module functions
  ``Wtime()`` and ``Wtick()``. Module constant
  ``WTIME_IS_GLOBAL`` indicates whether clocks at all processes
  in ``COMM_WORLD`` communicator are synchronized.

- *Error Handling*

  Error handling functionality is almost completely supported.  Errors
  originated in native MPI calls will throw an instance of the module
  exception class ``Exception``, which derives from standard Python
  exception ``RuntimeError``.

  In order facilitate communicator sharing with other Python modules
  interfacing MPI-based parallel libraries, default MPI error handlers
  ``ERRORS_RETURN``, ``ERRORS_ARE_FATAL`` can be assigned to and
  retrieved from communicators, windows and files with methods
  ``Set_errhandler()`` and ``Get_errhandler()``.

  .. caution:: Importing with ``from mpi4py.mpi import *`` will cause
   a name clashing with standard Python ``Exception`` base class.


Extensions
----------

MPI for Python adds some extensions to the standard MPI syntax. The
rationale is simplified usage and conformance with some Python idioms
and facilities.

An elegant abstraction for message-passing borrowed from OOMPI is
introduced: communicators can be seen as containers of *ports*}. A
port is a tiny object with references to a communication domain and a
process *id*. This *id* is used as source or destination process in
point-to-point communications, or root process in collective
communications.  Communicators can now be treated as container of
``Port`` instances and indexing/iteration can be defined for
them. Data streams can be messaged between ``Port`` instances
using ``<<`` and ``>>`` operators.

Accessors methods for different objects are mapped to *properties*,
i.e., managed attributes. For example, communicator rank and size of
``COMM_WORLD`` can be directly obtained with ``COMM_WORLD.rank`` and
``COMM_WORLD.size`` instead of calling ``Get_rank()`` and
``Get_size()`` methods.

Some constants are added for convenience.  Integers ``rank`` and
``size`` are shortcuts for the accessor methods ``Get_rank()`` and
``Get_size()`` of ``COMM_WORLD`` instance.  Booleans ``zero``,
``last``, ``even`` and ``odd`` have values related to process rank
in ``COMM_WORLD``.

There is also support for transparently passing any MPI objects to
other modules generated with SWIG.


Documentation
-------------

The standard Python on-line help mechanism will provide information
about module constants, classes and functions using their
documentation strings.
