TIMPI
Public Types | Public Member Functions | List of all members
libMesh::Parallel::Communicator Class Reference

#include <communicator.h>

Inheritance diagram for libMesh::Parallel::Communicator:
[legend]

Public Types

enum  SendMode { DEFAULT =0, SYNCHRONOUS }
 Whether to use default or synchronous sends? More...
 
enum  SyncType { NBX, ALLTOALL_COUNTS, SENDRECEIVE }
 What algorithm to use for parallel synchronization? More...
 

Public Member Functions

 Communicator ()=default
 
 Communicator (const TIMPI::communicator &comm)
 
 Communicator (const Communicator &)=delete
 
Communicatoroperator= (const Communicator &)=delete
 
 Communicator (Communicator &&)=default
 
Communicatoroperator= (Communicator &&)=default
 
 ~Communicator ()=default
 
void split (int color, int key, Communicator &target) const
 
void split_by_type (int split_type, int key, info i, Communicator &target) const
 
void duplicate (const Communicator &comm)
 
void duplicate (const communicator &comm)
 
communicator & get ()
 
const communicator & get () const
 
MessageTag get_unique_tag (int tagvalue=MessageTag::invalid_tag) const
 Get a tag that is unique to this Communicator. More...
 
void reference_unique_tag (int tagvalue) const
 Reference an already-acquired tag, so that we know it will be dereferenced multiple times before we can re-release it. More...
 
void dereference_unique_tag (int tagvalue) const
 Dereference an already-acquired tag, and see if we can re-release it. More...
 
void clear ()
 Free and reset this communicator. More...
 
processor_id_type rank () const
 
processor_id_type size () const
 
constexpr processor_id_type size () const
 
void send_mode (const SendMode sm)
 Explicitly sets the SendMode type used for send operations. More...
 
SendMode send_mode () const
 Gets the user-requested SendMode. More...
 
void sync_type (const SyncType st)
 Explicitly sets the SyncType used for sync operations. More...
 
void sync_type (const std::string &st)
 Sets the sync type used for sync operations via a string. More...
 
SyncType sync_type () const
 Gets the user-requested SyncType. More...
 
void barrier () const
 Pause execution until all processors reach a certain point. More...
 
void nonblocking_barrier (Request &req) const
 Start a barrier that doesn't block. More...
 
template<typename T >
timpi_pure bool verify (const T &r) const
 Check whether a local variable has the same value on all processors, returning true if it does or false if not. More...
 
template<typename T >
bool verify (const T &r) const
 
template<typename T >
timpi_pure bool semiverify (const T *r) const
 Check whether a local pointer points to the same value on all processors where it is not null, returning true if it does or false if not. More...
 
template<typename T >
bool semiverify (const T *r) const
 
template<typename T >
void min (const T &r, T &o, Request &req) const
 Non-blocking minimum of the local value r into o with the request req. More...
 
template<typename T >
void min (T &r) const
 Take a local variable and replace it with the minimum of it's values on all processors. More...
 
template<typename A >
void min (std::vector< bool, A > &r) const
 
template<typename T >
void minloc (T &r, unsigned int &min_id) const
 Take a local variable and replace it with the minimum of it's values on all processors, returning the minimum rank of a processor which originally held the minimum value. More...
 
template<typename T , typename A1 , typename A2 >
void minloc (std::vector< T, A1 > &r, std::vector< unsigned int, A2 > &min_id) const
 Take a vector of local variables and replace each entry with the minimum of it's values on all processors. More...
 
template<typename A1 , typename A2 >
void minloc (std::vector< bool, A1 > &r, std::vector< unsigned int, A2 > &min_id) const
 
template<typename T >
void max (const T &r, T &o, Request &req) const
 Non-blocking maximum of the local value r into o with the request req. More...
 
template<typename T >
void max (T &r) const
 Take a local variable and replace it with the maximum of it's values on all processors. More...
 
template<typename A >
void max (std::vector< bool, A > &r) const
 
template<typename T >
void maxloc (T &r, unsigned int &max_id) const
 Take a local variable and replace it with the maximum of it's values on all processors, returning the minimum rank of a processor which originally held the maximum value. More...
 
template<typename T , typename A1 , typename A2 >
void maxloc (std::vector< T, A1 > &r, std::vector< unsigned int, A2 > &max_id) const
 Take a vector of local variables and replace each entry with the maximum of it's values on all processors. More...
 
template<typename A1 , typename A2 >
void maxloc (std::vector< bool, A1 > &r, std::vector< unsigned int, A2 > &max_id) const
 
template<typename T >
void product (T &r) const
 Take a local variable and replace it with the product of its values on all processors. More...
 
template<typename T >
void product (const T &r, T &o, Request &req) const
 Non-blocking product of the local value r into o with the request req. More...
 
template<typename T >
void logical_and (T &r) const
 Take a local variable and replace it with the logical_and of its values on all processors. More...
 
template<typename T >
void logical_and (const T &r, T &o, Request &req) const
 Non-blocking logical_and of the local value r into o with the request req. More...
 
template<typename T >
void bitwise_and (T &r) const
 Take a local variable and replace it with the bitwise_and of its values on all processors. More...
 
template<typename T >
void bitwise_and (const T &r, T &o, Request &req) const
 Non-blocking bitwise_and of the local value r into o with the request req. More...
 
template<typename T >
void logical_or (T &r) const
 Take a local variable and replace it with the logical_or of its values on all processors. More...
 
template<typename T >
void logical_or (const T &r, T &o, Request &req) const
 Non-blocking logical_or of the local value r into o with the request req. More...
 
template<typename T >
void bitwise_or (T &r) const
 Take a local variable and replace it with the bitwise_or of its values on all processors. More...
 
template<typename T >
void bitwise_or (const T &r, T &o, Request &req) const
 Non-blocking bitwise_or of the local value r into o with the request req. More...
 
template<typename T >
void logical_xor (T &r) const
 Take a local variable and replace it with the logical_xor of its values on all processors. More...
 
template<typename T >
void logical_xor (const T &r, T &o, Request &req) const
 Non-blocking logical_xor of the local value r into o with the request req. More...
 
template<typename T >
void bitwise_xor (T &r) const
 Take a local variable and replace it with the bitwise_xor of its values on all processors. More...
 
template<typename T >
void bitwise_xor (const T &r, T &o, Request &req) const
 Non-blocking bitwise_xor of the local value r into o with the request req. More...
 
template<typename T >
void sum (T &r) const
 Take a local variable and replace it with the sum of it's values on all processors. More...
 
template<typename T >
void sum (const T &r, T &o, Request &req) const
 Non-blocking sum of the local value r into o with the request req. More...
 
template<typename T >
void set_union (T &data, const unsigned int root_id) const
 Take a container (set, map, unordered_set, multimap, etc) of local variables on each processor, and collect their union over all processors, replacing the original on the processor with rank root_id. More...
 
template<typename T >
void set_union (T &data) const
 Take a container of local variables on each processor, and replace it with their union over all processors, replacing the original on all processors. More...
 
status probe (const unsigned int src_processor_id, const MessageTag &tag=any_tag) const
 Blocking message probe. More...
 
template<typename T >
Status packed_range_probe (const unsigned int src_processor_id, const MessageTag &tag, bool &flag) const
 Non-Blocking message probe for a packed range message. More...
 
template<typename T >
void send (const unsigned int dest_processor_id, const T &buf, const MessageTag &tag=no_tag) const
 Blocking-send to one processor with data-defined type. More...
 
template<typename T >
void send (const unsigned int dest_processor_id, const T &buf, Request &req, const MessageTag &tag=no_tag) const
 Nonblocking-send to one processor with data-defined type. More...
 
template<typename T >
void send (const unsigned int dest_processor_id, const T &buf, const DataType &type, const MessageTag &tag=no_tag) const
 Blocking-send to one processor with user-defined type. More...
 
template<typename T >
void send (const unsigned int dest_processor_id, const T &buf, const DataType &type, Request &req, const MessageTag &tag=no_tag) const
 Nonblocking-send to one processor with user-defined type. More...
 
template<typename T >
void send (const unsigned int dest_processor_id, const T &buf, const NotADataType &type, Request &req, const MessageTag &tag=no_tag) const
 Nonblocking-send to one processor with user-defined packable type. More...
 
template<typename T >
void send (const unsigned int dest_processor_id, const std::basic_string< T > &buf, const MessageTag &tag) const
 
template<typename T >
void send (const unsigned int dest_processor_id, const std::basic_string< T > &buf, Request &req, const MessageTag &tag) const
 
template<typename T >
Status receive (const unsigned int dest_processor_id, T &buf, const MessageTag &tag=any_tag) const
 Blocking-receive from one processor with data-defined type. More...
 
template<typename T >
void receive (const unsigned int dest_processor_id, T &buf, Request &req, const MessageTag &tag=any_tag) const
 Nonblocking-receive from one processor with data-defined type. More...
 
template<typename T >
Status receive (const unsigned int dest_processor_id, T &buf, const DataType &type, const MessageTag &tag=any_tag) const
 Blocking-receive from one processor with user-defined type. More...
 
template<typename T >
void receive (const unsigned int dest_processor_id, T &buf, const DataType &type, Request &req, const MessageTag &tag=any_tag) const
 Nonblocking-receive from one processor with user-defined type. More...
 
template<typename T >
Status receive (const unsigned int src_processor_id, std::basic_string< T > &buf, const MessageTag &tag) const
 
template<typename T >
void receive (const unsigned int src_processor_id, std::basic_string< T > &buf, Request &req, const MessageTag &tag) const
 
template<typename T , typename A , typename std::enable_if< std::is_base_of< DataType, StandardType< T >>::value, int >::type = 0>
bool possibly_receive (unsigned int &src_processor_id, std::vector< T, A > &buf, Request &req, const MessageTag &tag) const
 Nonblocking-receive from one processor with user-defined type. More...
 
template<typename T , typename A , typename std::enable_if< Has_buffer_type< Packing< T >>::value, int >::type = 0>
bool possibly_receive (unsigned int &src_processor_id, std::vector< T, A > &buf, Request &req, const MessageTag &tag) const
 dispatches to possibly_receive_packed_range More...
 
template<typename T , typename A , typename std::enable_if< std::is_base_of< DataType, StandardType< T >>::value, int >::type = 0>
bool possibly_receive (unsigned int &src_processor_id, std::vector< T, A > &buf, const DataType &type, Request &req, const MessageTag &tag) const
 Nonblocking-receive from one processor with user-defined type. More...
 
template<typename T , typename A , typename std::enable_if< Has_buffer_type< Packing< T >>::value, int >::type = 0>
bool possibly_receive (unsigned int &src_processor_id, std::vector< T, A > &buf, const NotADataType &type, Request &req, const MessageTag &tag) const
 Nonblocking-receive from one processor with user-defined type. More...
 
template<typename T , typename A1 , typename A2 >
bool possibly_receive (unsigned int &src_processor_id, std::vector< std::vector< T, A1 >, A2 > &buf, const DataType &type, Request &req, const MessageTag &tag) const
 
template<typename Context , typename OutputIter , typename T >
bool possibly_receive_packed_range (unsigned int &src_processor_id, Context *context, OutputIter out, const T *output_type, Request &req, const MessageTag &tag) const
 Nonblocking packed range receive from one processor with user-defined type. More...
 
template<typename Context , typename Iter >
void send_packed_range (const unsigned int dest_processor_id, const Context *context, Iter range_begin, const Iter range_end, const MessageTag &tag=no_tag, std::size_t approx_buffer_size=1000000) const
 Blocking-send range-of-pointers to one processor. More...
 
template<typename Context , typename Iter >
void send_packed_range (const unsigned int dest_processor_id, const Context *context, Iter range_begin, const Iter range_end, Request &req, const MessageTag &tag=no_tag, std::size_t approx_buffer_size=1000000) const
 Nonblocking-send range-of-pointers to one processor. More...
 
template<typename Context , typename Iter >
void nonblocking_send_packed_range (const unsigned int dest_processor_id, const Context *context, Iter range_begin, const Iter range_end, Request &req, const MessageTag &tag=no_tag) const
 Similar to the above Nonblocking send_packed_range with a few important differences: More...
 
template<typename Context , typename Iter >
void nonblocking_send_packed_range (const unsigned int dest_processor_id, const Context *context, Iter range_begin, const Iter range_end, Request &req, std::shared_ptr< std::vector< typename TIMPI::Packing< typename std::iterator_traits< Iter >::value_type >::buffer_type >> &buffer, const MessageTag &tag=no_tag) const
 Similar to the above Nonblocking send_packed_range with a few important differences: More...
 
template<typename Context , typename Iter >
void nonblocking_send_packed_range (const unsigned int dest_processor_id, const Context *context, Iter range_begin, const Iter range_end, Request &req, std::shared_ptr< std::vector< typename Packing< typename std::iterator_traits< Iter >::value_type >::buffer_type >> &buffer, const MessageTag &tag) const
 
template<typename Context , typename OutputIter , typename T >
void receive_packed_range (const unsigned int dest_processor_id, Context *context, OutputIter out, const T *output_type, const MessageTag &tag=any_tag) const
 Blocking-receive range-of-pointers from one processor. More...
 
template<typename Context , typename OutputIter , typename T >
void nonblocking_receive_packed_range (const unsigned int src_processor_id, Context *context, OutputIter out, const T *output_type, Request &req, Status &stat, const MessageTag &tag=any_tag) const
 Non-Blocking-receive range-of-pointers from one processor. More...
 
template<typename Context , typename OutputIter , typename T >
void nonblocking_receive_packed_range (const unsigned int src_processor_id, Context *context, OutputIter out, const T *output_type, Request &req, Status &stat, std::shared_ptr< std::vector< typename TIMPI::Packing< T >::buffer_type >> &buffer, const MessageTag &tag=any_tag) const
 Non-Blocking-receive range-of-pointers from one processor. More...
 
template<typename Context , typename OutputIter , typename T >
void nonblocking_receive_packed_range (const unsigned int src_processor_id, Context *context, OutputIter out, const T *, Request &req, Status &stat, std::shared_ptr< std::vector< typename Packing< T >::buffer_type >> &buffer, const MessageTag &tag) const
 
template<typename T1 , typename T2 , typename std::enable_if< std::is_base_of< DataType, StandardType< T1 >>::value &&std::is_base_of< DataType, StandardType< T2 >>::value, int >::type = 0>
void send_receive (const unsigned int dest_processor_id, const T1 &send_data, const unsigned int source_processor_id, T2 &recv_data, const MessageTag &send_tag=no_tag, const MessageTag &recv_tag=any_tag) const
 Send data send to one processor while simultaneously receiving other data recv from a (potentially different) processor. More...
 
template<typename T1 , typename T2 >
void send_receive (const unsigned int dest_processor_id, const T1 &send_data, const DataType &type1, const unsigned int source_processor_id, T2 &recv_data, const DataType &type2, const MessageTag &send_tag=no_tag, const MessageTag &recv_tag=any_tag) const
 Send data send to one processor while simultaneously receiving other data recv from a (potentially different) processor, using a user-specified MPI Dataype. More...
 
template<typename T , typename A , typename std::enable_if< Has_buffer_type< Packing< T >>::value, int >::type >
void send_receive (const unsigned int dest_processor_id, const std::vector< T, A > &send_data, const unsigned int source_processor_id, std::vector< T, A > &recv_data, const MessageTag &send_tag, const MessageTag &recv_tag) const
 
template<typename T , typename A1 , typename A2 >
void send_receive (const unsigned int dest_processor_id, const std::vector< std::vector< T, A1 >, A2 > &sendvec, const unsigned int source_processor_id, std::vector< std::vector< T, A1 >, A2 > &recv, const MessageTag &send_tag, const MessageTag &recv_tag) const
 
template<typename T1 , typename T2 , typename std::enable_if< std::is_base_of< DataType, StandardType< T1 >>::value &&std::is_base_of< DataType, StandardType< T2 >>::value, int >::type >
void send_receive (const unsigned int timpi_dbg_var(send_tgt), const T1 &send_val, const unsigned int timpi_dbg_var(recv_source), T2 &recv_val, const MessageTag &, const MessageTag &) const
 Send-receive data from one processor. More...
 
template<typename T , typename A , typename std::enable_if< std::is_base_of< DataType, StandardType< T >>::value, int >::type >
void send_receive (const unsigned int timpi_dbg_var(dest_processor_id), const std::vector< T, A > &send, const unsigned int timpi_dbg_var(source_processor_id), std::vector< T, A > &recv, const MessageTag &, const MessageTag &) const
 
template<typename T , typename A1 , typename A2 >
void send_receive (const unsigned int timpi_dbg_var(dest_processor_id), const std::vector< std::vector< T, A1 >, A2 > &send, const unsigned int timpi_dbg_var(source_processor_id), std::vector< std::vector< T, A1 >, A2 > &recv, const MessageTag &, const MessageTag &) const
 
template<typename Context1 , typename RangeIter , typename Context2 , typename OutputIter , typename T >
void send_receive_packed_range (const unsigned int dest_processor_id, const Context1 *context1, RangeIter send_begin, const RangeIter send_end, const unsigned int source_processor_id, Context2 *context2, OutputIter out, const T *output_type, const MessageTag &send_tag=no_tag, const MessageTag &recv_tag=any_tag, std::size_t approx_buffer_size=1000000) const
 Send a range-of-pointers to one processor while simultaneously receiving another range from a (potentially different) processor. More...
 
template<typename Context1 , typename RangeIter , typename Context2 , typename OutputIter , typename T >
void send_receive_packed_range (const unsigned int timpi_dbg_var(dest_processor_id), const Context1 *context1, RangeIter send_begin, const RangeIter send_end, const unsigned int timpi_dbg_var(source_processor_id), Context2 *context2, OutputIter out_iter, const T *output_type, const MessageTag &, const MessageTag &, std::size_t) const
 Send-receive range-of-pointers from one processor. More...
 
