Please note: This documentation is very dated and should be treated as an old draft. Among the major updates as of 8/2005 are a jump from version .6 to .8, the renaming of staging to launcher.

Tutorial II: Pyre Binding

After learning about properties and how they fit into your Pyre application, the next step is to attach an existing code to the Pyre framework. As a nontrivial example, you will walk through the steps required to run a parallel application, hello.py, on several processors which will each respond with something like “Hello, I am node 1 of 16.” To do so involves binding Pyre to the message passing interface standard, MPI, so applications will communicate and run in parallel on multiple processors.

Support for Concurrent Applications

Python can drive concurrent applications that are embarrassingly parallel and have custom communication strategies, such as sockets, ICE, and shared memory. It also provides excellent support for MPI. Pyre supports MPI with mpipython.exe, an MPI-enabled interpreter--needed only on some platforms--which is included in the MPI package.

The mpi package contains Python bindings for MPI. Those include support for staging and launching, communicator and processor group manipulation, and support for exchanging Python objects among processors. Pyre also works with mpi.Application that provides support for launching and staging MPI applications. It is a descendant of pyre.application. Application and features auto-detection of parallelism, is fully configurable at runtime, and can be used as a base class for user-defined application classes.

Enabling parallelism in Python is implemented by embedding the interpreter in an MPI application, constructing an extension module with bindings for MPI, and providing an object-oriented veneer for easy access. Instead of deriving from the normal application you have to derive from a different object, namely the class application in the MPI package.

Example 4.6. Parallel Python

int main(int argc, char **argv) {
    int status = MPI_Init(&argc, &argv);
    if (status != MPI_SUCCESS) {
	std::cerr << argv[0] 
            << ": MPI_Init failed! Exiting ..." << std::endl;
	return status;
    }
    status = Py_Main(argc, argv);
    MPI_Finalize();
    return status;
}

Example 4.7. Access to MPI through Pyre

import mpi

# get the world communicator
world = mpi.world()

# compute processor rank in MPI_COMM_WORLD
rank = world.rank

# create a new communicator
new = world.include([0])
if new:
    print “world: %d, new: %d” % (rank, new.rank)
else:
    print “world: %d (excluded from new)” % rank

Tip

world.include([0])creates a new communicator by manipulating the communicator group

Example 4.8. Parallel hello.py

from mpi.Application import Application

class HelloApp(Application):

    def run(self):
        import mpi
        world = mpi.world()
        print "[%03d/%03d] Hello world" % (world.rank, world.size)
        return

    def __init__(self):
        Application.__init__(self, "hello")
        return

# main
if __name__ == "__main__":
    app = HelloApp()
    app.main()

Tip

mpi.Applicationaccesses the new base class.