1 // Copyright (C) 2005, 2006 Douglas Gregor <doug.gregor -at- gmail.com>.
3 // Use, modification and distribution is subject to the Boost Software
4 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
7 /** @file communicator.hpp
9 * This header defines the @c communicator class, which is the basis
10 * of all communication within Boost.MPI, and provides point-to-point
11 * communication operations.
13 #ifndef BOOST_MPI_COMMUNICATOR_HPP
14 #define BOOST_MPI_COMMUNICATOR_HPP
16 #include <boost/mpi/config.hpp>
17 #include <boost/mpi/exception.hpp>
18 #include <boost/optional.hpp>
19 #include <boost/shared_ptr.hpp>
20 #include <boost/mpi/datatype.hpp>
23 #include <stdexcept> // for std::range_error
25 // For (de-)serializing sends and receives
26 #include <boost/mpi/packed_oarchive.hpp>
27 #include <boost/mpi/packed_iarchive.hpp>
29 // For (de-)serializing skeletons and content
30 #include <boost/mpi/skeleton_and_content_fwd.hpp>
32 // For (de-)serializing arrays
33 #include <boost/serialization/array.hpp>
35 #include <boost/mpi/detail/point_to_point.hpp>
36 #include <boost/mpi/status.hpp>
37 #include <boost/mpi/request.hpp>
40 # pragma warning(push)
41 # pragma warning(disable : 4800) // forcing to bool 'true' or 'false'
44 namespace boost
{ namespace mpi
{
47 * @brief A constant representing "any process."
49 * This constant may be used for the @c source parameter of @c receive
50 * operations to indicate that a message may be received from any
53 const int any_source
= MPI_ANY_SOURCE
;
56 * @brief A constant representing "any tag."
58 * This constant may be used for the @c tag parameter of @c receive
59 * operations to indicate that a @c send with any tag will be matched
62 const int any_tag
= MPI_ANY_TAG
;
65 * @brief Enumeration used to describe how to adopt a C @c MPI_Comm into
66 * a Boost.MPI communicator.
68 * The values for this enumeration determine how a Boost.MPI
69 * communicator will behave when constructed with an MPI
70 * communicator. The options are:
72 * - @c comm_duplicate: Duplicate the MPI_Comm communicator to
73 * create a new communicator (e.g., with MPI_Comm_dup). This new
74 * MPI_Comm communicator will be automatically freed when the
75 * Boost.MPI communicator (and all copies of it) is destroyed.
77 * - @c comm_take_ownership: Take ownership of the communicator. It
78 * will be freed automatically when all of the Boost.MPI
79 * communicators go out of scope. This option must not be used with
82 * - @c comm_attach: The Boost.MPI communicator will reference the
83 * existing MPI communicator but will not free it when the Boost.MPI
84 * communicator goes out of scope. This option should only be used
85 * when the communicator is managed by the user or MPI library
86 * (e.g., MPI_COMM_WORLD).
88 enum comm_create_kind
{ comm_duplicate
, comm_take_ownership
, comm_attach
};
93 * Forward declaration of @c group needed for the @c group
94 * constructor and accessor.
101 * Forward declaration of @c intercommunicator needed for the "cast"
102 * from a communicator to an intercommunicator.
104 class intercommunicator
;
109 * Forward declaration of @c graph_communicator needed for the "cast"
110 * from a communicator to a graph communicator.
112 class graph_communicator
;
115 * @brief A communicator that permits communication and
116 * synchronization among a set of processes.
118 * The @c communicator class abstracts a set of communicating
119 * processes in MPI. All of the processes that belong to a certain
120 * communicator can determine the size of the communicator, their rank
121 * within the communicator, and communicate with any other processes
122 * in the communicator.
124 class BOOST_MPI_DECL communicator
128 * Build a new Boost.MPI communicator for @c MPI_COMM_WORLD.
130 * Constructs a Boost.MPI communicator that attaches to @c
131 * MPI_COMM_WORLD. This is the equivalent of constructing with
132 * @c (MPI_COMM_WORLD, comm_attach).
137 * Build a new Boost.MPI communicator based on the MPI communicator
140 * @p comm may be any valid MPI communicator. If @p comm is
141 * MPI_COMM_NULL, an empty communicator (that cannot be used for
142 * communication) is created and the @p kind parameter is
143 * ignored. Otherwise, the @p kind parameters determines how the
144 * Boost.MPI communicator will be related to @p comm:
146 * - If @p kind is @c comm_duplicate, duplicate @c comm to create
147 * a new communicator. This new communicator will be freed when
148 * the Boost.MPI communicator (and all copies of it) is destroyed.
149 * This option is only permitted if @p comm is a valid MPI
150 * intracommunicator or if the underlying MPI implementation
151 * supports MPI 2.0 (which supports duplication of
152 * intercommunicators).
154 * - If @p kind is @c comm_take_ownership, take ownership of @c
155 * comm. It will be freed automatically when all of the Boost.MPI
156 * communicators go out of scope. This option must not be used
157 * when @c comm is MPI_COMM_WORLD.
159 * - If @p kind is @c comm_attach, this Boost.MPI communicator
160 * will reference the existing MPI communicator @p comm but will
161 * not free @p comm when the Boost.MPI communicator goes out of
162 * scope. This option should only be used when the communicator is
163 * managed by the user or MPI library (e.g., MPI_COMM_WORLD).
165 communicator(const MPI_Comm
& comm
, comm_create_kind kind
);
168 * Build a new Boost.MPI communicator based on a subgroup of another
171 * This routine will construct a new communicator containing all of
172 * the processes from communicator @c comm that are listed within
173 * the group @c subgroup. Equivalent to @c MPI_Comm_create.
175 * @param comm An MPI communicator.
177 * @param subgroup A subgroup of the MPI communicator, @p comm, for
178 * which we will construct a new communicator.
180 communicator(const communicator
& comm
, const boost::mpi::group
& subgroup
);
183 * @brief Determine the rank of the executing process in a
186 * This routine is equivalent to @c MPI_Comm_rank.
188 * @returns The rank of the process in the communicator, which
189 * will be a value in [0, size())
194 * @brief Determine the number of processes in a communicator.
196 * This routine is equivalent to @c MPI_Comm_size.
198 * @returns The number of processes in the communicator.
203 * This routine constructs a new group whose members are the
204 * processes within this communicator. Equivalent to
205 * calling @c MPI_Comm_group.
207 boost::mpi::group
group() const;
209 // ----------------------------------------------------------------
210 // Point-to-point communication
211 // ----------------------------------------------------------------
214 * @brief Send data to another process.
216 * This routine executes a potentially blocking send with tag @p tag
217 * to the process with rank @p dest. It can be received by the
218 * destination process with a matching @c recv call.
220 * The given @p value must be suitable for transmission over
221 * MPI. There are several classes of types that meet these
224 * - Types with mappings to MPI data types: If @c
225 * is_mpi_datatype<T> is convertible to @c mpl::true_, then @p
226 * value will be transmitted using the MPI data type
227 * @c get_mpi_datatype<T>(). All primitive C++ data types that have
228 * MPI equivalents, e.g., @c int, @c float, @c char, @c double,
229 * etc., have built-in mappings to MPI data types. You may turn a
230 * Serializable type with fixed structure into an MPI data type by
231 * specializing @c is_mpi_datatype for your type.
233 * - Serializable types: Any type that provides the @c serialize()
234 * functionality required by the Boost.Serialization library can be
235 * transmitted and received.
237 * - Packed archives and skeletons: Data that has been packed into
238 * an @c mpi::packed_oarchive or the skeletons of data that have
239 * been backed into an @c mpi::packed_skeleton_oarchive can be
240 * transmitted, but will be received as @c mpi::packed_iarchive and
241 * @c mpi::packed_skeleton_iarchive, respectively, to allow the
242 * values (or skeletons) to be extracted by the destination process.
244 * - Content: Content associated with a previously-transmitted
245 * skeleton can be transmitted by @c send and received by @c
246 * recv. The receiving process may only receive content into the
247 * content of a value that has been constructed with the matching
250 * For types that have mappings to an MPI data type (including the
251 * concent of a type), an invocation of this routine will result in
252 * a single MPI_Send call. For variable-length data, e.g.,
253 * serialized types and packed archives, two messages will be sent
254 * via MPI_Send: one containing the length of the data and the
255 * second containing the data itself. Note that the transmission
256 * mode for variable-length data is an implementation detail that
257 * is subject to change.
259 * @param dest The rank of the remote process to which the data
262 * @param tag The tag that will be associated with this message. Tags
263 * may be any integer between zero and an implementation-defined
264 * upper limit. This limit is accessible via @c environment::max_tag().
266 * @param value The value that will be transmitted to the
267 * receiver. The type @c T of this value must meet the aforementioned
268 * criteria for transmission.
271 void send(int dest
, int tag
, const T
& value
) const;
274 * @brief Send the skeleton of an object.
276 * This routine executes a potentially blocking send with tag @p
277 * tag to the process with rank @p dest. It can be received by the
278 * destination process with a matching @c recv call. This variation
279 * on @c send will be used when a send of a skeleton is explicitly
280 * requested via code such as:
283 * comm.send(dest, tag, skeleton(object));
286 * The semantics of this routine are equivalent to that of sending
287 * a @c packed_skeleton_oarchive storing the skeleton of the @c
290 * @param dest The rank of the remote process to which the skeleton
293 * @param tag The tag that will be associated with this message. Tags
294 * may be any integer between zero and an implementation-defined
295 * upper limit. This limit is accessible via @c environment::max_tag().
297 * @param proxy The @c skeleton_proxy containing a reference to the
298 * object whose skeleton will be transmitted.
302 void send(int dest
, int tag
, const skeleton_proxy
<T
>& proxy
) const;
305 * @brief Send an array of values to another process.
307 * This routine executes a potentially blocking send of an array of
308 * data with tag @p tag to the process with rank @p dest. It can be
309 * received by the destination process with a matching array @c
312 * If @c T is an MPI datatype, an invocation of this routine will
313 * be mapped to a single call to MPI_Send, using the datatype @c
314 * get_mpi_datatype<T>().
316 * @param dest The process rank of the remote process to which
317 * the data will be sent.
319 * @param tag The tag that will be associated with this message. Tags
320 * may be any integer between zero and an implementation-defined
321 * upper limit. This limit is accessible via @c environment::max_tag().
323 * @param values The array of values that will be transmitted to the
324 * receiver. The type @c T of these values must be mapped to an MPI
327 * @param n The number of values stored in the array. The destination
328 * process must call receive with at least this many elements to
329 * correctly receive the message.
332 void send(int dest
, int tag
, const T
* values
, int n
) const;
335 * @brief Send a message to another process without any data.
337 * This routine executes a potentially blocking send of a message
338 * to another process. The message contains no extra data, and can
339 * therefore only be received by a matching call to @c recv().
341 * @param dest The process rank of the remote process to which
342 * the message will be sent.
344 * @param tag The tag that will be associated with this message. Tags
345 * may be any integer between zero and an implementation-defined
346 * upper limit. This limit is accessible via @c environment::max_tag().
349 void send(int dest
, int tag
) const;
352 * @brief Receive data from a remote process.
354 * This routine blocks until it receives a message from the process @p
355 * source with the given @p tag. The type @c T of the @p value must be
356 * suitable for transmission over MPI, which includes serializable
357 * types, types that can be mapped to MPI data types (including most
358 * built-in C++ types), packed MPI archives, skeletons, and content
359 * associated with skeletons; see the documentation of @c send for a
360 * complete description.
362 * @param source The process that will be sending data. This will
363 * either be a process rank within the communicator or the
364 * constant @c any_source, indicating that we can receive the
365 * message from any process.
367 * @param tag The tag that matches a particular kind of message sent
368 * by the source process. This may be any tag value permitted by @c
369 * send. Alternatively, the argument may be the constant @c any_tag,
370 * indicating that this receive matches a message with any tag.
372 * @param value Will contain the value of the message after a
373 * successful receive. The type of this value must match the value
374 * transmitted by the sender, unless the sender transmitted a packed
375 * archive or skeleton: in these cases, the sender transmits a @c
376 * packed_oarchive or @c packed_skeleton_oarchive and the
377 * destination receives a @c packed_iarchive or @c
378 * packed_skeleton_iarchive, respectively.
380 * @returns Information about the received message.
383 status
recv(int source
, int tag
, T
& value
) const;
386 * @brief Receive a skeleton from a remote process.
388 * This routine blocks until it receives a message from the process @p
389 * source with the given @p tag containing a skeleton.
391 * @param source The process that will be sending data. This will
392 * either be a process rank within the communicator or the constant
393 * @c any_source, indicating that we can receive the message from
396 * @param tag The tag that matches a particular kind of message
397 * sent by the source process. This may be any tag value permitted
398 * by @c send. Alternatively, the argument may be the constant @c
399 * any_tag, indicating that this receive matches a message with any
402 * @param proxy The @c skeleton_proxy containing a reference to the
403 * object that will be reshaped to match the received skeleton.
405 * @returns Information about the received message.
408 status
recv(int source
, int tag
, const skeleton_proxy
<T
>& proxy
) const;
411 * @brief Receive a skeleton from a remote process.
413 * This routine blocks until it receives a message from the process @p
414 * source with the given @p tag containing a skeleton.
416 * @param source The process that will be sending data. This will
417 * either be a process rank within the communicator or the constant
418 * @c any_source, indicating that we can receive the message from
421 * @param tag The tag that matches a particular kind of message
422 * sent by the source process. This may be any tag value permitted
423 * by @c send. Alternatively, the argument may be the constant @c
424 * any_tag, indicating that this receive matches a message with any
427 * @param proxy The @c skeleton_proxy containing a reference to the
428 * object that will be reshaped to match the received skeleton.
430 * @returns Information about the received message.
433 status
recv(int source
, int tag
, skeleton_proxy
<T
>& proxy
) const;
436 * @brief Receive an array of values from a remote process.
438 * This routine blocks until it receives an array of values from the
439 * process @p source with the given @p tag. If the type @c T is
441 * @param source The process that will be sending data. This will
442 * either be a process rank within the communicator or the
443 * constant @c any_source, indicating that we can receive the
444 * message from any process.
446 * @param tag The tag that matches a particular kind of message sent
447 * by the source process. This may be any tag value permitted by @c
448 * send. Alternatively, the argument may be the constant @c any_tag,
449 * indicating that this receive matches a message with any tag.
451 * @param values Will contain the values in the message after a
452 * successful receive. The type of these elements must match the
453 * type of the elements transmitted by the sender.
455 * @param n The number of values that can be stored into the @p
456 * values array. This shall not be smaller than the number of
457 * elements transmitted by the sender.
459 * @throws std::range_error if the message to be received contains
460 * more than @p n values.
462 * @returns Information about the received message.
465 status
recv(int source
, int tag
, T
* values
, int n
) const;
468 * @brief Receive a message from a remote process without any data.
470 * This routine blocks until it receives a message from the process
471 * @p source with the given @p tag.
473 * @param source The process that will be sending the message. This
474 * will either be a process rank within the communicator or the
475 * constant @c any_source, indicating that we can receive the
476 * message from any process.
478 * @param tag The tag that matches a particular kind of message
479 * sent by the source process. This may be any tag value permitted
480 * by @c send. Alternatively, the argument may be the constant @c
481 * any_tag, indicating that this receive matches a message with any
484 * @returns Information about the received message.
486 status
recv(int source
, int tag
) const;
489 * @brief Send a message to a remote process without blocking.
491 * The @c isend method is functionality identical to the @c send
492 * method and transmits data in the same way, except that @c isend
493 * will not block while waiting for the data to be
494 * transmitted. Instead, a request object will be immediately
495 * returned, allowing one to query the status of the communication
496 * or wait until it has completed.
498 * @param dest The rank of the remote process to which the data
501 * @param tag The tag that will be associated with this message. Tags
502 * may be any integer between zero and an implementation-defined
503 * upper limit. This limit is accessible via @c environment::max_tag().
505 * @param value The value that will be transmitted to the
506 * receiver. The type @c T of this value must meet the aforementioned
507 * criteria for transmission.
509 * @returns a @c request object that describes this communication.
512 request
isend(int dest
, int tag
, const T
& value
) const;
515 * @brief Send the skeleton of an object without blocking.
517 * This routine is functionally identical to the @c send method for
518 * @c skeleton_proxy objects except that @c isend will not block
519 * while waiting for the data to be transmitted. Instead, a request
520 * object will be immediately returned, allowing one to query the
521 * status of the communication or wait until it has completed.
523 * The semantics of this routine are equivalent to a non-blocking
524 * send of a @c packed_skeleton_oarchive storing the skeleton of
527 * @param dest The rank of the remote process to which the skeleton
530 * @param tag The tag that will be associated with this message. Tags
531 * may be any integer between zero and an implementation-defined
532 * upper limit. This limit is accessible via @c environment::max_tag().
534 * @param proxy The @c skeleton_proxy containing a reference to the
535 * object whose skeleton will be transmitted.
537 * @returns a @c request object that describes this communication.
540 request
isend(int dest
, int tag
, const skeleton_proxy
<T
>& proxy
) const;
543 * @brief Send an array of values to another process without
546 * This routine is functionally identical to the @c send method for
547 * arrays except that @c isend will not block while waiting for the
548 * data to be transmitted. Instead, a request object will be
549 * immediately returned, allowing one to query the status of the
550 * communication or wait until it has completed.
552 * @param dest The process rank of the remote process to which
553 * the data will be sent.
555 * @param tag The tag that will be associated with this message. Tags
556 * may be any integer between zero and an implementation-defined
557 * upper limit. This limit is accessible via @c environment::max_tag().
559 * @param values The array of values that will be transmitted to the
560 * receiver. The type @c T of these values must be mapped to an MPI
563 * @param n The number of values stored in the array. The destination
564 * process must call receive with at least this many elements to
565 * correctly receive the message.
567 * @returns a @c request object that describes this communication.
570 request
isend(int dest
, int tag
, const T
* values
, int n
) const;
573 * @brief Send a message to another process without any data
576 * This routine is functionally identical to the @c send method for
577 * sends with no data, except that @c isend will not block while
578 * waiting for the message to be transmitted. Instead, a request
579 * object will be immediately returned, allowing one to query the
580 * status of the communication or wait until it has completed.
582 * @param dest The process rank of the remote process to which
583 * the message will be sent.
585 * @param tag The tag that will be associated with this message. Tags
586 * may be any integer between zero and an implementation-defined
587 * upper limit. This limit is accessible via @c environment::max_tag().
590 * @returns a @c request object that describes this communication.
592 request
isend(int dest
, int tag
) const;
595 * @brief Prepare to receive a message from a remote process.
597 * The @c irecv method is functionally identical to the @c recv
598 * method and receive data in the same way, except that @c irecv
599 * will not block while waiting for data to be
600 * transmitted. Instead, it immediately returns a request object
601 * that allows one to query the status of the receive or wait until
604 * @param source The process that will be sending data. This will
605 * either be a process rank within the communicator or the
606 * constant @c any_source, indicating that we can receive the
607 * message from any process.
609 * @param tag The tag that matches a particular kind of message sent
610 * by the source process. This may be any tag value permitted by @c
611 * send. Alternatively, the argument may be the constant @c any_tag,
612 * indicating that this receive matches a message with any tag.
614 * @param value Will contain the value of the message after a
615 * successful receive. The type of this value must match the value
616 * transmitted by the sender, unless the sender transmitted a packed
617 * archive or skeleton: in these cases, the sender transmits a @c
618 * packed_oarchive or @c packed_skeleton_oarchive and the
619 * destination receives a @c packed_iarchive or @c
620 * packed_skeleton_iarchive, respectively.
622 * @returns a @c request object that describes this communication.
625 request
irecv(int source
, int tag
, T
& value
) const;
628 * @brief Initiate receipt of an array of values from a remote process.
630 * This routine initiates a receive operation for an array of values
631 * transmitted by process @p source with the given @p tag.
633 * @param source The process that will be sending data. This will
634 * either be a process rank within the communicator or the
635 * constant @c any_source, indicating that we can receive the
636 * message from any process.
638 * @param tag The tag that matches a particular kind of message sent
639 * by the source process. This may be any tag value permitted by @c
640 * send. Alternatively, the argument may be the constant @c any_tag,
641 * indicating that this receive matches a message with any tag.
643 * @param values Will contain the values in the message after a
644 * successful receive. The type of these elements must match the
645 * type of the elements transmitted by the sender.
647 * @param n The number of values that can be stored into the @p
648 * values array. This shall not be smaller than the number of
649 * elements transmitted by the sender.
651 * @returns a @c request object that describes this communication.
654 request
irecv(int source
, int tag
, T
* values
, int n
) const;
657 * @brief Initiate receipt of a message from a remote process that
660 * This routine initiates a receive operation for a message from
661 * process @p source with the given @p tag that carries no data.
663 * @param source The process that will be sending the message. This
664 * will either be a process rank within the communicator or the
665 * constant @c any_source, indicating that we can receive the
666 * message from any process.
668 * @param tag The tag that matches a particular kind of message
669 * sent by the source process. This may be any tag value permitted
670 * by @c send. Alternatively, the argument may be the constant @c
671 * any_tag, indicating that this receive matches a message with any
674 * @returns a @c request object that describes this communication.
676 request
irecv(int source
, int tag
) const;
679 * @brief Waits until a message is available to be received.
681 * This operation waits until a message matching (@p source, @p tag)
682 * is available to be received. It then returns information about
683 * that message. The functionality is equivalent to @c MPI_Probe. To
684 * check if a message is available without blocking, use @c iprobe.
686 * @param source Determine if there is a message available from
687 * this rank. If @c any_source, then the message returned may come
690 * @param tag Determine if there is a message available with the
691 * given tag. If @c any_tag, then the message returned may have any
694 * @returns Returns information about the first message that
695 * matches the given criteria.
697 status
probe(int source
= any_source
, int tag
= any_tag
) const;
700 * @brief Determine if a message is available to be received.
702 * This operation determines if a message matching (@p source, @p
703 * tag) is available to be received. If so, it returns information
704 * about that message; otherwise, it returns immediately with an
705 * empty optional. The functionality is equivalent to @c
706 * MPI_Iprobe. To wait until a message is available, use @c wait.
708 * @param source Determine if there is a message available from
709 * this rank. If @c any_source, then the message returned may come
712 * @param tag Determine if there is a message available with the
713 * given tag. If @c any_tag, then the message returned may have any
716 * @returns If a matching message is available, returns
717 * information about that message. Otherwise, returns an empty
718 * @c boost::optional.
721 iprobe(int source
= any_source
, int tag
= any_tag
) const;
724 // Linux defines a function-like macro named "barrier". So, we need
725 // to avoid expanding the macro when we define our barrier()
726 // function. However, some C++ parsers (Doxygen, for instance) can't
727 // handle this syntax, so we only use it when necessary.
728 void (barrier
)() const;
731 * @brief Wait for all processes within a communicator to reach the
734 * This routine is a collective operation that blocks each process
735 * until all processes have entered it, then releases all of the
736 * processes "simultaneously". It is equivalent to @c MPI_Barrier.
738 void barrier() const;
741 /** @brief Determine if this communicator is valid for
744 * Evaluates @c true in a boolean context if this communicator is
745 * valid for communication, i.e., does not represent
746 * MPI_COMM_NULL. Otherwise, evaluates @c false.
748 operator bool() const { return (bool)comm_ptr
; }
751 * @brief Access the MPI communicator associated with a Boost.MPI
754 * This routine permits the implicit conversion from a Boost.MPI
755 * communicator to an MPI communicator.
757 * @returns The associated MPI communicator.
759 operator MPI_Comm() const;
762 * Split the communicator into multiple, disjoint communicators
763 * each of which is based on a particular color. This is a
764 * collective operation that returns a new communicator that is a
765 * subgroup of @p this. This routine is functionally equivalent to
768 * @param color The color of this process. All processes with the
769 * same @p color value will be placed into the same group.
771 * @returns A new communicator containing all of the processes in
772 * @p this that have the same @p color.
774 communicator
split(int color
) const;
777 * Split the communicator into multiple, disjoint communicators
778 * each of which is based on a particular color. This is a
779 * collective operation that returns a new communicator that is a
780 * subgroup of @p this. This routine is functionally equivalent to
783 * @param color The color of this process. All processes with the
784 * same @p color value will be placed into the same group.
786 * @param key A key value that will be used to determine the
787 * ordering of processes with the same color in the resulting
788 * communicator. If omitted, the rank of the processes in @p this
789 * will determine the ordering of processes in the resulting
792 * @returns A new communicator containing all of the processes in
793 * @p this that have the same @p color.
795 communicator
split(int color
, int key
) const;
798 * Determine if the communicator is in fact an intercommunicator
799 * and, if so, return that intercommunicator.
801 * @returns an @c optional containing the intercommunicator, if this
802 * communicator is in fact an intercommunicator. Otherwise, returns
803 * an empty @c optional.
805 optional
<intercommunicator
> as_intercommunicator() const;
808 * Determine if the communicator has a graph topology and, if so,
809 * return that @c graph_communicator. Even though the communicators
810 * have different types, they refer to the same underlying
811 * communication space and can be used interchangeably for
814 * @returns an @c optional containing the graph communicator, if this
815 * communicator does in fact have a graph topology. Otherwise, returns
816 * an empty @c optional.
818 optional
<graph_communicator
> as_graph_communicator() const;
821 * Determines whether this communicator has a Cartesian topology.
823 bool has_cartesian_topology() const;
826 template<typename Extents
>
828 with_cartesian_topology(const Extents
& extents
,
829 bool periodic
= false,
830 bool reorder
= false) const;
832 template<typename DimInputIterator
, typename PeriodicInputIterator
>
834 with_cartesian_topology(DimInputIterator first_dim
,
835 DimInputIterator last_dim
,
836 PeriodicInputIterator first_periodic
,
837 bool reorder
= false);
839 template<typename Allocator
, std::size_t NumDims
>
841 with_cartesian_topology(const multi_array
<bool, NumDims
, Allocator
>& periods
,
842 bool reorder
= false);
845 /** Abort all tasks in the group of this communicator.
847 * Makes a "best attempt" to abort all of the tasks in the group of
848 * this communicator. Depending on the underlying MPI
849 * implementation, this may either abort the entire program (and
850 * possibly return @p errcode to the environment) or only abort
851 * some processes, allowing the others to continue. Consult the
852 * documentation for your MPI implementation. This is equivalent to
853 * a call to @c MPI_Abort
855 * @param errcode The error code to return from aborted processes.
856 * @returns Will not return.
858 void abort(int errcode
) const;
864 * Function object that frees an MPI communicator and deletes the
865 * memory associated with it. Intended to be used as a deleter with
870 void operator()(MPI_Comm
* comm
) const
873 BOOST_MPI_CHECK_RESULT(MPI_Finalized
, (&finalized
));
875 BOOST_MPI_CHECK_RESULT(MPI_Comm_free
, (comm
));
884 * We're sending a type that has an associated MPI datatype, so we
885 * map directly to that datatype.
888 void send_impl(int dest
, int tag
, const T
& value
, mpl::true_
) const;
893 * We're sending a type that does not have an associated MPI
894 * datatype, so it must be serialized then sent as MPI_PACKED data,
895 * to be deserialized on the receiver side.
898 void send_impl(int dest
, int tag
, const T
& value
, mpl::false_
) const;
903 * We're sending an array of a type that has an associated MPI
904 * datatype, so we map directly to that datatype.
908 array_send_impl(int dest
, int tag
, const T
* values
, int n
, mpl::true_
) const;
913 * We're sending an array of a type that does not have an associated
914 * MPI datatype, so it must be serialized then sent as MPI_PACKED
915 * data, to be deserialized on the receiver side.
919 array_send_impl(int dest
, int tag
, const T
* values
, int n
,
925 * We're sending a type that has an associated MPI datatype, so we
926 * map directly to that datatype.
929 request
isend_impl(int dest
, int tag
, const T
& value
, mpl::true_
) const;
934 * We're sending a type that does not have an associated MPI
935 * datatype, so it must be serialized then sent as MPI_PACKED data,
936 * to be deserialized on the receiver side.
939 request
isend_impl(int dest
, int tag
, const T
& value
, mpl::false_
) const;
944 * We're sending an array of a type that has an associated MPI
945 * datatype, so we map directly to that datatype.
949 array_isend_impl(int dest
, int tag
, const T
* values
, int n
,
955 * We're sending an array of a type that does not have an associated
956 * MPI datatype, so it must be serialized then sent as MPI_PACKED
957 * data, to be deserialized on the receiver side.
961 array_isend_impl(int dest
, int tag
, const T
* values
, int n
,
967 * We're receiving a type that has an associated MPI datatype, so we
968 * map directly to that datatype.
971 status
recv_impl(int source
, int tag
, T
& value
, mpl::true_
) const;
976 * We're receiving a type that does not have an associated MPI
977 * datatype, so it must have been serialized then sent as
978 * MPI_PACKED. We'll receive it and then deserialize.
981 status
recv_impl(int source
, int tag
, T
& value
, mpl::false_
) const;
986 * We're receiving an array of a type that has an associated MPI
987 * datatype, so we map directly to that datatype.
991 array_recv_impl(int source
, int tag
, T
* values
, int n
, mpl::true_
) const;
996 * We're receiving a type that does not have an associated MPI
997 * datatype, so it must have been serialized then sent as
998 * MPI_PACKED. We'll receive it and then deserialize.
1000 template<typename T
>
1002 array_recv_impl(int source
, int tag
, T
* values
, int n
, mpl::false_
) const;
1007 * We're receiving a type that has an associated MPI datatype, so we
1008 * map directly to that datatype.
1010 template<typename T
>
1011 request
irecv_impl(int source
, int tag
, T
& value
, mpl::true_
) const;
1016 * We're receiving a type that does not have an associated MPI
1017 * datatype, so it must have been serialized then sent as
1018 * MPI_PACKED. We'll receive it and then deserialize.
1020 template<typename T
>
1021 request
irecv_impl(int source
, int tag
, T
& value
, mpl::false_
) const;
1026 * We're receiving a type that has an associated MPI datatype, so we
1027 * map directly to that datatype.
1029 template<typename T
>
1031 array_irecv_impl(int source
, int tag
, T
* values
, int n
, mpl::true_
) const;
1036 * We're receiving a type that does not have an associated MPI
1037 * datatype, so it must have been serialized then sent as
1038 * MPI_PACKED. We'll receive it and then deserialize.
1040 template<typename T
>
1042 array_irecv_impl(int source
, int tag
, T
* values
, int n
, mpl::false_
) const;
1044 shared_ptr
<MPI_Comm
> comm_ptr
;
1048 * @brief Determines whether two communicators are identical.
1050 * Equivalent to calling @c MPI_Comm_compare and checking whether the
1051 * result is @c MPI_IDENT.
1053 * @returns True when the two communicators refer to the same
1054 * underlying MPI communicator.
1056 BOOST_MPI_DECL
bool operator==(const communicator
& comm1
, const communicator
& comm2
);
1059 * @brief Determines whether two communicators are different.
1061 * @returns @c !(comm1 == comm2)
1063 inline bool operator!=(const communicator
& comm1
, const communicator
& comm2
)
1065 return !(comm1
== comm2
);
1069 /************************************************************************
1070 * Implementation details *
1071 ************************************************************************/
1072 // Count elements in a message
1073 template<typename T
>
1074 inline optional
<int> status::count() const
1076 return count_impl
<T
>(is_mpi_datatype
<T
>());
1079 template<typename T
>
1080 optional
<int> status::count_impl(mpl::true_
) const
1086 BOOST_MPI_CHECK_RESULT(MPI_Get_count
,
1087 (&m_status
, get_mpi_datatype
<T
>(T()), &return_value
));
1088 if (return_value
== MPI_UNDEFINED
)
1089 return optional
<int>();
1091 /* Cache the result. */
1092 return m_count
= return_value
;
1095 template<typename T
>
1096 inline optional
<int> status::count_impl(mpl::false_
) const
1099 return optional
<int>();
1104 // We're sending a type that has an associated MPI datatype, so we
1105 // map directly to that datatype.
1106 template<typename T
>
1108 communicator::send_impl(int dest
, int tag
, const T
& value
, mpl::true_
) const
1110 BOOST_MPI_CHECK_RESULT(MPI_Send
,
1111 (const_cast<T
*>(&value
), 1, get_mpi_datatype
<T
>(value
),
1112 dest
, tag
, MPI_Comm(*this)));
1115 // We're sending a type that does not have an associated MPI
1116 // datatype, so it must be serialized then sent as MPI_PACKED data,
1117 // to be deserialized on the receiver side.
1118 template<typename T
>
1120 communicator::send_impl(int dest
, int tag
, const T
& value
, mpl::false_
) const
1122 packed_oarchive
oa(*this);
1124 send(dest
, tag
, oa
);
1127 // Single-element receive may either send the element directly or
1128 // serialize it via a buffer.
1129 template<typename T
>
1130 void communicator::send(int dest
, int tag
, const T
& value
) const
1132 this->send_impl(dest
, tag
, value
, is_mpi_datatype
<T
>());
1135 // We're sending an array of a type that has an associated MPI
1136 // datatype, so we map directly to that datatype.
1137 template<typename T
>
1139 communicator::array_send_impl(int dest
, int tag
, const T
* values
, int n
,
1142 BOOST_MPI_CHECK_RESULT(MPI_Send
,
1143 (const_cast<T
*>(values
), n
,
1144 get_mpi_datatype
<T
>(*values
),
1145 dest
, tag
, MPI_Comm(*this)));
1148 // We're sending an array of a type that does not have an associated
1149 // MPI datatype, so it must be serialized then sent as MPI_PACKED
1150 // data, to be deserialized on the receiver side.
1151 template<typename T
>
1153 communicator::array_send_impl(int dest
, int tag
, const T
* values
, int n
,
1156 packed_oarchive
oa(*this);
1157 oa
<< n
<< boost::serialization::make_array(values
, n
);
1158 send(dest
, tag
, oa
);
1161 // Array send must send the elements directly
1162 template<typename T
>
1163 void communicator::send(int dest
, int tag
, const T
* values
, int n
) const
1165 this->array_send_impl(dest
, tag
, values
, n
, is_mpi_datatype
<T
>());
1168 // We're receiving a type that has an associated MPI datatype, so we
1169 // map directly to that datatype.
1170 template<typename T
>
1171 status
communicator::recv_impl(int source
, int tag
, T
& value
, mpl::true_
) const
1175 BOOST_MPI_CHECK_RESULT(MPI_Recv
,
1176 (const_cast<T
*>(&value
), 1,
1177 get_mpi_datatype
<T
>(value
),
1178 source
, tag
, MPI_Comm(*this), &stat
.m_status
));
1182 template<typename T
>
1184 communicator::recv_impl(int source
, int tag
, T
& value
, mpl::false_
) const
1186 // Receive the message
1187 packed_iarchive
ia(*this);
1188 status stat
= recv(source
, tag
, ia
);
1190 // Deserialize the data in the message
1196 // Single-element receive may either receive the element directly or
1197 // deserialize it from a buffer.
1198 template<typename T
>
1199 status
communicator::recv(int source
, int tag
, T
& value
) const
1201 return this->recv_impl(source
, tag
, value
, is_mpi_datatype
<T
>());
1204 template<typename T
>
1206 communicator::array_recv_impl(int source
, int tag
, T
* values
, int n
,
1210 BOOST_MPI_CHECK_RESULT(MPI_Recv
,
1211 (const_cast<T
*>(values
), n
,
1212 get_mpi_datatype
<T
>(*values
),
1213 source
, tag
, MPI_Comm(*this), &stat
.m_status
));
1217 template<typename T
>
1219 communicator::array_recv_impl(int source
, int tag
, T
* values
, int n
,
1222 // Receive the message
1223 packed_iarchive
ia(*this);
1224 status stat
= recv(source
, tag
, ia
);
1226 // Determine how much data we are going to receive
1230 // Deserialize the data in the message
1231 boost::serialization::array
<T
> arr(values
, count
> n
? n
: count
);
1235 boost::throw_exception(
1236 std::range_error("communicator::recv: message receive overflow"));
1239 stat
.m_count
= count
;
1243 // Array receive must receive the elements directly into a buffer.
1244 template<typename T
>
1245 status
communicator::recv(int source
, int tag
, T
* values
, int n
) const
1247 return this->array_recv_impl(source
, tag
, values
, n
, is_mpi_datatype
<T
>());
1250 // We're sending a type that has an associated MPI datatype, so we
1251 // map directly to that datatype.
1252 template<typename T
>
1254 communicator::isend_impl(int dest
, int tag
, const T
& value
, mpl::true_
) const
1257 BOOST_MPI_CHECK_RESULT(MPI_Isend
,
1258 (const_cast<T
*>(&value
), 1,
1259 get_mpi_datatype
<T
>(value
),
1260 dest
, tag
, MPI_Comm(*this), &req
.m_requests
[0]));
1264 // We're sending a type that does not have an associated MPI
1265 // datatype, so it must be serialized then sent as MPI_PACKED data,
1266 // to be deserialized on the receiver side.
1267 template<typename T
>
1269 communicator::isend_impl(int dest
, int tag
, const T
& value
, mpl::false_
) const
1271 shared_ptr
<packed_oarchive
> archive(new packed_oarchive(*this));
1273 request result
= isend(dest
, tag
, *archive
);
1274 result
.m_data
= archive
;
1278 // Single-element receive may either send the element directly or
1279 // serialize it via a buffer.
1280 template<typename T
>
1281 request
communicator::isend(int dest
, int tag
, const T
& value
) const
1283 return this->isend_impl(dest
, tag
, value
, is_mpi_datatype
<T
>());
1286 template<typename T
>
1288 communicator::array_isend_impl(int dest
, int tag
, const T
* values
, int n
,
1292 BOOST_MPI_CHECK_RESULT(MPI_Isend
,
1293 (const_cast<T
*>(values
), n
,
1294 get_mpi_datatype
<T
>(*values
),
1295 dest
, tag
, MPI_Comm(*this), &req
.m_requests
[0]));
1299 template<typename T
>
1301 communicator::array_isend_impl(int dest
, int tag
, const T
* values
, int n
,
1304 shared_ptr
<packed_oarchive
> archive(new packed_oarchive(*this));
1305 *archive
<< n
<< boost::serialization::make_array(values
, n
);
1306 request result
= isend(dest
, tag
, *archive
);
1307 result
.m_data
= archive
;
1312 // Array isend must send the elements directly
1313 template<typename T
>
1314 request
communicator::isend(int dest
, int tag
, const T
* values
, int n
) const
1316 return array_isend_impl(dest
, tag
, values
, n
, is_mpi_datatype
<T
>());
1321 * Internal data structure that stores everything required to manage
1322 * the receipt of serialized data via a request object.
1324 template<typename T
>
1325 struct serialized_irecv_data
1327 serialized_irecv_data(const communicator
& comm
, int source
, int tag
,
1329 : comm(comm
), source(source
), tag(tag
), ia(comm
), value(value
)
1333 void deserialize(status
& stat
)
1348 struct serialized_irecv_data
<packed_iarchive
>
1350 serialized_irecv_data(const communicator
& comm
, int source
, int tag
,
1351 packed_iarchive
& ia
)
1352 : comm(comm
), source(source
), tag(tag
), ia(ia
) { }
1354 void deserialize(status
&) { /* Do nothing. */ }
1360 packed_iarchive
& ia
;
1364 * Internal data structure that stores everything required to manage
1365 * the receipt of an array of serialized data via a request object.
1367 template<typename T
>
1368 struct serialized_array_irecv_data
1370 serialized_array_irecv_data(const communicator
& comm
, int source
, int tag
,
1372 : comm(comm
), source(source
), tag(tag
), ia(comm
), values(values
), n(n
)
1376 void deserialize(status
& stat
);
1387 template<typename T
>
1388 void serialized_array_irecv_data
<T
>::deserialize(status
& stat
)
1390 // Determine how much data we are going to receive
1394 // Deserialize the data in the message
1395 boost::serialization::array
<T
> arr(values
, count
> n
? n
: count
);
1399 boost::throw_exception(
1400 std::range_error("communicator::recv: message receive overflow"));
1403 stat
.m_count
= count
;
1407 template<typename T
>
1409 request::handle_serialized_irecv(request
* self
, request_action action
)
1411 typedef detail::serialized_irecv_data
<T
> data_t
;
1412 shared_ptr
<data_t
> data
= static_pointer_cast
<data_t
>(self
->m_data
);
1414 if (action
== ra_wait
) {
1416 if (self
->m_requests
[1] == MPI_REQUEST_NULL
) {
1417 // Wait for the count message to complete
1418 BOOST_MPI_CHECK_RESULT(MPI_Wait
,
1419 (self
->m_requests
, &stat
.m_status
));
1420 // Resize our buffer and get ready to receive its data
1421 data
->ia
.resize(data
->count
);
1422 BOOST_MPI_CHECK_RESULT(MPI_Irecv
,
1423 (data
->ia
.address(), data
->ia
.size(), MPI_PACKED
,
1424 stat
.source(), stat
.tag(),
1425 MPI_Comm(data
->comm
), self
->m_requests
+ 1));
1428 // Wait until we have received the entire message
1429 BOOST_MPI_CHECK_RESULT(MPI_Wait
,
1430 (self
->m_requests
+ 1, &stat
.m_status
));
1432 data
->deserialize(stat
);
1434 } else if (action
== ra_test
) {
1438 if (self
->m_requests
[1] == MPI_REQUEST_NULL
) {
1439 // Check if the count message has completed
1440 BOOST_MPI_CHECK_RESULT(MPI_Test
,
1441 (self
->m_requests
, &flag
, &stat
.m_status
));
1443 // Resize our buffer and get ready to receive its data
1444 data
->ia
.resize(data
->count
);
1445 BOOST_MPI_CHECK_RESULT(MPI_Irecv
,
1446 (data
->ia
.address(), data
->ia
.size(),MPI_PACKED
,
1447 stat
.source(), stat
.tag(),
1448 MPI_Comm(data
->comm
), self
->m_requests
+ 1));
1450 return optional
<status
>(); // We have not finished yet
1453 // Check if we have received the message data
1454 BOOST_MPI_CHECK_RESULT(MPI_Test
,
1455 (self
->m_requests
+ 1, &flag
, &stat
.m_status
));
1457 data
->deserialize(stat
);
1460 return optional
<status
>();
1462 return optional
<status
>();
1466 template<typename T
>
1468 request::handle_serialized_array_irecv(request
* self
, request_action action
)
1470 typedef detail::serialized_array_irecv_data
<T
> data_t
;
1471 shared_ptr
<data_t
> data
= static_pointer_cast
<data_t
>(self
->m_data
);
1473 if (action
== ra_wait
) {
1475 if (self
->m_requests
[1] == MPI_REQUEST_NULL
) {
1476 // Wait for the count message to complete
1477 BOOST_MPI_CHECK_RESULT(MPI_Wait
,
1478 (self
->m_requests
, &stat
.m_status
));
1479 // Resize our buffer and get ready to receive its data
1480 data
->ia
.resize(data
->count
);
1481 BOOST_MPI_CHECK_RESULT(MPI_Irecv
,
1482 (data
->ia
.address(), data
->ia
.size(), MPI_PACKED
,
1483 stat
.source(), stat
.tag(),
1484 MPI_Comm(data
->comm
), self
->m_requests
+ 1));
1487 // Wait until we have received the entire message
1488 BOOST_MPI_CHECK_RESULT(MPI_Wait
,
1489 (self
->m_requests
+ 1, &stat
.m_status
));
1491 data
->deserialize(stat
);
1493 } else if (action
== ra_test
) {
1497 if (self
->m_requests
[1] == MPI_REQUEST_NULL
) {
1498 // Check if the count message has completed
1499 BOOST_MPI_CHECK_RESULT(MPI_Test
,
1500 (self
->m_requests
, &flag
, &stat
.m_status
));
1502 // Resize our buffer and get ready to receive its data
1503 data
->ia
.resize(data
->count
);
1504 BOOST_MPI_CHECK_RESULT(MPI_Irecv
,
1505 (data
->ia
.address(), data
->ia
.size(),MPI_PACKED
,
1506 stat
.source(), stat
.tag(),
1507 MPI_Comm(data
->comm
), self
->m_requests
+ 1));
1509 return optional
<status
>(); // We have not finished yet
1512 // Check if we have received the message data
1513 BOOST_MPI_CHECK_RESULT(MPI_Test
,
1514 (self
->m_requests
+ 1, &flag
, &stat
.m_status
));
1516 data
->deserialize(stat
);
1519 return optional
<status
>();
1521 return optional
<status
>();
1525 // We're receiving a type that has an associated MPI datatype, so we
1526 // map directly to that datatype.
1527 template<typename T
>
1529 communicator::irecv_impl(int source
, int tag
, T
& value
, mpl::true_
) const
1532 BOOST_MPI_CHECK_RESULT(MPI_Irecv
,
1533 (const_cast<T
*>(&value
), 1,
1534 get_mpi_datatype
<T
>(value
),
1535 source
, tag
, MPI_Comm(*this), &req
.m_requests
[0]));
1539 template<typename T
>
1541 communicator::irecv_impl(int source
, int tag
, T
& value
, mpl::false_
) const
1543 typedef detail::serialized_irecv_data
<T
> data_t
;
1544 shared_ptr
<data_t
> data(new data_t(*this, source
, tag
, value
));
1547 req
.m_handler
= request::handle_serialized_irecv
<T
>;
1549 BOOST_MPI_CHECK_RESULT(MPI_Irecv
,
1551 get_mpi_datatype
<std::size_t>(data
->count
),
1552 source
, tag
, MPI_Comm(*this), &req
.m_requests
[0]));
1557 template<typename T
>
1559 communicator::irecv(int source
, int tag
, T
& value
) const
1561 return this->irecv_impl(source
, tag
, value
, is_mpi_datatype
<T
>());
1564 template<typename T
>
1566 communicator::array_irecv_impl(int source
, int tag
, T
* values
, int n
,
1570 BOOST_MPI_CHECK_RESULT(MPI_Irecv
,
1571 (const_cast<T
*>(values
), n
,
1572 get_mpi_datatype
<T
>(*values
),
1573 source
, tag
, MPI_Comm(*this), &req
.m_requests
[0]));
1577 template<typename T
>
1579 communicator::array_irecv_impl(int source
, int tag
, T
* values
, int n
,
1582 typedef detail::serialized_array_irecv_data
<T
> data_t
;
1583 shared_ptr
<data_t
> data(new data_t(*this, source
, tag
, values
, n
));
1586 req
.m_handler
= request::handle_serialized_array_irecv
<T
>;
1588 BOOST_MPI_CHECK_RESULT(MPI_Irecv
,
1590 get_mpi_datatype
<std::size_t>(data
->count
),
1591 source
, tag
, MPI_Comm(*this), &req
.m_requests
[0]));
1597 // Array receive must receive the elements directly into a buffer.
1598 template<typename T
>
1599 request
communicator::irecv(int source
, int tag
, T
* values
, int n
) const
1601 return this->array_irecv_impl(source
, tag
, values
, n
, is_mpi_datatype
<T
>());
1609 communicator::send
<packed_oarchive
>(int dest
, int tag
,
1610 const packed_oarchive
& ar
) const;
1617 communicator::send
<packed_skeleton_oarchive
>
1618 (int dest
, int tag
, const packed_skeleton_oarchive
& ar
) const;
1625 communicator::send
<content
>(int dest
, int tag
, const content
& c
) const;
1631 BOOST_MPI_DECL status
1632 communicator::recv
<packed_iarchive
>(int source
, int tag
,
1633 packed_iarchive
& ar
) const;
1639 BOOST_MPI_DECL status
1640 communicator::recv
<packed_skeleton_iarchive
>
1641 (int source
, int tag
, packed_skeleton_iarchive
& ar
) const;
1647 BOOST_MPI_DECL status
1648 communicator::recv
<const content
>(int source
, int tag
,
1649 const content
& c
) const;
1656 communicator::recv
<content
>(int source
, int tag
,
1659 return recv
<const content
>(source
,tag
,c
);
1666 BOOST_MPI_DECL request
1667 communicator::isend
<packed_oarchive
>(int dest
, int tag
,
1668 const packed_oarchive
& ar
) const;
1674 BOOST_MPI_DECL request
1675 communicator::isend
<packed_skeleton_oarchive
>
1676 (int dest
, int tag
, const packed_skeleton_oarchive
& ar
) const;
1682 BOOST_MPI_DECL request
1683 communicator::isend
<content
>(int dest
, int tag
, const content
& c
) const;
1689 BOOST_MPI_DECL request
1690 communicator::irecv
<packed_skeleton_iarchive
>
1691 (int source
, int tag
, packed_skeleton_iarchive
& ar
) const;
1697 BOOST_MPI_DECL request
1698 communicator::irecv
<const content
>(int source
, int tag
,
1699 const content
& c
) const;
1706 communicator::irecv
<content
>(int source
, int tag
,
1709 return irecv
<const content
>(source
, tag
, c
);
1713 } } // end namespace boost::mpi
1715 // If the user has already included skeleton_and_content.hpp, include
1716 // the code to send/receive skeletons and content.
1717 #ifdef BOOST_MPI_SKELETON_AND_CONTENT_HPP
1718 # include <boost/mpi/detail/communicator_sc.hpp>
1722 # pragma warning(pop)
1725 #endif // BOOST_MPI_COMMUNICATOR_HPP