template<typename T , typename A >
void gather (const unsigned int root_id, const T &send_data, std::vector< T, A > &recv) const
 Take a vector of length comm.size(), and on processor root_id fill in recv[processor_id] = the value of send on processor processor_id. More...
 
template<typename T , typename A >
void gather (const unsigned int root_id, const std::basic_string< T > &send_data, std::vector< std::basic_string< T >, A > &recv_data, const bool identical_buffer_sizes=false) const
 The gather overload for string types has an optional identical_buffer_sizes optimization for when all strings are the same length. More...
 
template<typename T , typename A , typename std::enable_if< std::is_base_of< DataType, StandardType< T >>::value, int >::type = 0>
void gather (const unsigned int root_id, std::vector< T, A > &r) const
 
Take a vector of local variables and expand it on processor root_id to include values from all processors More...
 
template<typename T , typename A , typename std::enable_if< Has_buffer_type< Packing< T >>::value, int >::type = 0>
void gather (const unsigned int root_id, std::vector< T, A > &r) const
 
template<typename T , typename A , typename std::enable_if< std::is_base_of< DataType, StandardType< T >>::value, int >::type = 0>
void allgather (const T &send_data, std::vector< T, A > &recv_data) const
 Take a vector of length this->size(), and fill in recv[processor_id] = the value of send on that processor. More...
 
template<typename T , typename A , typename std::enable_if< Has_buffer_type< Packing< T >>::value, int >::type = 0>
void allgather (const T &send_data, std::vector< T, A > &recv_data) const
 Take a vector of length this->size(), and fill in recv[processor_id] = the value of send on that processor. More...
 
template<typename T , typename A >
void allgather (const std::basic_string< T > &send_data, std::vector< std::basic_string< T >, A > &recv_data, const bool identical_buffer_sizes=false) const
 The allgather overload for string types has an optional identical_buffer_sizes optimization for when all strings are the same length. More...
 
template<typename T , typename A , typename std::enable_if< std::is_base_of< DataType, StandardType< T >>::value, int >::type = 0>
void allgather (std::vector< T, A > &r, const bool identical_buffer_sizes=false) const
 
Take a vector of fixed size local variables and expand it to include values from all processors. More...
 
template<typename T , typename A1 , typename A2 , typename std::enable_if< std::is_base_of< DataType, StandardType< T >>::value, int >::type = 0>
void allgather (const std::vector< T, A1 > &send_data, std::vector< std::vector< T, A1 >, A2 > &recv_data, const bool identical_buffer_sizes=false) const
 Take a vector of fixed size local variables and collect similar vectors from all processors. More...
 
template<typename T , typename A1 , typename A2 , typename std::enable_if< Has_buffer_type< Packing< T >>::value, int >::type = 0>
void allgather (const std::vector< T, A1 > &send_data, std::vector< std::vector< T, A1 >, A2 > &recv_data, const bool identical_buffer_sizes=false) const
 Take a vector of dynamic-size local variables and collect similar vectors from all processors. More...
 
template<typename T , typename A , typename std::enable_if< Has_buffer_type< Packing< T >>::value, int >::type = 0>
void allgather (std::vector< T, A > &r, const bool identical_buffer_sizes=false) const
 
Take a vector of possibly dynamically sized local variables and expand it to include values from all processors. More...
 
template<typename T , typename A >
void allgather (std::vector< std::basic_string< T >, A > &r, const bool identical_buffer_sizes=false) const
 AllGather overload for vectors of string types. More...
 
template<typename T , typename A >
void scatter (const std::vector< T, A > &data, T &recv, const unsigned int root_id=0) const
 Take a vector of local variables and scatter the ith item to the ith processor in the communicator. More...
 
template<typename T , typename A >
void scatter (const std::vector< T, A > &data, std::vector< T, A > &recv, const unsigned int root_id=0) const
 Take a vector of local variables and scatter the ith equal-sized chunk to the ith processor in the communicator. More...
 
template<typename T , typename A1 , typename A2 >
void scatter (const std::vector< T, A1 > &data, const std::vector< CountType, A2 > counts, std::vector< T, A1 > &recv, const unsigned int root_id=0) const
 Take a vector of local variables and scatter the ith variable-sized chunk to the ith processor in the communicator. More...
 
template<typename T , typename A1 , typename A2 >
void scatter (const std::vector< T, A1 > &data, const std::vector< int, A2 > counts, std::vector< T, A1 > &recv, const unsigned int root_id=0) const
 vector<int> based scatter, for backwards compatibility More...
 
template<typename T , typename A1 , typename A2 >
void scatter (const std::vector< std::vector< T, A1 >, A2 > &data, std::vector< T, A1 > &recv, const unsigned int root_id=0, const bool identical_buffer_sizes=false) const
 Take a vector of vectors and scatter the ith inner vector to the ith processor in the communicator. More...
 
template<typename Context , typename Iter , typename OutputIter >
void gather_packed_range (const unsigned int root_id, Context *context, Iter range_begin, const Iter range_end, OutputIter out, std::size_t approx_buffer_size=1000000) const
 Take a range of local variables, combine it with ranges from all processors, and write the output to the output iterator on rank root. More...
 
template<typename Context , typename Iter , typename OutputIter >
void allgather_packed_range (Context *context, Iter range_begin, const Iter range_end, OutputIter out, std::size_t approx_buffer_size=1000000) const
 Take a range of local variables, combine it with ranges from all processors, and write the output to the output iterator. More...
 
template<typename T , typename A >
void alltoall (std::vector< T, A > &r) const
 Effectively transposes the input vector across all processors. More...
 
template<typename T #ifdef TIMPI_HAVE_MPI, typename std::enable_if< std::is_base_of< DataType, StandardType< T >>::value, int >::type = 0 #endif>
void broadcast (T &data, const unsigned int root_id=0, const bool identical_sizes=false) const
 Take a local value and broadcast it to all processors. More...
 
template<typename T , typename std::enable_if< Has_buffer_type< Packing< T >>::value, int >::type = 0>
void broadcast (T &data, const unsigned int root_id=0, const bool identical_sizes=false) const
 Take a possibly dynamically-sized local value and broadcast it to all processors. More...
 
template<typename T >
void broadcast (std::basic_string< T > &data, const unsigned int root_id, const bool identical_sizes) const
 
template<typename T , typename A >
void broadcast (std::vector< std::basic_string< T >, A > &data, const unsigned int root_id, const bool identical_sizes) const
 
template<typename Context , typename OutputContext , typename Iter , typename OutputIter >
void broadcast_packed_range (const Context *context1, Iter range_begin, const Iter range_end, OutputContext *context2, OutputIter out, const unsigned int root_id=0, std::size_t approx_buffer_size=1000000) const
 Blocking-broadcast range-of-pointers to one processor. More...
 

Detailed Description

Definition at line 1508 of file communicator.h.

Member Enumeration Documentation

◆ SendMode

Whether to use default or synchronous sends?

Enumerator
DEFAULT 
SYNCHRONOUS 

Definition at line 220 of file communicator.h.

◆ SyncType

What algorithm to use for parallel synchronization?

Enumerator
NBX 
ALLTOALL_COUNTS 
SENDRECEIVE 

Definition at line 225 of file communicator.h.

Constructor & Destructor Documentation

◆ Communicator() [1/4]

libMesh::Parallel::Communicator::Communicator ( )
default

◆ Communicator() [2/4]

libMesh::Parallel::Communicator::Communicator ( const TIMPI::communicator comm)
inlineexplicit

Definition at line 1511 of file communicator.h.

1511 : TIMPI::Communicator(comm) {}
Encapsulates the MPI_Comm object.
Definition: communicator.h:108

◆ Communicator() [3/4]

libMesh::Parallel::Communicator::Communicator ( const Communicator )
delete

◆ Communicator() [4/4]

libMesh::Parallel::Communicator::Communicator ( Communicator &&  )
default

◆ ~Communicator()

libMesh::Parallel::Communicator::~Communicator ( )
default

Member Function Documentation

◆ allgather() [1/8]

template<typename T , typename A , typename std::enable_if< std::is_base_of< DataType, StandardType< T >>::value, int >::type = 0>
void TIMPI::Communicator::allgather ( const T &  send_data,
std::vector< T, A > &  recv_data 
) const
inlineinherited

◆ allgather() [2/8]

template<typename T , typename A , typename std::enable_if< Has_buffer_type< Packing< T >>::value, int >::type = 0>
void TIMPI::Communicator::allgather ( const T &  send_data,
std::vector< T, A > &  recv_data 
) const
inlineinherited

Take a vector of length this->size(), and fill in recv[processor_id] = the value of send on that processor.

This overload works on potentially dynamically sized types, and dispatches to allgather_packed_range

◆ allgather() [3/8]

template<typename T , typename A >
void TIMPI::Communicator::allgather ( const std::basic_string< T > &  send_data,
std::vector< std::basic_string< T >, A > &  recv_data,
const bool  identical_buffer_sizes = false 
) const
inlineinherited

The allgather overload for string types has an optional identical_buffer_sizes optimization for when all strings are the same length.

Definition at line 1629 of file parallel_implementation.h.

References TIMPI::Communicator::allgather(), and TIMPI::Communicator::size().

1632 {
1633  TIMPI_LOG_SCOPE ("allgather()","Parallel");
1634 
1635  timpi_assert(this->size());
1636  recv.assign(this->size(), "");
1637 
1638  // serial case
1639  if (this->size() < 2)
1640  {
1641  recv.resize(1);
1642  recv[0] = sendval;
1643  return;
1644  }
1645 
1646  std::vector<CountType>
1647  sendlengths (this->size(), 0);
1648  std::vector<DispType>
1649  displacements(this->size(), 0);
1650 
1651  const CountType mysize = cast_int<CountType>(sendval.size());
1652 
1653  if (identical_buffer_sizes)
1654  sendlengths.assign(this->size(), mysize);
1655  else
1656  // first comm step to determine buffer sizes from all processors
1657  this->allgather(mysize, sendlengths);
1658 
1659  // Find the total size of the final array and
1660  // set up the displacement offsets for each processor
1661  CountType globalsize = 0;
1662  for (unsigned int i=0; i != this->size(); ++i)
1663  {
1664  displacements[i] = globalsize;
1665  globalsize += sendlengths[i];
1666  }
1667 
1668  // Check for quick return
1669  if (globalsize == 0)
1670  return;
1671 
1672  // monolithic receive buffer
1673  std::basic_string<T> r(globalsize, 0);
1674 
1675  // and get the data from the remote processors.
1676  timpi_call_mpi
1677  (TIMPI_ALLGATHERV(const_cast<T*>(mysize ? sendval.data() : nullptr),
1678  mysize, StandardType<T>(),
1679  &r[0], sendlengths.data(), displacements.data(),
1680  StandardType<T>(), this->get()));
1681 
1682  // slice receive buffer up
1683  for (unsigned int i=0; i != this->size(); ++i)
1684  recv[i] = r.substr(displacements[i], sendlengths[i]);
1685 }
void allgather(const T &send_data, std::vector< T, A > &recv_data) const
Take a vector of length this->size(), and fill in recv[processor_id] = the value of send on that proc...
processor_id_type size() const
Definition: communicator.h:211
MPI_Count CountType
Definition: status.h:47

◆ allgather() [4/8]

template<typename T , typename A , typename std::enable_if< std::is_base_of< DataType, StandardType< T >>::value, int >::type = 0>
void TIMPI::Communicator::allgather ( std::vector< T, A > &  r,
const bool  identical_buffer_sizes = false 
) const
inlineinherited


Take a vector of fixed size local variables and expand it to include values from all processors.

By default, each processor is allowed to have its own unique input buffer length. If it is known that all processors have the same input sizes additional communication can be avoided.

Specifically, this function transforms this:

* Processor 0: [ ... N_0 ]
* Processor 1: [ ....... N_1 ]
* ...
* Processor M: [ .. N_M]
* 

into this:

* [ [ ... N_0 ] [ ....... N_1 ] ... [ .. N_M] ]
* 

on each processor. This function is collective and therefore must be called by all processors in the Communicator.

◆ allgather() [5/8]

template<typename T , typename A1 , typename A2 , typename std::enable_if< std::is_base_of< DataType, StandardType< T >>::value, int >::type = 0>
void TIMPI::Communicator::allgather ( const std::vector< T, A1 > &  send_data,
std::vector< std::vector< T, A1 >, A2 > &  recv_data,
const bool  identical_buffer_sizes = false 
) const
inlineinherited

Take a vector of fixed size local variables and collect similar vectors from all processors.

By default, each processor is allowed to have its own unique input buffer length. If it is known that all processors have the same input sizes additional communication can be avoided.

◆ allgather() [6/8]

template<typename T , typename A1 , typename A2 , typename std::enable_if< Has_buffer_type< Packing< T >>::value, int >::type = 0>
void TIMPI::Communicator::allgather ( const std::vector< T, A1 > &  send_data,
std::vector< std::vector< T, A1 >, A2 > &  recv_data,
const bool  identical_buffer_sizes = false 
) const
inlineinherited

Take a vector of dynamic-size local variables and collect similar vectors from all processors.

◆ allgather() [7/8]

template<typename T , typename A , typename std::enable_if< Has_buffer_type< Packing< T >>::value, int >::type = 0>
void TIMPI::Communicator::allgather ( std::vector< T, A > &  r,
const bool  identical_buffer_sizes = false 
) const
inlineinherited


Take a vector of possibly dynamically sized local variables and expand it to include values from all processors.

By default, each processor is allowed to have its own unique input buffer length. If it is known that all processors have the same input sizes additional communication can be avoided.

Specifically, this function transforms this:

* Processor 0: [ ... N_0 ]
* Processor 1: [ ....... N_1 ]
* ...
* Processor M: [ .. N_M]
* 

into this:

* [ [ ... N_0 ] [ ....... N_1 ] ... [ .. N_M] ]
* 

on each processor. This function is collective and therefore must be called by all processors in the Communicator.

◆ allgather() [8/8]

template<typename T , typename A >
void TIMPI::Communicator::allgather ( std::vector< std::basic_string< T >, A > &  r,
const bool  identical_buffer_sizes = false 
) const
inlineinherited

AllGather overload for vectors of string types.

◆ allgather_packed_range()

template<typename Context , typename Iter , typename OutputIter >
void TIMPI::Communicator::allgather_packed_range ( Context *  context,
Iter  range_begin,
const Iter  range_end,
OutputIter  out,
std::size_t  approx_buffer_size = 1000000 
) const
inlineinherited

Take a range of local variables, combine it with ranges from all processors, and write the output to the output iterator.

The approximate maximum size (in entries; number of bytes will likely be 4x or 8x larger) to use in a single data vector buffer to send can be specified for performance or memory usage reasons; if the range cannot be packed into a single buffer of this size then multiple buffers and messages will be used.

Note that the received data vector sizes will be the sum of the sent vector sizes; a smaller-than-default size may be useful for users on many processors, in cases where all-to-one communication cannot be avoided entirely.

Referenced by testGettableStringAllGather(), testNestingAllGather(), testNullAllGather(), and testTupleStringAllGather().

◆ alltoall()

template<typename T , typename A >
void TIMPI::Communicator::alltoall ( std::vector< T, A > &  r) const
inlineinherited

Effectively transposes the input vector across all processors.

The jth entry on processor i is replaced with the ith entry from processor j.

Referenced by TIMPI::detail::push_parallel_alltoall_helper().

◆ barrier()

void TIMPI::Communicator::barrier ( ) const
inherited

Pause execution until all processors reach a certain point.

Definition at line 225 of file communicator.C.

References TIMPI::Communicator::size().

Referenced by testBarrier(), and TIMPI::TIMPIInit::~TIMPIInit().

226 {
227  if (this->size() > 1)
228  {
229  TIMPI_LOG_SCOPE("barrier()", "Communicator");
230  timpi_call_mpi(MPI_Barrier (this->get()));
231  }
232 }
processor_id_type size() const
Definition: communicator.h:211

◆ bitwise_and() [1/2]

template<typename T >
void TIMPI::Communicator::bitwise_and ( T &  r) const
inlineinherited

Take a local variable and replace it with the bitwise_and of its values on all processors.

Containers are replaced element-wise.

◆ bitwise_and() [2/2]

template<typename T >
void TIMPI::Communicator::bitwise_and ( const T &  r,
T &  o,
Request req 
) const
inlineinherited

Non-blocking bitwise_and of the local value r into o with the request req.

◆ bitwise_or() [1/2]

template<typename T >
void TIMPI::Communicator::bitwise_or ( T &  r) const
inlineinherited

Take a local variable and replace it with the bitwise_or of its values on all processors.

Containers are replaced element-wise.

◆ bitwise_or() [2/2]

template<typename T >
void TIMPI::Communicator::bitwise_or ( const T &  r,
T &  o,
Request req 
) const
inlineinherited

Non-blocking bitwise_or of the local value r into o with the request req.

◆ bitwise_xor() [1/2]

template<typename T >
void TIMPI::Communicator::bitwise_xor ( T &  r) const
inlineinherited

Take a local variable and replace it with the bitwise_xor of its values on all processors.

Containers are replaced element-wise.

◆ bitwise_xor() [2/2]

template<typename T >
void TIMPI::Communicator::bitwise_xor ( const T &  r,
T &  o,
Request req 
) const
inlineinherited

Non-blocking bitwise_xor of the local value r into o with the request req.

◆ broadcast() [1/4]

