template<class S> class MPIslave { public: int nprocs, myid; vector<int> idle; /* list of waiting slaves, valid on master */ MPIslave(); ~MPIslave() {finalize();} void init(); void finalize(); MPIbuf& operator<<(void (S::*m)(MPIbuf&)) template <class T> MPIbuf& operator<<(const T& x); void exec(MPIbuf& x); MPIbuf& get_returnv(); void wait_all_idle(); void bcast(MPIbuf& c=cmd); };
MPIslave is an implementation of a master-slave application. An
MPIslave object must be created within an MPI parallel region (eg
created by MPISPMD). The slave
code is implemented as a class (S say), with each method
implementing a remote procedure
being of type void (MPIbuf&)
. Declaring a variable of type
MPIslave<S>
will set up an interpreter on the slave processor. The remote processes
are closed down once the variable is finalised, or goes out of scope.
See the file mandelbrot.cc in the mpi-examples for an example of how this works.
operator<<
is provided as a convenience -- one can compose a
message of the form:
MPIslave<S> slave; slave << &S::foo << x << send(1);without needing to declare additional MPIbufs.
For managing a list of idle slaves, the idle vector is employed, and is manipulated through the exec method, which dispatches a command to be executed on a slave, and the get_returnv() which returns the returned result as an MPIbuf, and places the processor from which it received a value back on the idle list. This technique is only valid for slave methods returning a message (even if its a null message). The wait_all_idle method waits for all slaves to return.
The bcast() method is a convenience method for sending the contents of MPISlave::cmd, or the optional MPIbuf argument to all slaves.