123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- [section:skeleton_and_content Separating structure from content]
- When communicating data types over MPI that are not fundamental to MPI
- (such as strings, lists, and user-defined data types), Boost.MPI must
- first serialize these data types into a buffer and then communicate
- them; the receiver then copies the results into a buffer before
- deserializing into an object on the other end. For some data types,
- this overhead can be eliminated by using [classref
- boost::mpi::is_mpi_datatype `is_mpi_datatype`]. However,
- variable-length data types such as strings and lists cannot be MPI
- data types.
- Boost.MPI supports a second technique for improving performance by
- separating the structure of these variable-length data structures from
- the content stored in the data structures. This feature is only
- beneficial when the shape of the data structure remains the same but
- the content of the data structure will need to be communicated several
- times. For instance, in a finite element analysis the structure of the
- mesh may be fixed at the beginning of computation but the various
- variables on the cells of the mesh (temperature, stress, etc.) will be
- communicated many times within the iterative analysis process. In this
- case, Boost.MPI allows one to first send the "skeleton" of the mesh
- once, then transmit the "content" multiple times. Since the content
- need not contain any information about the structure of the data type,
- it can be transmitted without creating separate communication buffers.
- To illustrate the use of skeletons and content, we will take a
- somewhat more limited example wherein a master process generates
- random number sequences into a list and transmits them to several
- slave processes. The length of the list will be fixed at program
- startup, so the content of the list (i.e., the current sequence of
- numbers) can be transmitted efficiently. The complete example is
- available in `example/random_content.cpp`. We being with the master
- process (rank 0), which builds a list, communicates its structure via
- a [funcref boost::mpi::skeleton `skeleton`], then repeatedly
- generates random number sequences to be broadcast to the slave
- processes via [classref boost::mpi::content `content`]:
-
- // Generate the list and broadcast its structure
- std::list<int> l(list_len);
- broadcast(world, mpi::skeleton(l), 0);
- // Generate content several times and broadcast out that content
- mpi::content c = mpi::get_content(l);
- for (int i = 0; i < iterations; ++i) {
- // Generate new random values
- std::generate(l.begin(), l.end(), &random);
- // Broadcast the new content of l
- broadcast(world, c, 0);
- }
- // Notify the slaves that we're done by sending all zeroes
- std::fill(l.begin(), l.end(), 0);
- broadcast(world, c, 0);
- The slave processes have a very similar structure to the master. They
- receive (via the [funcref boost::mpi::broadcast
- `broadcast()`] call) the skeleton of the data structure, then use it
- to build their own lists of integers. In each iteration, they receive
- via another `broadcast()` the new content in the data structure and
- compute some property of the data:
- // Receive the content and build up our own list
- std::list<int> l;
- broadcast(world, mpi::skeleton(l), 0);
- mpi::content c = mpi::get_content(l);
- int i = 0;
- do {
- broadcast(world, c, 0);
- if (std::find_if
- (l.begin(), l.end(),
- std::bind1st(std::not_equal_to<int>(), 0)) == l.end())
- break;
- // Compute some property of the data.
- ++i;
- } while (true);
- The skeletons and content of any Serializable data type can be
- transmitted either via the [memberref
- boost::mpi::communicator::send `send`] and [memberref
- boost::mpi::communicator::recv `recv`] members of the
- [classref boost::mpi::communicator `communicator`] class
- (for point-to-point communicators) or broadcast via the [funcref
- boost::mpi::broadcast `broadcast()`] collective. When
- separating a data structure into a skeleton and content, be careful
- not to modify the data structure (either on the sender side or the
- receiver side) without transmitting the skeleton again. Boost.MPI can
- not detect these accidental modifications to the data structure, which
- will likely result in incorrect data being transmitted or unstable
- programs.
- [endsect:skeleton_and_content]
|