template<typename T #ifdef TIMPI_HAVE_MPI, typename std::enable_if< std::is_base_of< DataType, StandardType< T >>::value, int >::type = 0 #endif>
void TIMPI::Communicator::broadcast ( T &  data,
const unsigned int  root_id = 0,
const bool  identical_sizes = false 
) const
inlineinherited

Take a local value and broadcast it to all processors.

Optionally takes the root_id processor, which specifies the processor initiating the broadcast.

If data is a container, it will be resized on target processors. When using pre-sized target containers, specify identical_sizes=true on all processors for an optimization.

Fixed variant

Referenced by TIMPI::Communicator::broadcast(), testBroadcast(), testBroadcastArrayType(), testBroadcastNestedType(), testBroadcastString(), testContainerBroadcast(), and testVectorOfContainersBroadcast().

◆ broadcast() [2/4]

template<typename T , typename std::enable_if< Has_buffer_type< Packing< T >>::value, int >::type = 0>
void TIMPI::Communicator::broadcast ( T &  data,
const unsigned int  root_id = 0,
const bool  identical_sizes = false 
) const
inlineinherited

Take a possibly dynamically-sized local value and broadcast it to all processors.

Optionally takes the root_id processor, which specifies the processor initiating the broadcast.

If data is a container, it will be resized on target processors. When using pre-sized target containers, specify identical_sizes=true on all processors for an optimization.

Dynamic variant

◆ broadcast() [3/4]

template<typename T >
void TIMPI::Communicator::broadcast ( std::basic_string< T > &  data,
const unsigned int  root_id,
const bool  identical_sizes 
) const
inlineinherited

Definition at line 1720 of file parallel_implementation.h.

References TIMPI::Communicator::broadcast(), TIMPI::Communicator::rank(), TIMPI::Communicator::size(), and TIMPI::Communicator::verify().

1723 {
1724  if (this->size() == 1)
1725  {
1726  timpi_assert (!this->rank());
1727  timpi_assert (!root_id);
1728  return;
1729  }
1730 
1731  timpi_assert_less (root_id, this->size());
1732  timpi_assert (this->verify(identical_sizes));
1733 
1734  TIMPI_LOG_SCOPE("broadcast()", "Parallel");
1735 
1736  std::size_t data_size = data.size();
1737 
1738  if (identical_sizes)
1739  timpi_assert(this->verify(data_size));
1740  else
1741  this->broadcast(data_size, root_id);
1742 
1743  std::vector<T> data_c(data_size);
1744 #ifndef NDEBUG
1745  std::basic_string<T> orig(data);
1746 #endif
1747 
1748  if (this->rank() == root_id)
1749  for (std::size_t i=0; i<data.size(); i++)
1750  data_c[i] = data[i];
1751 
1752  this->broadcast (data_c, root_id, StandardType<T>::is_fixed_type);
1753 
1754  data.assign(data_c.begin(), data_c.end());
1755 
1756 #ifndef NDEBUG
1757  if (this->rank() == root_id)
1758  timpi_assert_equal_to (data, orig);
1759 #endif
1760 }
processor_id_type rank() const
Definition: communicator.h:208
processor_id_type size() const
Definition: communicator.h:211
static const bool is_fixed_type
Definition: data_type.h:130
void broadcast(T &data, const unsigned int root_id=0, const bool identical_sizes=false) const
Take a local value and broadcast it to all processors.
timpi_pure bool verify(const T &r) const
Check whether a local variable has the same value on all processors, returning true if it does or fal...

◆ broadcast() [4/4]

template<typename T , typename A >
void TIMPI::Communicator::broadcast ( std::vector< std::basic_string< T >, A > &  data,
const unsigned int  root_id,
const bool  identical_sizes 
) const
inlineinherited

The strings will be packed in one long array with the size of each string preceding the actual characters

Definition at line 1764 of file parallel_implementation.h.

References TIMPI::Communicator::broadcast(), TIMPI::Communicator::rank(), TIMPI::Communicator::size(), and TIMPI::Communicator::verify().

1767 {
1768  if (this->size() == 1)
1769  {
1770  timpi_assert (!this->rank());
1771  timpi_assert (!root_id);
1772  return;
1773  }
1774 
1775  timpi_assert_less (root_id, this->size());
1776  timpi_assert (this->verify(identical_sizes));
1777 
1778  TIMPI_LOG_SCOPE("broadcast()", "Parallel");
1779 
1780  std::size_t bufsize=0;
1781  if (root_id == this->rank() || identical_sizes)
1782  {
1783  for (std::size_t i=0; i<data.size(); ++i)
1784  bufsize += data[i].size() + 1; // Add one for the string length word
1785  }
1786 
1787  if (identical_sizes)
1788  timpi_assert(this->verify(bufsize));
1789  else
1790  this->broadcast(bufsize, root_id);
1791 
1792  // Here we use unsigned int to store up to 32-bit characters
1793  std::vector<unsigned int> temp; temp.reserve(bufsize);
1794  // Pack the strings
1795  if (root_id == this->rank())
1796  {
1797  for (std::size_t i=0; i<data.size(); ++i)
1798  {
1799  temp.push_back(cast_int<unsigned int>(data[i].size()));
1800  for (std::size_t j=0; j != data[i].size(); ++j)
1805  temp.push_back(data[i][j]);
1806  }
1807  }
1808  else
1809  temp.resize(bufsize);
1810 
1811  // broad cast the packed strings
1812  this->broadcast(temp, root_id, true);
1813 
1814  // Unpack the strings
1815  if (root_id != this->rank())
1816  {
1817  data.clear();
1818  typename std::vector<unsigned int>::const_iterator iter = temp.begin();
1819  while (iter != temp.end())
1820  {
1821  std::size_t curr_len = *iter++;
1822  data.push_back(std::basic_string<T>(iter, iter+curr_len));
1823  iter += curr_len;
1824  }
1825  }
1826 }
processor_id_type rank() const
Definition: communicator.h:208
processor_id_type size() const
Definition: communicator.h:211
void broadcast(T &data, const unsigned int root_id=0, const bool identical_sizes=false) const
Take a local value and broadcast it to all processors.
timpi_pure bool verify(const T &r) const
Check whether a local variable has the same value on all processors, returning true if it does or fal...

◆ broadcast_packed_range()

template<typename Context , typename OutputContext , typename Iter , typename OutputIter >
void TIMPI::Communicator::broadcast_packed_range ( const Context *  context1,
Iter  range_begin,
const Iter  range_end,
OutputContext *  context2,
OutputIter  out,
const unsigned int  root_id = 0,
std::size_t  approx_buffer_size = 1000000 
) const
inlineinherited

Blocking-broadcast range-of-pointers to one processor.

This function does not send the raw pointers, but rather constructs new objects at the other end whose contents match the objects pointed to by the sender.

void TIMPI::pack(const T *, vector<int> & data, const Context *) is used to serialize type T onto the end of a data vector.

unsigned int TIMPI::packable_size(const T *, const Context *) is used to allow data vectors to reserve memory, and for additional error checking

unsigned int TIMPI::packed_size(const T *, vector<int>::const_iterator) is used to advance to the beginning of the next object's data.

The approximate maximum size (in entries; number of bytes will likely be 4x or 8x larger) to use in a single data vector buffer can be specified for performance or memory usage reasons; if the range cannot be packed into a single buffer of this size then multiple buffers and messages will be used.

◆ clear()

void TIMPI::Communicator::clear ( )
inherited

Free and reset this communicator.

Definition at line 162 of file communicator.C.

References TIMPI::Communicator::_communicator, and TIMPI::Communicator::_I_duped_it.

Referenced by TIMPI::Communicator::operator=(), TIMPI::Communicator::split(), TIMPI::Communicator::split_by_type(), and TIMPI::Communicator::~Communicator().

162  {
163 #ifdef TIMPI_HAVE_MPI
164  if (_I_duped_it)
165  {
166  timpi_assert (_communicator != MPI_COMM_NULL);
167  timpi_call_mpi
168  (MPI_Comm_free(&_communicator));
169 
170  _communicator = MPI_COMM_NULL;
171  }
172  _I_duped_it = false;
173 #endif
174 }
communicator _communicator
Definition: communicator.h:236

◆ dereference_unique_tag()

void TIMPI::Communicator::dereference_unique_tag ( int  tagvalue) const
inherited

Dereference an already-acquired tag, and see if we can re-release it.

Definition at line 46 of file communicator.C.

References TIMPI::Communicator::used_tag_values.

Referenced by TIMPI::MessageTag::operator=(), and TIMPI::MessageTag::~MessageTag().

47 {
48  // This had better be an already-acquired tag.
49  timpi_assert(used_tag_values.count(tagvalue));
50 
51  used_tag_values[tagvalue]--;
52  // If we don't have any more outstanding references, we
53  // don't even need to keep this tag in our "used" set.
54  if (!used_tag_values[tagvalue])
55  used_tag_values.erase(tagvalue);
56 }
std::map< int, unsigned int > used_tag_values
Definition: communicator.h:243

◆ duplicate() [1/2]

void TIMPI::Communicator::duplicate ( const Communicator comm)
inherited

Definition at line 137 of file communicator.C.

References TIMPI::Communicator::_communicator, TIMPI::Communicator::send_mode(), and TIMPI::Communicator::sync_type().

Referenced by testGetUniqueTagAuto(), and testStringSyncType().

138 {
139  this->duplicate(comm._communicator);
140  this->send_mode(comm.send_mode());
141  this->sync_type(comm.sync_type());
142 }
SyncType sync_type() const
Gets the user-requested SyncType.
Definition: communicator.h:355
SendMode send_mode() const
Gets the user-requested SendMode.
Definition: communicator.h:338
void duplicate(const Communicator &comm)
Definition: communicator.C:137

◆ duplicate() [2/2]

void TIMPI::Communicator::duplicate ( const communicator comm)
inherited

Definition at line 146 of file communicator.C.

References TIMPI::Communicator::_communicator, TIMPI::Communicator::_I_duped_it, and TIMPI::Communicator::assign().

147 {
148  if (_communicator != MPI_COMM_NULL)
149  {
150  timpi_call_mpi
151  (MPI_Comm_dup(comm, &_communicator));
152 
153  _I_duped_it = true;
154  }
155  this->assign(_communicator);
156 }
communicator _communicator
Definition: communicator.h:236
void assign(const communicator &comm)
Utility function for setting our member variables from an MPI communicator.
Definition: communicator.C:185

◆ gather() [1/4]

template<typename T , typename A >
void TIMPI::Communicator::gather ( const unsigned int  root_id,
const T &  send_data,
std::vector< T, A > &  recv 
) const
inlineinherited

Take a vector of length comm.size(), and on processor root_id fill in recv[processor_id] = the value of send on processor processor_id.

Referenced by testGather(), testGatherString(), and testGatherString2().

◆ gather() [2/4]

template<typename T , typename A >
void TIMPI::Communicator::gather ( const unsigned int  root_id,
const std::basic_string< T > &  send_data,
std::vector< std::basic_string< T >, A > &  recv_data,
const bool  identical_buffer_sizes = false 
) const
inlineinherited

The gather overload for string types has an optional identical_buffer_sizes optimization for when all strings are the same length.

◆ gather() [3/4]

template<typename T , typename A , typename std::enable_if< std::is_base_of< DataType, StandardType< T >>::value, int >::type = 0>
void TIMPI::Communicator::gather ( const unsigned int  root_id,
std::vector< T, A > &  r 
) const
inlineinherited


Take a vector of local variables and expand it on processor root_id to include values from all processors

This handles the case where the lengths of the vectors may vary. Specifically, this function transforms this:

* Processor 0: [ ... N_0 ]
* Processor 1: [ ....... N_1 ]
* ...
* Processor M: [ .. N_M]
* 

into this:

* [ [ ... N_0 ] [ ....... N_1 ] ... [ .. N_M] ]
* 

on processor root_id. This function is collective and therefore must be called by all processors in the Communicator.

If the type T is a standard (fixed-size) type then we use a standard MPI_Gatherv; if it is a packable variable-size type then we dispatch to gather_packed_range.

◆ gather() [4/4]

template<typename T , typename A , typename std::enable_if< Has_buffer_type< Packing< T >>::value, int >::type = 0>
void TIMPI::Communicator::gather ( const unsigned int  root_id,
std::vector< T, A > &  r 
) const
inlineinherited

◆ gather_packed_range()

template<typename Context , typename Iter , typename OutputIter >
void TIMPI::Communicator::gather_packed_range ( const unsigned int  root_id,
Context *  context,
Iter  range_begin,
const Iter  range_end,
OutputIter  out,
std::size_t  approx_buffer_size = 1000000 
) const
inlineinherited

Take a range of local variables, combine it with ranges from all processors, and write the output to the output iterator on rank root.

The approximate maximum size (in entries; number of bytes will likely be 4x or 8x larger) to use in a single data vector buffer to send can be specified for performance or memory usage reasons; if the range cannot be packed into a single buffer of this size then multiple buffers and messages will be used.

Note that the received data vector sizes will be the sum of the sent vector sizes; a smaller-than-default size may be useful for users on many processors, in cases where all-to-one communication cannot be avoided entirely.

◆ get() [1/2]

communicator& TIMPI::Communicator::get ( )
inlineinherited

◆ get() [2/2]

const communicator& TIMPI::Communicator::get ( ) const
inlineinherited

Definition at line 169 of file communicator.h.

References TIMPI::Communicator::_communicator.

169 { return _communicator; }
communicator _communicator
Definition: communicator.h:236

◆ get_unique_tag()

MessageTag TIMPI::Communicator::get_unique_tag ( int  tagvalue = MessageTag::invalid_tag) const
inherited

Get a tag that is unique to this Communicator.

A requested tag value may be provided. If no request is made then an automatic unique tag value will be generated; such usage of get_unique_tag() must be done on every processor in a consistent order.

Note
If people are also using magic numbers or copying raw communicators around then we can't guarantee the tag is unique to this MPI_Comm.
Leaving tagvalue unspecified is recommended in most cases. Manually selecting tag values is dangerous, as tag values may be freed and reselected earlier than expected in asynchronous communication algorithms.

Definition at line 251 of file communicator.C.

References TIMPI::Communicator::_max_tag, TIMPI::Communicator::_next_tag, TIMPI::MessageTag::invalid_tag, TIMPI::Communicator::max(), and TIMPI::Communicator::used_tag_values.

Referenced by TIMPI::pull_parallel_vector_data(), TIMPI::detail::push_parallel_alltoall_helper(), TIMPI::detail::push_parallel_nbx_helper(), TIMPI::detail::push_parallel_roundrobin_helper(), testGetUniqueTagAuto(), testGetUniqueTagManual(), and testGetUniqueTagOverlap().

252 {
253  if (tagvalue == MessageTag::invalid_tag)
254  {
255 #ifndef NDEBUG
256  // Automatic tag values have to be requested in sync
257  int maxval = _next_tag;
258  this->max(maxval);
259  timpi_assert_equal_to(_next_tag, maxval);
260 #endif
261  tagvalue = _next_tag++;
262  }
263 
264  if (used_tag_values.count(tagvalue))
265  {
266  // Get the largest value in the used values, and pick one
267  // larger
268  tagvalue = used_tag_values.rbegin()->first+1;
269  timpi_assert(!used_tag_values.count(tagvalue));
270  }
271  if (tagvalue >= _next_tag)
272  _next_tag = tagvalue+1;
273 
274  if (_next_tag >= _max_tag)
275  _next_tag = _max_tag/2;
276 
277  used_tag_values[tagvalue] = 1;
278 
279  return MessageTag(tagvalue, this);
280 }
std::map< int, unsigned int > used_tag_values
Definition: communicator.h:243
static const int invalid_tag
Invalid tag, to allow for default construction.
Definition: message_tag.h:53
void max(const T &r, T &o, Request &req) const
Non-blocking maximum of the local value r into o with the request req.

◆ logical_and() [1/2]

template<typename T >
void TIMPI::Communicator::logical_and ( T &  r) const
inlineinherited

Take a local variable and replace it with the logical_and of its values on all processors.

Containers are replaced element-wise.

◆ logical_and() [2/2]

template<typename T >
void TIMPI::Communicator::logical_and ( const T &  r,
T &  o,
Request req 
) const
inlineinherited

Non-blocking logical_and of the local value r into o with the request req.

◆ logical_or() [1/2]

template<typename T >
void TIMPI::Communicator::logical_or ( T &  r) const
inlineinherited

Take a local variable and replace it with the logical_or of its values on all processors.

Containers are replaced element-wise.

◆ logical_or() [2/2]

template<typename T >
void TIMPI::Communicator::logical_or ( const T &  r,
T &  o,
Request req 
) const
inlineinherited

Non-blocking logical_or of the local value r into o with the request req.

◆ logical_xor() [1/2]

template<typename T >
void TIMPI::Communicator::logical_xor ( T &  r) const
inlineinherited

Take a local variable and replace it with the logical_xor of its values on all processors.

Containers are replaced element-wise.

◆ logical_xor() [2/2]

template<typename T >
void TIMPI::Communicator::logical_xor ( const T &  r,
T &  o,
Request req 
) const
inlineinherited

Non-blocking logical_xor of the local value r into o with the request req.

◆ max() [1/3]

template<typename T >
void TIMPI::Communicator::max ( const T &  r,
T &  o,
Request req 
) const
inlineinherited

◆ max() [2/3]

template<typename T >
void TIMPI::Communicator::max ( T &  r) const
inlineinherited

Take a local variable and replace it with the maximum of it's values on all processors.

Containers are replaced element-wise.

◆ max() [3/3]

template<typename A >
void TIMPI::Communicator::max ( std::vector< bool, A > &  r) const
inlineinherited

Definition at line 2303 of file parallel_implementation.h.

References TIMPI::Communicator::size(), and TIMPI::Communicator::verify().

2304 {
2305  if (this->size() > 1 && !r.empty())
2306  {
2307  TIMPI_LOG_SCOPE("max(vector<bool>)", "Parallel");
2308 
2309  timpi_assert(this->verify(r.size()));
2310 
2311  std::vector<unsigned int> ruint;
2312  pack_vector_bool(r, ruint);
2313  std::vector<unsigned int> temp(ruint.size());
2314  timpi_call_mpi
2315  (TIMPI_ALLREDUCE (ruint.data(), temp.data(),
2316  cast_int<CountType>(ruint.size()),
2317  StandardType<unsigned int>(), MPI_BOR,
2318  this->get()));
2319  unpack_vector_bool(temp, r);
2320  }
2321 }
processor_id_type size() const
Definition: communicator.h:211
timpi_pure bool verify(const T &r) const
Check whether a local variable has the same value on all processors, returning true if it does or fal...

◆ maxloc() [1/3]

template<typename T >
void TIMPI::Communicator::maxloc ( T &  r,
unsigned int &  max_id 
) const
inlineinherited

Take a local variable and replace it with the maximum of it's values on all processors, returning the minimum rank of a processor which originally held the maximum value.

Definition at line 2441 of file parallel_implementation.h.

References TIMPI::ignore(), TIMPI::DataPlusInt< T >::rank, TIMPI::Communicator::rank(), TIMPI::Communicator::size(), and TIMPI::DataPlusInt< T >::val.

Referenced by testMaxloc(), testMaxlocBool(), testMaxlocDouble(), and testMaxlocPair().

2443 {
2444  if (this->size() > 1)
2445  {
2446  TIMPI_LOG_SCOPE("maxloc(scalar)", "Parallel");
2447 
2448  DataPlusInt<T> data_in;
2449  ignore(data_in); // unused ifndef TIMPI_HAVE_MPI
2450  data_in.val = r;
2451  data_in.rank = this->rank();
2452 
2453  timpi_call_mpi
2454  (TIMPI_ALLREDUCE (MPI_IN_PLACE, &data_in, 1,
2455  dataplusint_type_acquire<T>().first,
2456  OpFunction<T>::max_location(), this->get()));
2457  r = data_in.val;
2458  max_id = data_in.rank;
2459  }
2460  else
2461  max_id = this->rank();
2462 }
processor_id_type rank() const
Definition: communicator.h:208
void ignore(const Args &...)
Definition: timpi_assert.h:54
processor_id_type size() const
Definition: communicator.h:211

◆ maxloc() [2/3]

template<typename T , typename A1 , typename A2 >
void TIMPI::Communicator::maxloc ( std::vector< T, A1 > &  r,
std::vector< unsigned int, A2 > &  max_id 
) const
inlineinherited

Take a vector of local variables and replace each entry with the maximum of it's values on all processors.

Set each min_id entry to the minimum rank where a corresponding maximum was found.

Definition at line 2466 of file parallel_implementation.h.

References TIMPI::Communicator::rank(), TIMPI::Communicator::size(), and TIMPI::Communicator::verify().

2468 {
2469  if (this->size() > 1 && !r.empty())
2470  {
2471  TIMPI_LOG_SCOPE("maxloc(vector)", "Parallel");
2472 
2473  timpi_assert(this->verify(r.size()));
2474 
2475  std::vector<DataPlusInt<T>> data_in(r.size());
2476  for (std::size_t i=0; i != r.size(); ++i)
2477  {
2478  data_in[i].val = r[i];
2479  data_in[i].rank = this->rank();
2480  }
2481  std::vector<DataPlusInt<T>> data_out(r.size());
2482 
2483  timpi_call_mpi
2484  (TIMPI_ALLREDUCE(data_in.data(), data_out.data(),
2485  cast_int<CountType>(r.size()),
2486  dataplusint_type_acquire<T>().first,
2487  OpFunction<T>::max_location(),
2488  this->get()));
2489  for (std::size_t i=0; i != r.size(); ++i)
2490  {
2491  r[i] = data_out[i].val;
2492  max_id[i] = data_out[i].rank;
2493  }
2494  }
2495  else if (!r.empty())
2496  {
2497  for (std::size_t i=0; i != r.size(); ++i)
2498  max_id[i] = this->rank();
2499  }
2500 }
processor_id_type rank() const
Definition: communicator.h:208
processor_id_type size() const
Definition: communicator.h:211
timpi_pure bool verify(const T &r) const
Check whether a local variable has the same value on all processors, returning true if it does or fal...

◆ maxloc() [3/3]

template<typename A1 , typename A2 >
void TIMPI::Communicator::maxloc ( std::vector< bool, A1 > &  r,
std::vector< unsigned int, A2 > &  max_id 
) const
inlineinherited

Definition at line 2504 of file parallel_implementation.h.

References TIMPI::Communicator::rank(), TIMPI::Communicator::size(), and TIMPI::Communicator::verify().

2506 {
2507  if (this->size() > 1 && !r.empty())
2508  {
2509  TIMPI_LOG_SCOPE("maxloc(vector<bool>)", "Parallel");
2510 
2511  timpi_assert(this->verify(r.size()));
2512 
2513  std::vector<DataPlusInt<int>> data_in(r.size());
2514  for (std::size_t i=0; i != r.size(); ++i)
2515  {
2516  data_in[i].val = r[i];
2517  data_in[i].rank = this->rank();
2518  }
2519  std::vector<DataPlusInt<int>> data_out(r.size());
2520  timpi_call_mpi
2521  (TIMPI_ALLREDUCE(data_in.data(), data_out.data(),
2522  cast_int<CountType>(r.size()),
2523  StandardType<int>(),
2524  OpFunction<int>::max_location(),
2525  this->get()));
2526  for (std::size_t i=0; i != r.size(); ++i)
2527  {
2528  r[i] = data_out[i].val;
2529  max_id[i] = data_out[i].rank;
2530  }
2531  }
2532  else if (!r.empty())
2533  {
2534  for (std::size_t i=0; i != r.size(); ++i)
2535  max_id[i] = this->rank();
2536  }
2537 }
processor_id_type rank() const
Definition: communicator.h:208
processor_id_type size() const
Definition: communicator.h:211
timpi_pure bool verify(const T &r) const
Check whether a local variable has the same value on all processors, returning true if it does or fal...

◆ min() [1/3]

template<typename T >
void TIMPI::Communicator::min ( const T &  r,
T &  o,
Request req 
) const
inlineinherited

◆ min() [2/3]

template<typename T >
void TIMPI::Communicator::min ( T &  r) const
inlineinherited

Take a local variable and replace it with the minimum of it's values on all processors.

Containers are replaced element-wise.

◆ min() [3/3]

template<typename A >
void TIMPI::Communicator::min ( std::vector< bool, A > &  r) const
inlineinherited

Definition at line 2182 of file parallel_implementation.h.

References TIMPI::Communicator::size(), and TIMPI::Communicator::verify().

2183 {
2184  if (this->size() > 1 && !r.empty())
2185  {
2186  TIMPI_LOG_SCOPE("min(vector<bool>)", "Parallel");
2187 
2188  timpi_assert(this->verify(r.size()));
2189 
2190  std::vector<unsigned int> ruint;
2191  pack_vector_bool(r, ruint);
2192  std::vector<unsigned int> temp(ruint.size());
2193  timpi_call_mpi
2194  (TIMPI_ALLREDUCE
2195  (ruint.data(), temp.data(),
2196  cast_int<CountType>(ruint.size()),
2197  StandardType<unsigned int>(), MPI_BAND, this->get()));
2198  unpack_vector_bool(temp, r);
2199  }
2200 }
processor_id_type size() const
Definition: communicator.h:211
timpi_pure bool verify(const T &r) const
Check whether a local variable has the same value on all processors, returning true if it does or fal...

◆ minloc() [1/3]

template<typename T >
void TIMPI::Communicator::minloc ( T &  r,
unsigned int &  min_id 
) const
inlineinherited

Take a local variable and replace it with the minimum of it's values on all processors, returning the minimum rank of a processor which originally held the minimum value.

Definition at line 2204 of file parallel_implementation.h.

References TIMPI::ignore(), TIMPI::DataPlusInt< T >::rank, TIMPI::Communicator::rank(), TIMPI::Communicator::size(), and TIMPI::DataPlusInt< T >::val.

Referenced by testMinloc(), testMinlocBool(), testMinlocDouble(), and testMinlocPair().

2206 {
2207  if (this->size() > 1)
2208  {
2209  TIMPI_LOG_SCOPE("minloc(scalar)", "Parallel");
2210 
2211  DataPlusInt<T> data_in;
2212  ignore(data_in); // unused ifndef TIMPI_HAVE_MPI
2213  data_in.val = r;
2214  data_in.rank = this->rank();
2215 
2216  timpi_call_mpi
2217  (TIMPI_ALLREDUCE (MPI_IN_PLACE, &data_in, 1,
2218  dataplusint_type_acquire<T>().first,
2219  OpFunction<T>::min_location(), this->get()));
2220  r = data_in.val;
2221  min_id = data_in.rank;
2222  }
2223  else
2224  min_id = this->rank();
2225 }
processor_id_type rank() const
Definition: communicator.h:208
void ignore(const Args &...)
Definition: timpi_assert.h:54
processor_id_type size() const
Definition: communicator.h:211

◆ minloc() [2/3]

template<typename T , typename A1 , typename A2 >
void TIMPI::Communicator::minloc ( std::vector< T, A1 > &  r,
std::vector< unsigned int, A2 > &  min_id 
) const
inlineinherited

Take a vector of local variables and replace each entry with the minimum of it's values on all processors.

Set each min_id entry to the minimum rank where a corresponding minimum was found.

Definition at line 2229 of file parallel_implementation.h.

References TIMPI::Communicator::rank(), TIMPI::Communicator::size(), and TIMPI::Communicator::verify().

2231 {
2232  if (this->size() > 1 && !r.empty())
2233  {
2234  TIMPI_LOG_SCOPE("minloc(vector)", "Parallel");
2235 
2236  timpi_assert(this->verify(r.size()));
2237 
2238  std::vector<DataPlusInt<T>> data_in(r.size());
2239  for (std::size_t i=0; i != r.size(); ++i)
2240  {
2241  data_in[i].val = r[i];
2242  data_in[i].rank = this->rank();
2243  }
2244  std::vector<DataPlusInt<T>> data_out(r.size());
2245 
2246  timpi_call_mpi
2247  (TIMPI_ALLREDUCE (data_in.data(), data_out.data(),
2248  cast_int<CountType>(r.size()),
2249  dataplusint_type_acquire<T>().first,
2250  OpFunction<T>::min_location(), this->get()));
2251  for (std::size_t i=0; i != r.size(); ++i)
2252  {
2253  r[i] = data_out[i].val;
2254  min_id[i] = data_out[i].rank;
2255  }
2256  }
2257  else if (!r.empty())
2258  {
2259  for (std::size_t i=0; i != r.size(); ++i)
2260  min_id[i] = this->rank();
2261  }
2262 }
processor_id_type rank() const
Definition: communicator.h:208
processor_id_type size() const
Definition: communicator.h:211
timpi_pure bool verify(const T &r) const
Check whether a local variable has the same value on all processors, returning true if it does or fal...

◆ minloc() [3/3]

template<typename A1 , typename A2 >
void TIMPI::Communicator::minloc ( std::vector< bool, A1 > &  r,
std::vector< unsigned int, A2 > &  min_id 
) const
inlineinherited

Definition at line 2266 of file parallel_implementation.h.

References TIMPI::Communicator::rank(), TIMPI::Communicator::size(), and TIMPI::Communicator::verify().

2268 {
2269  if (this->size() > 1 && !r.empty())
2270  {
2271  TIMPI_LOG_SCOPE("minloc(vector<bool>)", "Parallel");
2272 
2273  timpi_assert(this->verify(r.size()));
2274 
2275  std::vector<DataPlusInt<int>> data_in(r.size());
2276  for (std::size_t i=0; i != r.size(); ++i)
2277  {
2278  data_in[i].val = r[i];
2279  data_in[i].rank = this->rank();
2280  }
2281  std::vector<DataPlusInt<int>> data_out(r.size());
2282  timpi_call_mpi
2283  (TIMPI_ALLREDUCE
2284  (data_in.data(), data_out.data(),
2285  cast_int<CountType>(r.size()), StandardType<int>(),
2286  OpFunction<int>::min_location(), this->get()));
2287  for (std::size_t i=0; i != r.size(); ++i)
2288  {
2289  r[i] = data_out[i].val;
2290  min_id[i] = data_out[i].rank;
2291  }
2292  }
2293  else if (!r.empty())
2294  {
2295  for (std::size_t i=0; i != r.size(); ++i)
2296  min_id[i] = this->rank();
2297  }
2298 }
processor_id_type rank() const
Definition: communicator.h:208
processor_id_type size() const
Definition: communicator.h:211
timpi_pure bool verify(const T &r) const
Check whether a local variable has the same value on all processors, returning true if it does or fal...

◆ nonblocking_barrier()

void TIMPI::Communicator::nonblocking_barrier ( Request req) const
inherited

Start a barrier that doesn't block.

Definition at line 238 of file communicator.C.

References TIMPI::Request::get(), and TIMPI::Communicator::size().

Referenced by TIMPI::detail::push_parallel_nbx_helper().

239 {
240  if (this->size() > 1)
241  {
242  TIMPI_LOG_SCOPE("nonblocking_barrier()", "Communicator");
243  timpi_call_mpi(MPI_Ibarrier (this->get(), req.get()));
244  }
245 }
processor_id_type size() const
Definition: communicator.h:211

◆ nonblocking_receive_packed_range() [1/3]

template<typename Context , typename OutputIter , typename T >
void TIMPI::Communicator::nonblocking_receive_packed_range ( const unsigned int  src_processor_id,
Context *  context,
OutputIter  out,
const T *  output_type,
Request req,
Status stat,
const MessageTag tag = any_tag 
) const
inlineinherited

Non-Blocking-receive range-of-pointers from one processor.

This is meant to receive messages from nonblocking_send_packed_range

Similar in design to the above receive_packed_range. However, this version requires a Request and a Status.

The Status must be a positively tested Status for a message of this type (i.e. a message does exist). It should most likely be generated by Communicator::packed_range_probe.

Definition at line 1290 of file parallel_implementation.h.

References TIMPI::Request::add_post_wait_work(), TIMPI::Communicator::receive(), and TIMPI::Status::size().

Referenced by TIMPI::push_parallel_packed_range().

1297 {
1298  typedef typename Packing<T>::buffer_type buffer_t;
1299 
1300  // Receive serialized variable size objects as a sequence of
1301  // buffer_t.
1302  // Allocate a buffer on the heap so we don't have to free it until
1303  // after the Request::wait()
1304  std::vector<buffer_t> * buffer = new std::vector<buffer_t>(stat.size());
1305  this->receive(src_processor_id, *buffer, req, tag);
1306 
1307  // Make the Request::wait() handle unpacking the buffer
1308  req.add_post_wait_work
1309  (new PostWaitUnpackBuffer<std::vector<buffer_t>, Context, OutputIter, T>(*buffer, context, out));
1310 
1311  // Make the Request::wait() then handle deleting the buffer
1312  req.add_post_wait_work
1313  (new PostWaitDeleteBuffer<std::vector<buffer_t>>(buffer));
1314 
1315  // The MessageTag should stay registered for the Request lifetime
1316  req.add_post_wait_work
1317  (new PostWaitDereferenceTag(tag));
1318 }
Status receive(const unsigned int dest_processor_id, T &buf, const MessageTag &tag=any_tag) const
Blocking-receive from one processor with data-defined type.

◆ nonblocking_receive_packed_range() [2/3]

template<typename Context , typename OutputIter , typename T >
void TIMPI::Communicator::nonblocking_receive_packed_range ( const unsigned int  src_processor_id,
Context *  context,
OutputIter  out,
const T *  output_type,
Request req,
Status stat,
std::shared_ptr< std::vector< typename TIMPI::Packing< T >::buffer_type >> &  buffer,
const MessageTag tag = any_tag 
) const
inlineinherited

Non-Blocking-receive range-of-pointers from one processor.

This is meant to receive messages from nonblocking_send_packed_range

Similar in design to the above receive_packed_range. However, this version requires a Request and a Status.

The Status must be a positively tested Status for a message of this type (i.e. a message does exist). It should most likely be generated by Communicator::packed_range_probe.

◆ nonblocking_receive_packed_range() [3/3]

template<typename Context , typename OutputIter , typename T >
void TIMPI::Communicator::nonblocking_receive_packed_range ( const unsigned int  src_processor_id,
Context *  context,
OutputIter  out,
const T *  ,
Request req,
Status stat,
std::shared_ptr< std::vector< typename Packing< T >::buffer_type >> &  buffer,
const MessageTag tag 
) const
inlineinherited

Definition at line 1937 of file parallel_implementation.h.

References TIMPI::Request::add_post_wait_work(), TIMPI::Communicator::receive(), and TIMPI::Status::size().

1945 {
1946  // If they didn't pass in a buffer - let's make one
1947  if (buffer == nullptr)
1948  buffer = std::make_shared<std::vector<typename Packing<T>::buffer_type>>();
1949  else
1950  buffer->clear();
1951 
1952  // Receive serialized variable size objects as a sequence of
1953  // buffer_t.
1954  // Allocate a buffer on the heap so we don't have to free it until
1955  // after the Request::wait()
1956  buffer->resize(stat.size());
1957  this->receive(src_processor_id, *buffer, req, tag);
1958 
1959  // Make the Request::wait() handle unpacking the buffer
1960  req.add_post_wait_work
1961  (new PostWaitUnpackBuffer<std::vector<typename Packing<T>::buffer_type>, Context, OutputIter, T>(*buffer, context, out));
1962 
1963  // Make it dereference the shared pointer (possibly freeing the buffer)
1964  req.add_post_wait_work
1965  (new PostWaitDereferenceSharedPtr<std::vector<typename Packing<T>::buffer_type>>(buffer));
1966 }
Status receive(const unsigned int dest_processor_id, T &buf, const MessageTag &tag=any_tag) const
Blocking-receive from one processor with data-defined type.

◆ nonblocking_send_packed_range() [1/3]

template<typename Context , typename Iter >
void TIMPI::Communicator::nonblocking_send_packed_range ( const unsigned int  dest_processor_id,
const Context *  context,
Iter  range_begin,
const Iter  range_end,
Request req,
const MessageTag tag = no_tag 
) const
inlineinherited

Similar to the above Nonblocking send_packed_range with a few important differences:

  1. The total size of the packed buffer MUST be less than std::numeric_limits<int>::max()
  2. Only one message is generated
  3. On the receiving end the message should be tested for using Communicator::packed_range_probe()
  4. The message must be received by Communicator::nonblocking_receive_packed_range()

Definition at line 777 of file parallel_implementation.h.

References TIMPI::Request::add_post_wait_work(), TIMPI::pack_range(), and TIMPI::Communicator::send().

Referenced by TIMPI::push_parallel_packed_range().

783 {
784  // Allocate a buffer on the heap so we don't have to free it until
785  // after the Request::wait()
786  typedef typename std::iterator_traits<Iter>::value_type T;
787  typedef typename Packing<T>::buffer_type buffer_t;
788 
789  if (range_begin != range_end)
790  {
791  std::vector<buffer_t> * buffer = new std::vector<buffer_t>();
792 
793  range_begin =
794  pack_range(context,
795  range_begin,
796  range_end,
797  *buffer,
798  // MPI-2/3 can only use signed integers for size,
799  // and with this API we need to fit a non-blocking
800  // send into one buffer
801  std::numeric_limits<CountType>::max());
802 
803  if (range_begin != range_end)
804  timpi_error_msg("Non-blocking packed range sends cannot exceed " << std::numeric_limits<CountType>::max() << "in size");
805 
806  // Make the Request::wait() handle deleting the buffer
807  req.add_post_wait_work
808  (new PostWaitDeleteBuffer<std::vector<buffer_t>>
809  (buffer));
810 
811  // Non-blocking send of the buffer
812  this->send(dest_processor_id, *buffer, req, tag);
813  }
814 }
Iter pack_range(const Context *context, Iter range_begin, const Iter range_end, std::vector< buffertype > &buffer, std::size_t approx_buffer_size)
Helper function for range packing.
Definition: packing.h:1044
void send(const unsigned int dest_processor_id, const T &buf, const MessageTag &tag=no_tag) const
Blocking-send to one processor with data-defined type.

◆ nonblocking_send_packed_range() [2/3]

template<typename Context , typename Iter >
void TIMPI::Communicator::nonblocking_send_packed_range ( const unsigned int  dest_processor_id,
const Context *  context,
Iter  range_begin,
const Iter  range_end,
Request req,
std::shared_ptr< std::vector< typename TIMPI::Packing< typename std::iterator_traits< Iter >::value_type >::buffer_type >> &  buffer,
const MessageTag tag = no_tag 
) const
inlineinherited

Similar to the above Nonblocking send_packed_range with a few important differences:

  1. The total size of the packed buffer MUST be less than std::numeric_limits<int>::max()
  2. Only one message is generated
  3. On the receiving end the message should be tested for using Communicator::packed_range_probe()
  4. The message must be received by Communicator::nonblocking_receive_packed_range()

◆ nonblocking_send_packed_range() [3/3]

template<typename Context , typename Iter >
void TIMPI::Communicator::nonblocking_send_packed_range ( const unsigned int  dest_processor_id,
const Context *  context,
Iter  range_begin,
const Iter  range_end,
Request req,
std::shared_ptr< std::vector< typename Packing< typename std::iterator_traits< Iter >::value_type >::buffer_type >> &  buffer,
const MessageTag tag 
) const
inlineinherited

Definition at line 1584 of file parallel_implementation.h.

References TIMPI::Request::add_post_wait_work(), TIMPI::pack_range(), and TIMPI::Communicator::send().

1591 {
1592  // Allocate a buffer on the heap so we don't have to free it until
1593  // after the Request::wait()
1594  typedef typename std::iterator_traits<Iter>::value_type T;
1595  typedef typename Packing<T>::buffer_type buffer_t;
1596 
1597  if (range_begin != range_end)
1598  {
1599  if (buffer == nullptr)
1600  buffer = std::make_shared<std::vector<buffer_t>>();
1601  else
1602  buffer->clear();
1603 
1604  range_begin =
1605  pack_range(context,
1606  range_begin,
1607  range_end,
1608  *buffer,
1609  // MPI-2/3 can only use signed integers for size,
1610  // and with this API we need to fit a non-blocking
1611  // send into one buffer
1612  std::numeric_limits<CountType>::max());
1613 
1614  if (range_begin != range_end)
1615  timpi_error_msg("Non-blocking packed range sends cannot exceed " << std::numeric_limits<CountType>::max() << "in size");
1616 
1617  // Make it dereference the shared pointer (possibly freeing the buffer)
1618  req.add_post_wait_work
1619  (new PostWaitDereferenceSharedPtr<std::vector<buffer_t>>(buffer));
1620 
1621  // Non-blocking send of the buffer
1622  this->send(dest_processor_id, *buffer, req, tag);
1623  }
1624 }
Iter pack_range(const Context *context, Iter range_begin, const Iter range_end, std::vector< buffertype > &buffer, std::size_t approx_buffer_size)
Helper function for range packing.
Definition: packing.h:1044
void send(const unsigned int dest_processor_id, const T &buf, const MessageTag &tag=no_tag) const
Blocking-send to one processor with data-defined type.

◆ operator=() [1/2]

Communicator& libMesh::Parallel::Communicator::operator= ( const Communicator )
delete

◆ operator=() [2/2]

Communicator& libMesh::Parallel::Communicator::operator= ( Communicator &&  )
default

◆ packed_range_probe()

template<typename T >
Status TIMPI::Communicator::packed_range_probe ( const unsigned int  src_processor_id,
const MessageTag tag,
bool &  flag 
) const
inlineinherited

Non-Blocking message probe for a packed range message.

Allows information about a message to be examined before the message is actually received.

Template type must match the object type that will be in the packed range

Parameters
src_processor_idThe processor the message is expected from or TIMPI::any_source
tagThe message tag or TIMPI::any_tag
flagOutput. True if a message exists. False otherwise.

Referenced by TIMPI::push_parallel_packed_range().

◆ possibly_receive() [1/5]

template<typename T , typename A , typename std::enable_if< std::is_base_of< DataType, StandardType< T >>::value, int >::type = 0>
bool TIMPI::Communicator::possibly_receive ( unsigned int &  src_processor_id,
std::vector< T, A > &  buf,
Request req,
const MessageTag tag 
) const
inlineinherited

Nonblocking-receive from one processor with user-defined type.

Checks to see if a message can be received from the src_processor_id . If so, it starts a non-blocking receive using the passed in request and returns true

Otherwise - if there is no message to receive it returns false

Note: The buf does NOT need to be properly sized before this call this will resize the buffer automatically

Parameters
src_processor_idThe pid to receive from or "any". will be set to the actual src being received from
bufThe buffer to receive into
reqThe request to use
tagThe tag to use

Referenced by TIMPI::push_parallel_vector_data().

◆ possibly_receive() [2/5]

template<typename T , typename A , typename std::enable_if< Has_buffer_type< Packing< T >>::value, int >::type = 0>
bool TIMPI::Communicator::possibly_receive ( unsigned int &  src_processor_id,
std::vector< T, A > &  buf,
Request req,
const MessageTag tag 
) const
inlineinherited

dispatches to possibly_receive_packed_range

Parameters
src_processor_idThe pid to receive from or "any". will be set to the actual src being received from
bufThe buffer to receive into
reqThe request to use
tagThe tag to use

◆ possibly_receive() [3/5]

template<typename T , typename A , typename std::enable_if< std::is_base_of< DataType, StandardType< T >>::value, int >::type >
bool TIMPI::Communicator::possibly_receive ( unsigned int &  src_processor_id,
std::vector< T, A > &  buf,
const DataType type,
Request req,
const MessageTag tag 
) const
inlineinherited

Nonblocking-receive from one processor with user-defined type.

As above, but with manually-specified data type.

Parameters
src_processor_idThe pid to receive from or "any". will be set to the actual src being received from
bufThe buffer to receive into
typeThe intrinsic datatype to receive
reqThe request to use
tagThe tag to use

Definition at line 1971 of file parallel_implementation.h.

References TIMPI::Request::add_post_wait_work(), TIMPI::any_source, TIMPI::Request::get(), TIMPI::Status::get(), TIMPI::Status::size(), TIMPI::Communicator::size(), TIMPI::Status::source(), and TIMPI::MessageTag::value().

1976 {
1977  TIMPI_LOG_SCOPE("possibly_receive()", "Parallel");
1978 
1979  Status stat(type);
1980 
1981  int int_flag = 0;
1982 
1983  timpi_assert(src_processor_id < this->size() ||
1984  src_processor_id == any_source);
1985 
1986  timpi_call_mpi(MPI_Iprobe(int(src_processor_id),
1987  tag.value(),
1988  this->get(),
1989  &int_flag,
1990  stat.get()));
1991 
1992  if (int_flag)
1993  {
1994  buf.resize(stat.size());
1995 
1996  src_processor_id = stat.source();
1997 
1998  timpi_call_mpi
1999  (TIMPI_IRECV(buf.data(), cast_int<CountType>(buf.size()), type,
2000  src_processor_id, tag.value(), this->get(),
2001  req.get()));
2002 
2003  // The MessageTag should stay registered for the Request lifetime
2004  req.add_post_wait_work
2005  (new PostWaitDereferenceTag(tag));
2006  }
2007 
2008  return int_flag;
2009 }
const unsigned int any_source
Processor id meaning "Accept from any source".
Definition: communicator.h:84
processor_id_type size() const
Definition: communicator.h:211

◆ possibly_receive() [4/5]

template<typename T , typename A , typename std::enable_if< Has_buffer_type< Packing< T >>::value, int >::type >
bool TIMPI::Communicator::possibly_receive ( unsigned int &  src_processor_id,
std::vector< T, A > &  buf,
const NotADataType type,
Request req,
const MessageTag tag 
) const
inlineinherited

Nonblocking-receive from one processor with user-defined type.

Dispatches to possibly_receive_packed_range

Parameters
src_processor_idThe pid to receive from or "any". will be set to the actual src being received from
bufThe buffer to receive into
typeThe packable type to receive
reqThe request to use
tagThe tag to use

Definition at line 2012 of file parallel_implementation.h.

References TIMPI::Communicator::possibly_receive_packed_range().

2017 {
2018  TIMPI_LOG_SCOPE("possibly_receive()", "Parallel");
2019 
2020  return this->possibly_receive_packed_range(src_processor_id,
2021  (void *)(nullptr),
2022  std::inserter(buf, buf.end()),
2023  (T *)(nullptr),
2024  req,
2025  tag);
2026 }
bool possibly_receive_packed_range(unsigned int &src_processor_id, Context *context, OutputIter out, const T *output_type, Request &req, const MessageTag &tag) const
Nonblocking packed range receive from one processor with user-defined type.

◆ possibly_receive() [5/5]

template<typename T , typename A1 , typename A2 >
bool TIMPI::Communicator::possibly_receive ( unsigned int &  src_processor_id,
std::vector< std::vector< T, A1 >, A2 > &  buf,
const DataType type,
Request req,
const MessageTag tag 
) const
inlineinherited

Definition at line 2031 of file parallel_implementation.h.

References TIMPI::Request::add_post_wait_work(), TIMPI::any_source, TIMPI::Status::get(), TIMPI::Communicator::receive(), TIMPI::Status::size(), TIMPI::Communicator::size(), TIMPI::Status::source(), and TIMPI::MessageTag::value().

2036 {
2037  TIMPI_LOG_SCOPE("possibly_receive()", "Parallel");
2038 
2039  Status stat(type);
2040 
2041  int int_flag = 0;
2042 
2043  timpi_assert(src_processor_id < this->size() ||
2044  src_processor_id == any_source);
2045 
2046  timpi_call_mpi(MPI_Iprobe(int(src_processor_id),
2047  tag.value(),
2048  this->get(),
2049  &int_flag,
2050  stat.get()));
2051 
2052  if (int_flag)
2053  {
2054  src_processor_id = stat.source();
2055 
2056  std::vector<char> * recvbuf =
2057  new std::vector<char>(stat.size(StandardType<char>()));
2058 
2059  this->receive(src_processor_id, *recvbuf, MPI_PACKED, req, tag);
2060 
2061  // When we wait on the receive, we'll unpack the temporary buffer
2062  req.add_post_wait_work
2063  (new PostWaitUnpackNestedBuffer<std::vector<std::vector<T,A1>,A2>>
2064  (*recvbuf, buf, type, *this));
2065 
2066  // And then we'll free the temporary buffer
2067  req.add_post_wait_work
2068  (new PostWaitDeleteBuffer<std::vector<char>>(recvbuf));
2069 
2070  // The MessageTag should stay registered for the Request lifetime
2071  req.add_post_wait_work
2072  (new PostWaitDereferenceTag(tag));
2073  }
2074 
2075  return int_flag;
2076 }
const unsigned int any_source
Processor id meaning "Accept from any source".
Definition: communicator.h:84
processor_id_type size() const
Definition: communicator.h:211
Status receive(const unsigned int dest_processor_id, T &buf, const MessageTag &tag=any_tag) const
Blocking-receive from one processor with data-defined type.

◆ possibly_receive_packed_range()

template<typename Context , typename OutputIter , typename T >
bool TIMPI::Communicator::possibly_receive_packed_range ( unsigned int &  src_processor_id,
Context *  context,
OutputIter  out,
const T *  output_type,
Request req,
const MessageTag tag 
) const
inherited

Nonblocking packed range receive from one processor with user-defined type.

Checks to see if a message can be received from the src_processor_id . If so, it starts a nonblocking packed range receive using the passed in request and returns true

Otherwise - if there is no message to receive it returns false

void Parallel::unpack(const T *, OutputIter data, const Context *) is used to unserialize type T

Parameters
src_processor_idThe pid to receive from or "any". will be set to the actual src being receieved from
contextContext pointer that will be passed into the unpack functions
outThe output iterator
output_typeThe intrinsic datatype to receive
reqThe request to use
tagThe tag to use

Referenced by TIMPI::Communicator::possibly_receive(), and TIMPI::push_parallel_packed_range().

◆ probe()

status TIMPI::Communicator::probe ( const unsigned int  src_processor_id,
const MessageTag tag = any_tag 
) const
inherited

Blocking message probe.

Allows information about a message to be examined before the message is actually received.

Definition at line 283 of file communicator.C.

References TIMPI::any_source, TIMPI::ignore(), TIMPI::Communicator::size(), and TIMPI::MessageTag::value().

Referenced by TIMPI::pull_parallel_vector_data(), TIMPI::detail::push_parallel_alltoall_helper(), and TIMPI::Communicator::receive().

285 {
286  TIMPI_LOG_SCOPE("probe()", "Communicator");
287 
288 #ifndef TIMPI_HAVE_MPI
289  timpi_not_implemented();
290  ignore(src_processor_id, tag);
291 #endif
292 
293  status stat;
294 
295  timpi_assert(src_processor_id < this->size() ||
296  src_processor_id == any_source);
297 
298  timpi_call_mpi
299  (MPI_Probe (int(src_processor_id), tag.value(), this->get(), &stat));
300 
301  return stat;
302 }
void ignore(const Args &...)
Definition: timpi_assert.h:54
const unsigned int any_source
Processor id meaning "Accept from any source".
Definition: communicator.h:84
MPI_Status status
Status object for querying messages.
Definition: status.h:44
processor_id_type size() const
Definition: communicator.h:211

◆ product() [1/2]

template<typename T >
void TIMPI::Communicator::product ( T &  r) const
inlineinherited

Take a local variable and replace it with the product of its values on all processors.

Containers are replaced element-wise.

◆ product() [2/2]

template<typename T >
void TIMPI::Communicator::product ( const T &  r,
T &  o,
Request req 
) const
inlineinherited

Non-blocking product of the local value r into o with the request req.

◆ rank()

processor_id_type TIMPI::Communicator::rank ( ) const
inlineinherited

Definition at line 208 of file communicator.h.

References TIMPI::Communicator::_rank.

Referenced by TIMPI::Communicator::broadcast(), TIMPI::detail::empty_send_assertion(), fill_data(), fill_scalar_data(), fill_vector_data(), TIMPI::Communicator::maxloc(), TIMPI::Communicator::minloc(), TIMPI::pull_parallel_vector_data(), TIMPI::detail::push_parallel_alltoall_helper(), TIMPI::detail::push_parallel_nbx_helper(), TIMPI::detail::push_parallel_roundrobin_helper(), TIMPI::report_here(), TIMPI::Communicator::send_receive(), TIMPI::Communicator::send_receive_packed_range(), testAllGather(), testAllGatherHalfEmptyVectorString(), testAllGatherString(), testAllGatherVectorString(), testAllGatherVectorVector(), testAllGatherVectorVectorInPlace(), testAllGatherVectorVectorPacked(), testArrayContainerAllGather(), testBigUnion(), testBroadcast(), testBroadcastArrayType(), testBroadcastNestedType(), testBroadcastString(), testContainerAllGather(), testContainerBroadcast(), testContainerSendReceive(), testEmptyEntry(), testGather(), testGatherString(), testGatherString2(), testGettableStringAllGather(), testIrecvSend(), testIsendRecv(), testLargeSetUnion(), testMapContainerAllGather(), testMapMap(), testMapMax(), testMapSet(), testMax(), testMaxloc(), testMaxlocBool(), testMaxlocDouble(), testMaxlocPair(), testMaxVecBool(), testMin(), testMinLarge(), testMinloc(), testMinlocBool(), testMinlocDouble(), testMinlocPair(), testMinVecBool(), testMPIULongMin(), testNestingAllGather(), testNonblockingMax(), testNonblockingMin(), testNonblockingString(), testNonblockingSum(), testNonblockingTest(), testNonblockingWaitany(), testNonFixedTypeMapMax(), testNonFixedTypeSum(), testNullAllGather(), testNullSendReceive(), testPackedSetUnion(), testPairContainerAllGather(), testPush(), testPushImpl(), testPushMove(), testPushMultimapImpl(), testPushMultimapVecVecImpl(), testPushPackedImpl(), testPushPackedImplMove(), testPushPackedNestedImpl(), testPushVecVecImpl(), testRecvIsendSets(), testRecvIsendVecVecs(), testScatter(), testSemiVerifyInf(), testSemiVerifyString(), testSemiVerifyType(), testSemiVerifyVector(), testSendRecvVecVecs(), testSplit(), testSplitByType(), testSum(), testSumOpFunction(), testTupleContainerAllGather(), testTupleStringAllGather(), testUnion(), testVectorOfContainersAllGather(), and testVectorOfContainersBroadcast().

208 { return _rank; }
processor_id_type _rank
Definition: communicator.h:237

◆ receive() [1/6]

template<typename T >
Status TIMPI::Communicator::receive ( const unsigned int  dest_processor_id,
T &  buf,
const MessageTag tag = any_tag 
) const
inlineinherited

Blocking-receive from one processor with data-defined type.

We do not currently support receives on one processor without MPI.

Definition at line 862 of file parallel_implementation.h.

References TIMPI::any_source, TIMPI::Status::get(), TIMPI::Communicator::probe(), TIMPI::Communicator::size(), and TIMPI::MessageTag::value().

Referenced by TIMPI::Communicator::nonblocking_receive_packed_range(), TIMPI::Communicator::possibly_receive(), TIMPI::pull_parallel_vector_data(), TIMPI::push_parallel_vector_data(), TIMPI::Communicator::receive(), TIMPI::Communicator::receive_packed_range(), testIrecvSend(), testIsendRecv(), testNonblockingString(), testRecvIsendSets(), testRecvIsendVecVecs(), and testSendRecvVecVecs().

865 {
866  TIMPI_LOG_SCOPE("receive()", "Parallel");
867 
868  // Get the status of the message, explicitly provide the
869  // datatype so we can later query the size
870  Status stat(this->probe(src_processor_id, tag), StandardType<T>(&buf));
871 
872  timpi_assert(src_processor_id < this->size() ||
873  src_processor_id == any_source);
874 
875  timpi_call_mpi
876  (TIMPI_RECV (&buf, 1, StandardType<T>(&buf), src_processor_id,
877  tag.value(), this->get(), stat.get()));
878 
879  return stat;
880 }
const unsigned int any_source
Processor id meaning "Accept from any source".
Definition: communicator.h:84
processor_id_type size() const
Definition: communicator.h:211
status probe(const unsigned int src_processor_id, const MessageTag &tag=any_tag) const
Blocking message probe.
Definition: communicator.C:283

◆ receive() [2/6]

template<typename T >
void TIMPI::Communicator::receive ( const unsigned int  dest_processor_id,
T &  buf,
Request req,
const MessageTag tag = any_tag 
) const
inlineinherited

Nonblocking-receive from one processor with data-defined type.

Definition at line 885 of file parallel_implementation.h.

References TIMPI::Request::add_post_wait_work(), TIMPI::any_source, TIMPI::Request::get(), TIMPI::Communicator::size(), and TIMPI::MessageTag::value().

889 {
890  TIMPI_LOG_SCOPE("receive()", "Parallel");
891 
892  timpi_assert(src_processor_id < this->size() ||
893  src_processor_id == any_source);
894 
895  timpi_call_mpi
896  (TIMPI_IRECV (&buf, 1, StandardType<T>(&buf), src_processor_id,
897  tag.value(), this->get(), req.get()));
898 
899  // The MessageTag should stay registered for the Request lifetime
900  req.add_post_wait_work
901  (new PostWaitDereferenceTag(tag));
902 }
const unsigned int any_source
Processor id meaning "Accept from any source".
Definition: communicator.h:84
processor_id_type size() const
Definition: communicator.h:211

◆ receive() [3/6]

template<typename T >
Status TIMPI::Communicator::receive ( const unsigned int  dest_processor_id,
T &  buf,
const DataType type,
const MessageTag tag = any_tag 
) const
inlineinherited

Blocking-receive from one processor with user-defined type.

If T is a container, container-of-containers, etc., then type should be the DataType of the underlying fixed-size entries in the container(s).

Definition at line 155 of file serial_implementation.h.

159 { timpi_not_implemented(); return Status(); }

◆ receive() [4/6]

template<typename T >
void TIMPI::Communicator::receive ( const unsigned int  dest_processor_id,
T &  buf,
const DataType type,
Request req,
const MessageTag tag = any_tag 
) const
inlineinherited

Nonblocking-receive from one processor with user-defined type.

If T is a container, container-of-containers, etc., then type should be the DataType of the underlying fixed-size entries in the container(s).

Definition at line 162 of file serial_implementation.h.

167 { timpi_not_implemented(); }

◆ receive() [5/6]

template<typename T >
Status TIMPI::Communicator::receive ( const unsigned int  src_processor_id,
std::basic_string< T > &  buf,
const MessageTag tag 
) const
inlineinherited

Definition at line 818 of file parallel_implementation.h.

References TIMPI::Communicator::receive().

821 {
822  std::vector<T> tempbuf; // Officially C++ won't let us get a
823  // modifiable array from a string
824 
825  Status stat = this->receive(src_processor_id, tempbuf, tag);
826  buf.assign(tempbuf.begin(), tempbuf.end());
827  return stat;
828 }
Status receive(const unsigned int dest_processor_id, T &buf, const MessageTag &tag=any_tag) const
Blocking-receive from one processor with data-defined type.

◆ receive() [6/6]

template<typename T >
void TIMPI::Communicator::receive ( const unsigned int  src_processor_id,
std::basic_string< T > &  buf,
Request req,
const MessageTag tag 
) const
inlineinherited

Definition at line 833 of file parallel_implementation.h.

References TIMPI::Request::add_post_wait_work(), and TIMPI::Communicator::receive().

837 {
838  // Officially C++ won't let us get a modifiable array from a
839  // string, and we can't even put one on the stack for the
840  // non-blocking case.
841  std::vector<T> * tempbuf = new std::vector<T>(buf.size());
842 
843  // We can clear the string, but the Request::wait() will need to
844  // handle copying our temporary buffer to it
845  buf.clear();
846 
847  req.add_post_wait_work
848  (new PostWaitCopyBuffer<std::vector<T>,
849  std::back_insert_iterator<std::basic_string<T>>>
850  (*tempbuf, std::back_inserter(buf)));
851 
852  // Make the Request::wait() then handle deleting the buffer
853  req.add_post_wait_work
854  (new PostWaitDeleteBuffer<std::vector<T>>(tempbuf));
855 
856  this->receive(src_processor_id, *tempbuf, req, tag);
857 }
Status receive(const unsigned int dest_processor_id, T &buf, const MessageTag &tag=any_tag) const
Blocking-receive from one processor with data-defined type.

◆ receive_packed_range()

template<typename Context , typename OutputIter , typename T >
void TIMPI::Communicator::receive_packed_range ( const unsigned int  dest_processor_id,
Context *  context,
OutputIter  out,
const T *  output_type,
const MessageTag tag = any_tag 
) const
inlineinherited

Blocking-receive range-of-pointers from one processor.

This function does not receive raw pointers, but rather constructs new objects whose contents match the objects pointed to by the sender.

The objects will be of type T = iterator_traits<OutputIter>::value_type.

Using std::back_inserter as the output iterator allows receive to fill any container type. Using some null_output_iterator allows the receive to be dealt with solely by TIMPI::unpack(), for objects whose unpack() is written so as to not leak memory when used in this fashion.

A future version of this method should be created to preallocate memory when receiving vectors...

void TIMPI::unpack(vector<int>::iterator in, T ** out, Context *) is used to unserialize type T, typically into a new heap-allocated object whose pointer is returned as *out.

unsigned int TIMPI::packed_size(const T *, vector<int>::const_iterator) is used to advance to the beginning of the next object's data.

Definition at line 1226 of file parallel_implementation.h.

References TIMPI::Communicator::receive(), TIMPI::Status::source(), TIMPI::Status::tag(), and TIMPI::unpack_range().

Referenced by TIMPI::Communicator::send_receive_packed_range().

1231 {
1232  typedef typename Packing<T>::buffer_type buffer_t;
1233 
1234  // Receive serialized variable size objects as sequences of buffer_t
1235  std::size_t total_buffer_size = 0;
1236  Status stat = this->receive(src_processor_id, total_buffer_size, tag);
1237 
1238  // Use stat.source() and stat.tag() in subsequent receives - if
1239  // src_processor_id is or tag is "any" then we want to be sure we
1240  // try to receive messages all corresponding to the same send.
1241 
1242  std::size_t received_buffer_size = 0;
1243 
1244  // OutputIter might not have operator= implemented; for maximum
1245  // compatibility we'll rely on its copy constructor.
1246  std::unique_ptr<OutputIter> next_out_iter =
1247  std::make_unique<OutputIter>(out_iter);
1248 
1249  while (received_buffer_size < total_buffer_size)
1250  {
1251  std::vector<buffer_t> buffer;
1252  this->receive(stat.source(), buffer, MessageTag(stat.tag()));
1253  received_buffer_size += buffer.size();
1254  auto return_out_iter = unpack_range
1255  (buffer, context, *next_out_iter, output_type);
1256  next_out_iter = std::make_unique<OutputIter>(return_out_iter);
1257  }
1258 }
OutputIter unpack_range(const std::vector< buffertype > &buffer, Context *context, OutputIter out_iter, const T *)
Helper function for range unpacking.
Definition: packing.h:1103
Status receive(const unsigned int dest_processor_id, T &buf, const MessageTag &tag=any_tag) const
Blocking-receive from one processor with data-defined type.

◆ reference_unique_tag()

void TIMPI::Communicator::reference_unique_tag ( int  tagvalue) const
inherited

Reference an already-acquired tag, so that we know it will be dereferenced multiple times before we can re-release it.

Definition at line 37 of file communicator.C.

References TIMPI::Communicator::used_tag_values.

Referenced by TIMPI::MessageTag::MessageTag(), and TIMPI::MessageTag::operator=().

38 {
39  // This had better be an already-acquired tag.
40  timpi_assert(used_tag_values.count(tagvalue));
41 
42  used_tag_values[tagvalue]++;
43 }
std::map< int, unsigned int > used_tag_values
Definition: communicator.h:243

◆ scatter() [1/5]

template<typename T , typename A >
void TIMPI::Communicator::scatter ( const std::vector< T, A > &  data,
T &  recv,
const unsigned int  root_id = 0 
) const
inlineinherited

Take a vector of local variables and scatter the ith item to the ith processor in the communicator.

The result is saved into recv.

Referenced by testScatter().

◆ scatter() [2/5]

template<typename T , typename A >
void TIMPI::Communicator::scatter ( const std::vector< T, A > &  data,
std::vector< T, A > &  recv,
const unsigned int  root_id = 0 
) const
inlineinherited

Take a vector of local variables and scatter the ith equal-sized chunk to the ith processor in the communicator.

The data size must be a multiple of the communicator size. The result is saved into recv buffer. The recv buffer does not have to be sized prior to this operation.

◆ scatter() [3/5]

template<typename T , typename A1 , typename A2 >
void TIMPI::Communicator::scatter ( const std::vector< T, A1 > &  data,
const std::vector< CountType, A2 >  counts,
std::vector< T, A1 > &  recv,
const unsigned int  root_id = 0 
) const
inlineinherited

Take a vector of local variables and scatter the ith variable-sized chunk to the ith processor in the communicator.

The counts vector should contain the number of items for each processor. The result is saved into recv buffer. The recv buffer does not have to be sized prior to this operation.

◆ scatter() [4/5]

template<typename T , typename A1 , typename A2 >
void TIMPI::Communicator::scatter ( const std::vector< T, A1 > &  data,
const std::vector< int, A2 >  counts,
std::vector< T, A1 > &  recv,
const unsigned int  root_id = 0 
) const
inlineinherited

vector<int> based scatter, for backwards compatibility

◆ scatter() [5/5]

template<typename T , typename A1 , typename A2 >
void TIMPI::Communicator::scatter ( const std::vector< std::vector< T, A1 >, A2 > &  data,
std::vector< T, A1 > &  recv,
const unsigned int  root_id = 0,
const bool  identical_buffer_sizes = false 
) const
inlineinherited

Take a vector of vectors and scatter the ith inner vector to the ith processor in the communicator.

The result is saved into recv buffer. The recv buffer does not have to be sized prior to this operation.

◆ semiverify() [1/2]

template<typename T >
timpi_pure bool TIMPI::Communicator::semiverify ( const T *  r) const
inlineinherited

Check whether a local pointer points to the same value on all processors where it is not null, returning true if it does or false if not.

Useful in assertions and possibly in user error checking.

Containers must have the same value in every entry on all processors where the pointer is not null for this function to return true.

Referenced by testSemiVerifyInf(), testSemiVerifyString(), testSemiVerifyType(), and testSemiVerifyVector().

◆ semiverify() [2/2]

template<typename T >
bool TIMPI::Communicator::semiverify ( const T *  r) const
inlineinherited

Definition at line 2112 of file parallel_implementation.h.

References TIMPI::Communicator::max(), TIMPI::Communicator::min(), and TIMPI::Communicator::size().

2113 {
2114  if (this->size() > 1 && Attributes<T>::has_min_max == true)
2115  {
2116  T tempmin, tempmax;
2117  if (r)
2118  tempmin = tempmax = *r;
2119  else
2120  {
2121  Attributes<T>::set_highest(tempmin);
2122  Attributes<T>::set_lowest(tempmax);
2123  }
2124  this->min(tempmin);
2125  this->max(tempmax);
2126  bool invalid = r && ((*r != tempmin) ||
2127  (*r != tempmax));
2128  this->max(invalid);
2129  return !invalid;
2130  }
2131 
2132  static_assert(Attributes<T>::has_min_max,
2133  "Tried to semiverify an unverifiable type");
2134 
2135  return true;
2136 }
processor_id_type size() const
Definition: communicator.h:211
void min(const T &r, T &o, Request &req) const
Non-blocking minimum of the local value r into o with the request req.
static const bool has_min_max
Definition: attributes.h:48
void max(const T &r, T &o, Request &req) const
Non-blocking maximum of the local value r into o with the request req.

◆ send() [1/7]

template<typename T >
void TIMPI::Communicator::send ( const unsigned int  dest_processor_id,
const std::basic_string< T > &  buf,
const MessageTag tag 
) const
inlineinherited

Definition at line 303 of file parallel_implementation.h.

References TIMPI::Communicator::send_mode(), TIMPI::Communicator::size(), TIMPI::Communicator::SYNCHRONOUS, and TIMPI::MessageTag::value().

306 {
307  TIMPI_LOG_SCOPE("send()", "Parallel");
308 
309  T * dataptr = buf.empty() ? nullptr : const_cast<T *>(buf.data());
310 
311  timpi_assert_less(dest_processor_id, this->size());
312 
313  timpi_call_mpi
314  (((this->send_mode() == SYNCHRONOUS) ?
315  TIMPI_SSEND : TIMPI_SEND)
316  (dataptr, cast_int<CountType>(buf.size()),
317  StandardType<T>(dataptr), dest_processor_id, tag.value(),
318  this->get()));
319 }
processor_id_type size() const
Definition: communicator.h:211
SendMode send_mode() const
Gets the user-requested SendMode.
Definition: communicator.h:338

◆ send() [2/7]

template<typename T >
void TIMPI::Communicator::send ( const unsigned int  dest_processor_id,
const std::basic_string< T > &  buf,
Request req,
const MessageTag tag 
) const
inlineinherited

Definition at line 324 of file parallel_implementation.h.

References TIMPI::Request::add_post_wait_work(), TIMPI::Request::get(), TIMPI::Communicator::send_mode(), TIMPI::Communicator::size(), TIMPI::Communicator::SYNCHRONOUS, and TIMPI::MessageTag::value().

328 {
329  TIMPI_LOG_SCOPE("send()", "Parallel");
330 
331  T * dataptr = buf.empty() ? nullptr : const_cast<T *>(buf.data());
332 
333  timpi_assert_less(dest_processor_id, this->size());
334 
335  timpi_call_mpi
336  (((this->send_mode() == SYNCHRONOUS) ?
337  TIMPI_ISSEND : TIMPI_ISEND)
338  (dataptr, cast_int<CountType>(buf.size()),
339  StandardType<T>(dataptr), dest_processor_id, tag.value(),
340  this->get(), req.get()));
341 
342  // The MessageTag should stay registered for the Request lifetime
343  req.add_post_wait_work
344  (new PostWaitDereferenceTag(tag));
345 }
processor_id_type size() const
Definition: communicator.h:211
SendMode send_mode() const
Gets the user-requested SendMode.
Definition: communicator.h:338

◆ send() [3/7]

template<typename T >
void TIMPI::Communicator::send ( const unsigned int  dest_processor_id,
const T &  buf,
const MessageTag tag = no_tag 
) const
inlineinherited

Blocking-send to one processor with data-defined type.

We do not currently support sends on one processor without MPI.

Definition at line 350 of file parallel_implementation.h.

References TIMPI::Communicator::send_mode(), TIMPI::Communicator::size(), TIMPI::Communicator::SYNCHRONOUS, and TIMPI::MessageTag::value().

Referenced by TIMPI::Communicator::nonblocking_send_packed_range(), TIMPI::pull_parallel_vector_data(), TIMPI::push_parallel_vector_data(), TIMPI::Communicator::send_packed_range(), TIMPI::Communicator::send_receive(), testIrecvSend(), testIsendRecv(), testNonblockingString(), testRecvIsendSets(), testRecvIsendVecVecs(), and testSendRecvVecVecs().

353 {
354  TIMPI_LOG_SCOPE("send()", "Parallel");
355 
356  T * dataptr = const_cast<T*> (&buf);
357 
358  timpi_assert_less(dest_processor_id, this->size());
359 
360  timpi_call_mpi
361  (((this->send_mode() == SYNCHRONOUS) ?
362  TIMPI_SSEND : TIMPI_SEND)
363  (dataptr, 1, StandardType<T>(dataptr), dest_processor_id,
364  tag.value(), this->get()));
365 }
processor_id_type size() const
Definition: communicator.h:211
SendMode send_mode() const
Gets the user-requested SendMode.
Definition: communicator.h:338

◆ send() [4/7]

template<typename T >
void TIMPI::Communicator::send ( const unsigned int  dest_processor_id,
const T &  buf,
Request req,
const MessageTag tag = no_tag 
) const
inlineinherited

Nonblocking-send to one processor with data-defined type.

Definition at line 370 of file parallel_implementation.h.

References TIMPI::Request::add_post_wait_work(), TIMPI::Request::get(), TIMPI::Communicator::send_mode(), TIMPI::Communicator::size(), TIMPI::Communicator::SYNCHRONOUS, and TIMPI::MessageTag::value().

374 {
375  TIMPI_LOG_SCOPE("send()", "Parallel");
376 
377  T * dataptr = const_cast<T*>(&buf);
378 
379  timpi_assert_less(dest_processor_id, this->size());
380 
381  timpi_call_mpi
382  (((this->send_mode() == SYNCHRONOUS) ?
383  TIMPI_ISSEND : TIMPI_ISEND)
384  (dataptr, 1, StandardType<T>(dataptr), dest_processor_id,
385  tag.value(), this->get(), req.get()));
386 
387  // The MessageTag should stay registered for the Request lifetime
388  req.add_post_wait_work
389  (new PostWaitDereferenceTag(tag));
390 }
processor_id_type size() const
Definition: communicator.h:211
SendMode send_mode() const
Gets the user-requested SendMode.
Definition: communicator.h:338

◆ send() [5/7]

template<typename T >
void TIMPI::Communicator::send ( const unsigned int  dest_processor_id,
const T &  buf,
const DataType type,
const MessageTag tag = no_tag 
) const
inlineinherited

Blocking-send to one processor with user-defined type.

If T is a container, container-of-containers, etc., then type should be the DataType of the underlying fixed-size entries in the container(s).

Definition at line 78 of file serial_implementation.h.

82 { timpi_not_implemented(); }

◆ send() [6/7]

template<typename T >
void TIMPI::Communicator::send ( const unsigned int  dest_processor_id,
const T &  buf,
const DataType type,
Request req,
const MessageTag tag = no_tag 
) const
inlineinherited

Nonblocking-send to one processor with user-defined type.

If T is a container, container-of-containers, etc., then type should be the DataType of the underlying fixed-size entries in the container(s).

Definition at line 85 of file serial_implementation.h.

90 { timpi_not_implemented(); }

◆ send() [7/7]

template<typename T >
void TIMPI::Communicator::send ( const unsigned int  dest_processor_id,
const T &  buf,
const NotADataType type,
Request req,
const MessageTag tag = no_tag 
) const
inlineinherited

Nonblocking-send to one processor with user-defined packable type.

Packing<T> must be defined for T

Definition at line 93 of file serial_implementation.h.

98 { timpi_not_implemented(); }

◆ send_mode() [1/2]

void TIMPI::Communicator::send_mode ( const SendMode  sm)
inlineinherited

◆ send_mode() [2/2]

SendMode TIMPI::Communicator::send_mode ( ) const
inlineinherited

◆ send_packed_range() [1/2]

template<typename Context , typename Iter >
void TIMPI::Communicator::send_packed_range ( const unsigned int  dest_processor_id,
const Context *  context,
Iter  range_begin,
const Iter  range_end,
const MessageTag tag = no_tag,
std::size_t  approx_buffer_size = 1000000 
) const
inlineinherited

Blocking-send range-of-pointers to one processor.

This function does not send the raw pointers, but rather constructs new objects at the other end whose contents match the objects pointed to by the sender.

void TIMPI::pack(const T *, vector<int> & data, const Context *) is used to serialize type T onto the end of a data vector.

unsigned int TIMPI::packable_size(const T *, const Context *) is used to allow data vectors to reserve memory, and for additional error checking

The approximate maximum size (in entries; number of bytes will likely be 4x or 8x larger) to use in a single data vector buffer can be specified for performance or memory usage reasons; if the range cannot be packed into a single buffer of this size then multiple buffers and messages will be used.

Definition at line 648 of file parallel_implementation.h.

References TIMPI::pack_range(), TIMPI::packed_range_size(), and TIMPI::Communicator::send().

Referenced by TIMPI::Communicator::send_receive_packed_range().

654 {
655  // We will serialize variable size objects from *range_begin to
656  // *range_end as a sequence of plain data (e.g. ints) in this buffer
657  typedef typename std::iterator_traits<Iter>::value_type T;
658 
659  std::size_t total_buffer_size =
660  packed_range_size (context, range_begin, range_end);
661 
662  this->send(dest_processor_id, total_buffer_size, tag);
663 
664 #ifdef DEBUG
665  std::size_t used_buffer_size = 0;
666 #endif
667 
668  while (range_begin != range_end)
669  {
670  timpi_assert_greater (std::distance(range_begin, range_end), 0);
671 
672  std::vector<typename Packing<T>::buffer_type> buffer;
673 
674  const Iter next_range_begin = pack_range
675  (context, range_begin, range_end, buffer, approx_buffer_size);
676 
677  timpi_assert_greater (std::distance(range_begin, next_range_begin), 0);
678 
679  range_begin = next_range_begin;
680 
681 #ifdef DEBUG
682  used_buffer_size += buffer.size();
683 #endif
684 
685  // Blocking send of the buffer
686  this->send(dest_processor_id, buffer, tag);
687  }
688 
689 #ifdef DEBUG
690  timpi_assert_equal_to(used_buffer_size, total_buffer_size);
691 #endif
692 }
Iter pack_range(const Context *context, Iter range_begin, const Iter range_end, std::vector< buffertype > &buffer, std::size_t approx_buffer_size)
Helper function for range packing.
Definition: packing.h:1044
void send(const unsigned int dest_processor_id, const T &buf, const MessageTag &tag=no_tag) const
Blocking-send to one processor with data-defined type.
std::size_t packed_range_size(const Context *context, Iter range_begin, const Iter range_end)
Helper function for range packing.
Definition: packing.h:1023

◆ send_packed_range() [2/2]

template<typename Context , typename Iter >
void TIMPI::Communicator::send_packed_range ( const unsigned int  dest_processor_id,
const Context *  context,
Iter  range_begin,
const Iter  range_end,
Request req,
const MessageTag tag = no_tag,
std::size_t  approx_buffer_size = 1000000 
) const
inlineinherited

Nonblocking-send range-of-pointers to one processor.

This function does not send the raw pointers, but rather constructs new objects at the other end whose contents match the objects pointed to by the sender.

void TIMPI::pack(const T *, vector<int> & data, const Context *) is used to serialize type T onto the end of a data vector.

unsigned int TIMPI::packable_size(const T *, const Context *) is used to allow data vectors to reserve memory, and for additional error checking

The approximate maximum size (in entries; number of bytes will likely be 4x or 8x larger) to use in a single data vector buffer can be specified for performance or memory usage reasons; if the range cannot be packed into a single buffer of this size then multiple buffers and messages will be used.

Definition at line 696 of file parallel_implementation.h.

References TIMPI::Request::add_post_wait_work(), TIMPI::Request::add_prior_request(), TIMPI::pack_range(), TIMPI::packed_range_size(), and TIMPI::Communicator::send().

703 {
704  // Allocate a buffer on the heap so we don't have to free it until
705  // after the Request::wait()
706  typedef typename std::iterator_traits<Iter>::value_type T;
707  typedef typename Packing<T>::buffer_type buffer_t;
708 
709  std::size_t total_buffer_size =
710  packed_range_size (context, range_begin, range_end);
711 
712  // That local variable will be gone soon; we need a send buffer that
713  // will stick around. I heard you like buffering so I put a buffer
714  // for your buffer size so you can buffer the size of your buffer.
715  std::size_t * total_buffer_size_buffer = new std::size_t;
716  *total_buffer_size_buffer = total_buffer_size;
717 
718  // Delete the buffer size's buffer when we're done
719  Request intermediate_req = request();
720  intermediate_req.add_post_wait_work
721  (new PostWaitDeleteBuffer<std::size_t>(total_buffer_size_buffer));
722  this->send(dest_processor_id, *total_buffer_size_buffer, intermediate_req, tag);
723 
724  // And don't finish up the full request until we're done with its
725  // dependencies
726  req.add_prior_request(intermediate_req);
727 
728 #ifdef DEBUG
729  std::size_t used_buffer_size = 0;
730 #endif
731 
732  while (range_begin != range_end)
733  {
734  timpi_assert_greater (std::distance(range_begin, range_end), 0);
735 
736  std::vector<buffer_t> * buffer = new std::vector<buffer_t>();
737 
738  const Iter next_range_begin = pack_range
739  (context, range_begin, range_end, *buffer, approx_buffer_size);
740 
741  timpi_assert_greater (std::distance(range_begin, next_range_begin), 0);
742 
743  range_begin = next_range_begin;
744 
745 #ifdef DEBUG
746  used_buffer_size += buffer->size();
747 #endif
748 
749  Request next_intermediate_req;
750 
751  Request * my_req = (range_begin == range_end) ? &req : &next_intermediate_req;
752 
753  // Make the Request::wait() handle deleting the buffer
754  my_req->add_post_wait_work
755  (new PostWaitDeleteBuffer<std::vector<buffer_t>>
756  (buffer));
757 
758  // Non-blocking send of the buffer
759  this->send(dest_processor_id, *buffer, *my_req, tag);
760 
761  if (range_begin != range_end)
762  req.add_prior_request(*my_req);
763  }
764 
765 #ifdef DEBUG
766  timpi_assert_equal_to(used_buffer_size, total_buffer_size);
767 #endif
768 }
MPI_Request request
Request object for non-blocking I/O.
Definition: request.h:41
Iter pack_range(const Context *context, Iter range_begin, const Iter range_end, std::vector< buffertype > &buffer, std::size_t approx_buffer_size)
Helper function for range packing.
Definition: packing.h:1044
void send(const unsigned int dest_processor_id, const T &buf, const MessageTag &tag=no_tag) const
Blocking-send to one processor with data-defined type.
std::size_t packed_range_size(const Context *context, Iter range_begin, const Iter range_end)
Helper function for range packing.
Definition: packing.h:1023

◆ send_receive() [1/7]

template<typename T1 , typename T2 , typename std::enable_if< std::is_base_of< DataType, StandardType< T1 >>::value &&std::is_base_of< DataType, StandardType< T2 >>::value, int >::type >
void TIMPI::Communicator::send_receive ( const unsigned int   timpi_dbg_varsend_tgt,
const T1 &  send_val,
const unsigned int   timpi_dbg_varrecv_source,
T2 &  recv_val,
const MessageTag ,
const MessageTag  
) const
inlineinherited

Send-receive data from one processor.

Definition at line 189 of file serial_implementation.h.

195 {
196  timpi_assert_equal_to (send_tgt, 0);
197  timpi_assert_equal_to (recv_source, 0);
198  recv_val = send_val;
199 }

◆ send_receive() [2/7]

template<typename T , typename A , typename std::enable_if< Has_buffer_type< Packing< T >>::value, int >::type >
void TIMPI::Communicator::send_receive ( const unsigned int   timpi_dbg_vardest_processor_id,
const std::vector< T, A > &  send,
const unsigned int   timpi_dbg_varsource_processor_id,
std::vector< T, A > &  recv,
const MessageTag ,
const MessageTag  
) const
inlineinherited

Definition at line 238 of file serial_implementation.h.

References TIMPI::Communicator::send().

244 {
245  timpi_assert_equal_to (dest_processor_id, 0);
246  timpi_assert_equal_to (source_processor_id, 0);
247  recv = send;
248 }
void send(const unsigned int dest_processor_id, const T &buf, const MessageTag &tag=no_tag) const
Blocking-send to one processor with data-defined type.

◆ send_receive() [3/7]

template<typename T , typename A1 , typename A2 >
void TIMPI::Communicator::send_receive ( const unsigned int   timpi_dbg_vardest_processor_id,
const std::vector< std::vector< T, A1 >, A2 > &  send,
const unsigned int   timpi_dbg_varsource_processor_id,
std::vector< std::vector< T, A1 >, A2 > &  recv,
const MessageTag ,
const MessageTag  
) const
inlineinherited

Definition at line 297 of file serial_implementation.h.

References TIMPI::Communicator::send().

303 {
304  timpi_assert_equal_to (dest_processor_id, 0);
305  timpi_assert_equal_to (source_processor_id, 0);
306  recv = send;
307 }
void send(const unsigned int dest_processor_id, const T &buf, const MessageTag &tag=no_tag) const
Blocking-send to one processor with data-defined type.

◆ send_receive() [4/7]

template<typename T1 , typename T2 , typename std::enable_if< std::is_base_of< DataType, StandardType< T1 >>::value &&std::is_base_of< DataType, StandardType< T2 >>::value, int >::type >
void TIMPI::Communicator::send_receive ( const unsigned int  dest_processor_id,
const T1 &  send_data,
const unsigned int  source_processor_id,
T2 &  recv_data,
const MessageTag send_tag = no_tag,
const MessageTag recv_tag = any_tag 
) const
inlineinherited

Send data send to one processor while simultaneously receiving other data recv from a (potentially different) processor.

This overload is defined for fixed-size data; other overloads exist for many other categories.

Definition at line 1397 of file parallel_implementation.h.

References TIMPI::any_source, TIMPI::Communicator::rank(), TIMPI::Communicator::size(), and TIMPI::MessageTag::value().

Referenced by TIMPI::push_parallel_vector_data().

1403 {
1404  TIMPI_LOG_SCOPE("send_receive()", "Parallel");
1405 
1406  if (dest_processor_id == this->rank() &&
1407  source_processor_id == this->rank())
1408  {
1409  recv = sendvec;
1410  return;
1411  }
1412 
1413  timpi_assert_less(dest_processor_id, this->size());
1414  timpi_assert(source_processor_id < this->size() ||
1415  source_processor_id == any_source);
1416 
1417  // MPI_STATUS_IGNORE is from MPI-2; using it with some versions of
1418  // MPICH may cause a crash:
1419  // https://bugzilla.mcs.anl.gov/globus/show_bug.cgi?id=1798
1420  timpi_call_mpi
1421  (TIMPI_SENDRECV(const_cast<T1*>(&sendvec), 1, StandardType<T1>(&sendvec),
1422  dest_processor_id, send_tag.value(), &recv, 1,
1423  StandardType<T2>(&recv), source_processor_id,
1424  recv_tag.value(), this->get(), MPI_STATUS_IGNORE));
1425 }
processor_id_type rank() const
Definition: communicator.h:208
const unsigned int any_source
Processor id meaning "Accept from any source".
Definition: communicator.h:84
processor_id_type size() const
Definition: communicator.h:211

◆ send_receive() [5/7]

template<typename T1 , typename T2 >
void TIMPI::Communicator::send_receive ( const unsigned int  dest_processor_id,
const T1 &  send_data,
const DataType type1,
const unsigned int  source_processor_id,
T2 &  recv_data,
const DataType type2,
const MessageTag send_tag = no_tag,
const MessageTag recv_tag = any_tag 
) const
inlineinherited

Send data send to one processor while simultaneously receiving other data recv from a (potentially different) processor, using a user-specified MPI Dataype.

◆ send_receive() [6/7]

template<typename T , typename A , typename std::enable_if< std::is_base_of< DataType, StandardType< T >>::value, int >::type >
void TIMPI::Communicator::send_receive ( const unsigned int  dest_processor_id,
const std::vector< T, A > &  send_data,
const unsigned int  source_processor_id,
std::vector< T, A > &  recv_data,
const MessageTag send_tag,
const MessageTag recv_tag 
) const
inlineinherited

Definition at line 1376 of file parallel_implementation.h.

References TIMPI::Communicator::send_receive_packed_range().

1382 {
1383  this->send_receive_packed_range(dest_processor_id, (void *)(nullptr),
1384  send_data.begin(), send_data.end(),
1385  source_processor_id, (void *)(nullptr),
1386  std::back_inserter(recv_data),
1387  (const T *)(nullptr),
1388  send_tag, recv_tag);
1389 }
void send_receive_packed_range(const unsigned int dest_processor_id, const Context1 *context1, RangeIter send_begin, const RangeIter send_end, const unsigned int source_processor_id, Context2 *context2, OutputIter out, const T *output_type, const MessageTag &send_tag=no_tag, const MessageTag &recv_tag=any_tag, std::size_t approx_buffer_size=1000000) const
Send a range-of-pointers to one processor while simultaneously receiving another range from a (potent...

◆ send_receive() [7/7]

template<typename T , typename A1 , typename A2 >
void TIMPI::Communicator::send_receive ( const unsigned int  dest_processor_id,
const std::vector< std::vector< T, A1 >, A2 > &  sendvec,
const unsigned int  source_processor_id,
std::vector< std::vector< T, A1 >, A2 > &  recv,
const MessageTag send_tag,
const MessageTag recv_tag 
) const
inlineinherited

Definition at line 1509 of file parallel_implementation.h.

1515 {
1516  send_receive_vec_of_vec
1517  (dest_processor_id, sendvec, source_processor_id, recv,
1518  send_tag, recv_tag, *this);
1519 }

◆ send_receive_packed_range() [1/2]

template<typename Context1 , typename RangeIter , typename Context2 , typename OutputIter , typename T >
void TIMPI::Communicator::send_receive_packed_range ( const unsigned int   timpi_dbg_vardest_processor_id,
const Context1 *  context1,
RangeIter  send_begin,
const RangeIter  send_end,
const unsigned int   timpi_dbg_varsource_processor_id,
Context2 *  context2,
OutputIter  out_iter,
const T *  output_type,
const MessageTag ,
const MessageTag ,
std::size_t   
) const
inlineinherited

Send-receive range-of-pointers from one processor.

If you call this without MPI you might be making a mistake, but we'll support it.

Definition at line 322 of file serial_implementation.h.

References TIMPI::pack_range(), and TIMPI::unpack_range().

333 {
334  // This makes no sense on one processor unless we're deliberately
335  // sending to ourself.
336  timpi_assert_equal_to(dest_processor_id, 0);
337  timpi_assert_equal_to(source_processor_id, 0);
338 
339  // On one processor, we just need to pack the range and then unpack
340  // it again.
341  typedef typename std::iterator_traits<RangeIter>::value_type T1;
342  typedef typename Packing<T1>::buffer_type buffer_t;
343 
344  // OutputIter might not have operator= implemented; for maximum
345  // compatibility we'll rely on its copy constructor.
346  std::unique_ptr<OutputIter> next_out_iter =
347  std::make_unique<OutputIter>(out_iter);
348 
349  while (send_begin != send_end)
350  {
351  timpi_assert_greater (std::distance(send_begin, send_end), 0);
352 
353  // We will serialize variable size objects from *range_begin to
354  // *range_end as a sequence of ints in this buffer
355  std::vector<buffer_t> buffer;
356 
357  const RangeIter next_send_begin = pack_range
358  (context1, send_begin, send_end, buffer);
359 
360  timpi_assert_greater (std::distance(send_begin, next_send_begin), 0);
361 
362  send_begin = next_send_begin;
363 
364  auto return_out_iter = unpack_range
365  (buffer, context2, *next_out_iter, output_type);
366  next_out_iter = std::make_unique<OutputIter>(return_out_iter);
367  }
368 }
OutputIter unpack_range(const std::vector< buffertype > &buffer, Context *context, OutputIter out_iter, const T *)
Helper function for range unpacking.
Definition: packing.h:1103
Iter pack_range(const Context *context, Iter range_begin, const Iter range_end, std::vector< buffertype > &buffer, std::size_t approx_buffer_size)
Helper function for range packing.
Definition: packing.h:1044

◆ send_receive_packed_range() [2/2]

template<typename Context1 , typename RangeIter , typename Context2 , typename OutputIter , typename T >
void TIMPI::Communicator::send_receive_packed_range ( const unsigned int  dest_processor_id,
const Context1 *  context1,
RangeIter  send_begin,
const RangeIter  send_end,
const unsigned int  source_processor_id,
Context2 *  context2,
OutputIter  out,
const T *  output_type,
const MessageTag send_tag = no_tag,
const MessageTag recv_tag = any_tag,
std::size_t  approx_buffer_size = 1000000 
) const
inlineinherited

Send a range-of-pointers to one processor while simultaneously receiving another range from a (potentially different) processor.

This function does not send or receive raw pointers, but rather constructs new objects at each receiver whose contents match the objects pointed to by the sender.

The objects being sent will be of type T1 = iterator_traits<RangeIter>::value_type, and the objects being received will be of type T2 = iterator_traits<OutputIter>::value_type

void TIMPI::pack(const T1*, vector<int> & data, const Context1*) is used to serialize type T1 onto the end of a data vector.

Using std::back_inserter as the output iterator allows send_receive to fill any container type. Using some null_output_iterator allows the receive to be dealt with solely by TIMPI::unpack(), for objects whose unpack() is written so as to not leak memory when used in this fashion.

A future version of this method should be created to preallocate memory when receiving vectors...

void TIMPI::unpack(vector<int>::iterator in, T2** out, Context *) is used to unserialize type T2, typically into a new heap-allocated object whose pointer is returned as *out.

unsigned int TIMPI::packable_size(const T1*, const Context1*) is used to allow data vectors to reserve memory, and for additional error checking.

unsigned int TIMPI::packed_size(const T2*, vector<int>::const_iterator) is used to advance to the beginning of the next object's data.

Definition at line 1527 of file parallel_implementation.h.

References TIMPI::pack_range(), TIMPI::Communicator::rank(), TIMPI::Communicator::receive_packed_range(), TIMPI::Communicator::send_packed_range(), TIMPI::unpack_range(), and TIMPI::Request::wait().

Referenced by TIMPI::push_parallel_packed_range(), TIMPI::Communicator::send_receive(), testContainerSendReceive(), and testNullSendReceive().

1538 {
1539  TIMPI_LOG_SCOPE("send_receive()", "Parallel");
1540 
1541  timpi_assert_equal_to
1542  ((dest_processor_id == this->rank()),
1543  (source_processor_id == this->rank()));
1544 
1545  if (dest_processor_id == this->rank() &&
1546  source_processor_id == this->rank())
1547  {
1548  // We need to pack and unpack, even if we don't need to
1549  // communicate the buffer, just in case user Packing
1550  // specializations have side effects
1551 
1552  // OutputIter might not have operator= implemented; for maximum
1553  // compatibility we'll rely on its copy constructor.
1554  std::unique_ptr<OutputIter> next_out_iter =
1555  std::make_unique<OutputIter>(out_iter);
1556 
1557  typedef typename Packing<T>::buffer_type buffer_t;
1558  while (send_begin != send_end)
1559  {
1560  std::vector<buffer_t> buffer;
1561  send_begin = pack_range
1562  (context1, send_begin, send_end, buffer, approx_buffer_size);
1563  auto return_out_iter = unpack_range
1564  (buffer, context2, *next_out_iter, output_type);
1565  next_out_iter = std::make_unique<OutputIter>(return_out_iter);
1566  }
1567  return;
1568  }
1569 
1570  Request req;
1571 
1572  this->send_packed_range (dest_processor_id, context1, send_begin, send_end,
1573  req, send_tag, approx_buffer_size);
1574 
1575  this->receive_packed_range (source_processor_id, context2, out_iter,
1576  output_type, recv_tag);
1577 
1578  req.wait();
1579 }
OutputIter unpack_range(const std::vector< buffertype > &buffer, Context *context, OutputIter out_iter, const T *)
Helper function for range unpacking.
Definition: packing.h:1103
processor_id_type rank() const
Definition: communicator.h:208
void send_packed_range(const unsigned int dest_processor_id, const Context *context, Iter range_begin, const Iter range_end, const MessageTag &tag=no_tag, std::size_t approx_buffer_size=1000000) const
Blocking-send range-of-pointers to one processor.
void receive_packed_range(const unsigned int dest_processor_id, Context *context, OutputIter out, const T *output_type, const MessageTag &tag=any_tag) const
Blocking-receive range-of-pointers from one processor.
Iter pack_range(const Context *context, Iter range_begin, const Iter range_end, std::vector< buffertype > &buffer, std::size_t approx_buffer_size)
Helper function for range packing.
Definition: packing.h:1044

◆ set_union() [1/2]

template<typename T >
void TIMPI::Communicator::set_union ( T &  data,
const unsigned int  root_id 
) const
inlineinherited

Take a container (set, map, unordered_set, multimap, etc) of local variables on each processor, and collect their union over all processors, replacing the original on the processor with rank root_id.

If the data is a map or unordered_map and entries exist on different processors with the same key and different values, then the value with the lowest processor id takes precedence.

If the data is a multiset or multimap or unordered_multimap, and entries exist on different processors with the same key, these entries are duplicated in the gathered container.

Referenced by testBigUnion(), testLargeSetUnion(), testMapMap(), testMapSet(), testPackedSetUnion(), and testUnion().

◆ set_union() [2/2]

template<typename T >
void TIMPI::Communicator::set_union ( T &  data) const
inlineinherited

Take a container of local variables on each processor, and replace it with their union over all processors, replacing the original on all processors.

If the data is a multiset or multimap or unordered_multimap, and entries exist on different processors with the same key, these entries are duplicated in the gathered container.

◆ size() [1/2]

processor_id_type TIMPI::Communicator::size ( ) const
inlineinherited

Definition at line 211 of file communicator.h.

References TIMPI::Communicator::_size.

Referenced by TIMPI::Communicator::allgather(), TIMPI::Communicator::barrier(), TIMPI::Communicator::broadcast(), TIMPI::Communicator::map_max(), TIMPI::Communicator::max(), TIMPI::Communicator::maxloc(), TIMPI::Communicator::min(), TIMPI::Communicator::minloc(), TIMPI::Communicator::nonblocking_barrier(), TIMPI::Communicator::packed_size_of(), TIMPI::Communicator::possibly_receive(), TIMPI::Communicator::probe(), TIMPI::pull_parallel_vector_data(), TIMPI::detail::push_parallel_alltoall_helper(), TIMPI::detail::push_parallel_nbx_helper(), TIMPI::detail::push_parallel_roundrobin_helper(), TIMPI::Communicator::receive(), TIMPI::Communicator::semiverify(), TIMPI::Communicator::send(), TIMPI::Communicator::send_receive(), testAllGatherString(), testAllGatherVectorVectorInPlace(), testArrayContainerAllGather(), testBigUnion(), testContainerAllGather(), testContainerSendReceive(), testEmptyEntry(), testGettableStringAllGather(), testIrecvSend(), testIsendRecv(), testLargeSetUnion(), testMapContainerAllGather(), testMapMax(), testMax(), testMaxloc(), testMaxlocBool(), testMaxlocDouble(), testMaxlocPair(), testMaxVecBool(), testMinloc(), testMinlocBool(), testMinlocDouble(), testMinlocPair(), testMinVecBool(), testNestingAllGather(), testNonblockingMax(), testNonblockingString(), testNonblockingSum(), testNonFixedTypeMapMax(), testNonFixedTypeSum(), testNullSendReceive(), testPackedSetUnion(), testPairContainerAllGather(), testPull(), testPullImpl(), testPullOversized(), testPullPacked(), testPullVecVec(), testPullVecVecImpl(), testPullVecVecOversized(), testPush(), testPushImpl(), testPushMove(), testPushMultimap(), testPushMultimapImpl(), testPushMultimapOversized(), testPushMultimapVecVec(), testPushMultimapVecVecImpl(), testPushMultimapVecVecOversized(), testPushOversized(), testPushPacked(), testPushPackedImpl(), testPushPackedImplMove(), testPushPackedMove(), testPushPackedMoveOversized(), testPushPackedNestedImpl(), testPushPackedOversized(), testPushVecVec(), testPushVecVecImpl(), testPushVecVecOversized(), testRecvIsendSets(), testRecvIsendVecVecs(), testScatter(), testSendRecvVecVecs(), testSplit(), testSplitByType(), testSum(), testSumOpFunction(), testTupleContainerAllGather(), testTupleStringAllGather(), testUnion(), testVectorOfContainersAllGather(), testVectorOfContainersBroadcast(), and TIMPI::Communicator::verify().

211 { return _size; }
processor_id_type _size
Definition: communicator.h:237

◆ size() [2/2]

constexpr processor_id_type TIMPI::Communicator::size ( ) const
inlineinherited

Definition at line 214 of file communicator.h.

214 { return 1; }

◆ split()

void TIMPI::Communicator::split ( int  color,
int  key,
Communicator target 
) const
inherited

Definition at line 97 of file communicator.C.

References TIMPI::Communicator::_I_duped_it, TIMPI::Communicator::assign(), TIMPI::Communicator::clear(), TIMPI::Communicator::send_mode(), and TIMPI::Communicator::sync_type().

Referenced by testSplit().

98 {
99  target.clear();
100  MPI_Comm newcomm;
101  timpi_call_mpi
102  (MPI_Comm_split(this->get(), color, key, &newcomm));
103 
104  target.assign(newcomm);
105  target._I_duped_it = (color != MPI_UNDEFINED);
106  target.send_mode(this->send_mode());
107  target.sync_type(this->sync_type());
108 }
SyncType sync_type() const
Gets the user-requested SyncType.
Definition: communicator.h:355
SendMode send_mode() const
Gets the user-requested SendMode.
Definition: communicator.h:338

◆ split_by_type()

void TIMPI::Communicator::split_by_type ( int  split_type,
int  key,
info  i,
Communicator target 
) const
inherited

Definition at line 111 of file communicator.C.

References TIMPI::Communicator::_I_duped_it, TIMPI::Communicator::assign(), TIMPI::Communicator::clear(), TIMPI::Communicator::send_mode(), and TIMPI::Communicator::sync_type().

Referenced by testSplitByType().

112 {
113  target.clear();
114  MPI_Comm newcomm;
115  timpi_call_mpi
116  (MPI_Comm_split_type(this->get(), split_type, key, i, &newcomm));
117 
118  target.assign(newcomm);
119  target._I_duped_it = (split_type != MPI_UNDEFINED);
120  target.send_mode(this->send_mode());
121  target.sync_type(this->sync_type());
122 }
SyncType sync_type() const
Gets the user-requested SyncType.
Definition: communicator.h:355
SendMode send_mode() const
Gets the user-requested SendMode.
Definition: communicator.h:338

◆ sum() [1/2]

template<typename T >
void TIMPI::Communicator::sum ( T &  r) const
inlineinherited

Take a local variable and replace it with the sum of it's values on all processors.

Containers are replaced element-wise.

Referenced by testNonblockingSum(), testNonFixedTypeSum(), testSum(), and testSumOpFunction().

◆ sum() [2/2]

template<typename T >
void TIMPI::Communicator::sum ( const T &  r,
T &  o,
Request req 
) const
inlineinherited

Non-blocking sum of the local value r into o with the request req.

◆ sync_type() [1/3]

void TIMPI::Communicator::sync_type ( const SyncType  st)
inlineinherited

◆ sync_type() [2/3]

void TIMPI::Communicator::sync_type ( const std::string &  st)
inherited

Sets the sync type used for sync operations via a string.

Useful for changing the sync type via a CLI arg or parameter.

Definition at line 455 of file communicator.C.

References TIMPI::Communicator::ALLTOALL_COUNTS, TIMPI::Communicator::NBX, TIMPI::Communicator::SENDRECEIVE, and TIMPI::Communicator::sync_type().

456 {
457  SyncType type = NBX;
458  if (st == "sendreceive")
459  type = SENDRECEIVE;
460  else if (st == "alltoall")
461  type = ALLTOALL_COUNTS;
462  else if (st != "nbx")
463  timpi_error_msg("Unrecognized TIMPI sync type " << st);
464  this->sync_type(type);
465 }
SyncType sync_type() const
Gets the user-requested SyncType.
Definition: communicator.h:355
SyncType
What algorithm to use for parallel synchronization?
Definition: communicator.h:225

◆ sync_type() [3/3]

SyncType TIMPI::Communicator::sync_type ( ) const
inlineinherited

◆ verify() [1/2]

template<typename T >
timpi_pure bool TIMPI::Communicator::verify ( const T &  r) const
inlineinherited

Check whether a local variable has the same value on all processors, returning true if it does or false if not.

Useful in assertions and possibly in user error checking.

Containers must have the same value in every entry for this function to return true.

Referenced by TIMPI::Communicator::broadcast(), TIMPI::Communicator::max(), TIMPI::Communicator::maxloc(), TIMPI::Communicator::min(), and TIMPI::Communicator::minloc().

◆ verify() [2/2]

template<typename T >
bool TIMPI::Communicator::verify ( const T &  r) const
inlineinherited

Definition at line 2092 of file parallel_implementation.h.

References TIMPI::Communicator::max(), TIMPI::Communicator::min(), and TIMPI::Communicator::size().

2093 {
2094  if (this->size() > 1 && Attributes<T>::has_min_max == true)
2095  {
2096  T tempmin = r, tempmax = r;
2097  this->min(tempmin);
2098  this->max(tempmax);
2099  bool verified = (r == tempmin) &&
2100  (r == tempmax);
2101  this->min(verified);
2102  return verified;
2103  }
2104 
2105  static_assert(Attributes<T>::has_min_max,
2106  "Tried to verify an unverifiable type");
2107 
2108  return true;
2109 }
processor_id_type size() const
Definition: communicator.h:211
void min(const T &r, T &o, Request &req) const
Non-blocking minimum of the local value r into o with the request req.
static const bool has_min_max
Definition: attributes.h:48
void max(const T &r, T &o, Request &req) const
Non-blocking maximum of the local value r into o with the request req.

The documentation for this class was generated from the following file: