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
 
template<typename Map , typename std::enable_if< std::is_base_of< DataType, StandardType< typename Map::key_type >>::value &&std::is_base_of< DataType, StandardType< typename Map::mapped_type >>::value, int >::type >
void map_broadcast (Map &timpi_mpi_var(data), const unsigned int root_id, const bool timpi_mpi_var(identical_sizes)) const
 
template<typename Map >
void map_broadcast (Map &timpi_mpi_var(data), const unsigned int root_id, const bool timpi_mpi_var(identical_sizes)) 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 T >
void min (T &timpi_mpi_var(r)) const
 
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 T >
void max (T &timpi_mpi_var(r)) const
 
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 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 sum (T &timpi_mpi_var(r)) const
 
template<typename T >
void sum (std::complex< T > &timpi_mpi_var(r)) const
 
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 T , typename A1 , typename A2 >
bool possibly_receive (unsigned int &src_processor_id, std::vector< std::vector< T, A1 >, A2 > &buf, 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 T #ifdef TIMPI_HAVE_MPI, typename std::enable_if< std::is_base_of< DataType, StandardType< T >>::value, int >::type # endif>
void broadcast (T &timpi_mpi_var(data), const unsigned int root_id, const bool) 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 1396 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 1399 of file communicator.h.

1399 : 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< Has_buffer_type< Packing< T >>::value, int >::type >
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 fixed size types

Definition at line 3382 of file parallel_implementation.h.

References TIMPI::Communicator::size().

Referenced by TIMPI::Communicator::allgather(), TIMPI::Communicator::allgather_packed_range(), TIMPI::Communicator::gather(), TIMPI::Communicator::map_max(), TIMPI::Communicator::map_sum(), testAllGather(), testAllGatherEmptyVectorString(), testAllGatherHalfEmptyVectorString(), testAllGatherString(), testAllGatherVectorString(), testAllGatherVectorVector(), testAllGatherVectorVectorInPlace(), testAllGatherVectorVectorPacked(), testArrayContainerAllGather(), testContainerAllGather(), testMapContainerAllGather(), testPairContainerAllGather(), testTupleContainerAllGather(), and testVectorOfContainersAllGather().

3384 {
3385  TIMPI_LOG_SCOPE ("allgather()","Parallel");
3386 
3387  timpi_assert(this->size());
3388  recv.resize(this->size());
3389 
3390  const unsigned int comm_size = this->size();
3391  if (comm_size > 1)
3392  {
3393  StandardType<T> send_type(&sendval);
3394 
3395  timpi_call_mpi
3396  (TIMPI_ALLGATHER(const_cast<T*>(&sendval), 1, send_type, recv.data(), 1,
3397  send_type, this->get()));
3398  }
3399  else if (comm_size > 0)
3400  recv[0] = sendval;
3401 }
processor_id_type size() const
Definition: communicator.h:211

◆ 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 1625 of file parallel_implementation.h.

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

1628 {
1629  TIMPI_LOG_SCOPE ("allgather()","Parallel");
1630 
1631  timpi_assert(this->size());
1632  recv.assign(this->size(), "");
1633 
1634  // serial case
1635  if (this->size() < 2)
1636  {
1637  recv.resize(1);
1638  recv[0] = sendval;
1639  return;
1640  }
1641 
1642  std::vector<CountType>
1643  sendlengths (this->size(), 0);
1644  std::vector<DispType>
1645  displacements(this->size(), 0);
1646 
1647  const CountType mysize = cast_int<CountType>(sendval.size());
1648 
1649  if (identical_buffer_sizes)
1650  sendlengths.assign(this->size(), mysize);
1651  else
1652  // first comm step to determine buffer sizes from all processors
1653  this->allgather(mysize, sendlengths);
1654 
1655  // Find the total size of the final array and
1656  // set up the displacement offsets for each processor
1657  CountType globalsize = 0;
1658  for (unsigned int i=0; i != this->size(); ++i)
1659  {
1660  displacements[i] = globalsize;
1661  globalsize += sendlengths[i];
1662  }
1663 
1664  // Check for quick return
1665  if (globalsize == 0)
1666  return;
1667 
1668  // monolithic receive buffer
1669  std::basic_string<T> r(globalsize, 0);
1670 
1671  // and get the data from the remote processors.
1672  timpi_call_mpi
1673  (TIMPI_ALLGATHERV(const_cast<T*>(mysize ? sendval.data() : nullptr),
1674  mysize, StandardType<T>(),
1675  &r[0], sendlengths.data(), displacements.data(),
1676  StandardType<T>(), this->get()));
1677 
1678  // slice receive buffer up
1679  for (unsigned int i=0; i != this->size(); ++i)
1680  recv[i] = r.substr(displacements[i], sendlengths[i]);
1681 }
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< Has_buffer_type< Packing< T >>::value, int >::type >
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.

Definition at line 3431 of file parallel_implementation.h.

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

3433 {
3434  if (this->size() < 2)
3435  return;
3436 
3437  TIMPI_LOG_SCOPE("allgather()", "Parallel");
3438 
3439  if (identical_buffer_sizes)
3440  {
3441  timpi_assert(this->verify(r.size()));
3442  if (r.empty())
3443  return;
3444 
3445  std::vector<T,A> r_src(r.size()*this->size());
3446  r_src.swap(r);
3447  StandardType<T> send_type(r_src.data());
3448 
3449  timpi_call_mpi
3450  (TIMPI_ALLGATHER(r_src.data(), cast_int<CountType>(r_src.size()),
3451  send_type, r.data(), cast_int<CountType>(r_src.size()),
3452  send_type, this->get()));
3453  // timpi_assert(this->verify(r));
3454  return;
3455  }
3456 
3457  std::vector<CountType>
3458  sendlengths (this->size(), 0);
3459  std::vector<DispType>
3460  displacements(this->size(), 0);
3461 
3462  const CountType mysize = cast_int<CountType>(r.size());
3463  this->allgather(mysize, sendlengths);
3464 
3465  // Find the total size of the final array and
3466  // set up the displacement offsets for each processor.
3467  CountType globalsize = 0;
3468  for (unsigned int i=0; i != this->size(); ++i)
3469  {
3470  displacements[i] = globalsize;
3471  globalsize += sendlengths[i];
3472  }
3473 
3474  // Check for quick return
3475  if (globalsize == 0)
3476  return;
3477 
3478  // copy the input buffer
3479  std::vector<T,A> r_src(globalsize);
3480  r_src.swap(r);
3481 
3482  StandardType<T> send_type(r.data());
3483 
3484  // and get the data from the remote processors.
3485  // Pass nullptr if our vector is empty.
3486  timpi_call_mpi
3487  (TIMPI_ALLGATHERV(r_src.empty() ? nullptr : r_src.data(), mysize,
3488  send_type, r.data(), sendlengths.data(),
3489  displacements.data(), send_type, this->get()));
3490 }
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
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...

◆ allgather() [5/8]

template<typename T , typename A1 , typename A2 , typename std::enable_if< Has_buffer_type< Packing< T >>::value, int >::type >
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.

Definition at line 2833 of file parallel_implementation.h.

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

2836 {
2837  TIMPI_LOG_SCOPE ("allgather()","Parallel");
2838 
2839  timpi_assert(this->size());
2840 
2841  // serial case
2842  if (this->size() < 2)
2843  {
2844  recv.resize(1);
2845  recv[0] = sendval;
2846  return;
2847  }
2848 
2849  recv.clear();
2850  recv.resize(this->size());
2851 
2852  std::vector<CountType>
2853  sendlengths (this->size(), 0);
2854  std::vector<DispType>
2855  displacements(this->size(), 0);
2856 
2857  const CountType mysize = cast_int<CountType>(sendval.size());
2858 
2859  if (identical_buffer_sizes)
2860  sendlengths.assign(this->size(), mysize);
2861  else
2862  // first comm step to determine buffer sizes from all processors
2863  this->allgather(mysize, sendlengths);
2864 
2865  // Find the total size of the final array and
2866  // set up the displacement offsets for each processor
2867  CountType globalsize = 0;
2868  for (unsigned int i=0; i != this->size(); ++i)
2869  {
2870  displacements[i] = globalsize;
2871  globalsize += sendlengths[i];
2872  }
2873 
2874  // Check for quick return
2875  if (globalsize == 0)
2876  return;
2877 
2878  // monolithic receive buffer
2879  std::vector<T,A1> r(globalsize, 0);
2880 
2881  // and get the data from the remote processors.
2882  timpi_call_mpi
2883  (TIMPI_ALLGATHERV(const_cast<T*>(mysize ? sendval.data() : nullptr),
2884  mysize, StandardType<T>(),
2885  &r[0], sendlengths.data(), displacements.data(),
2886  StandardType<T>(), this->get()));
2887 
2888  // slice receive buffer up
2889  for (unsigned int i=0; i != this->size(); ++i)
2890  recv[i].assign(r.begin()+displacements[i],
2891  r.begin()+displacements[i]+sendlengths[i]);
2892 }
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...
void assign(const communicator &comm)
Utility function for setting our member variables from an MPI communicator.
Definition: communicator.C:185
processor_id_type size() const
Definition: communicator.h:211
MPI_Count CountType
Definition: status.h:47

◆ 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.

Definition at line 3547 of file parallel_implementation.h.

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

3549 {
3550  if (this->size() < 2)
3551  return;
3552 
3553  TIMPI_LOG_SCOPE("allgather()", "Parallel");
3554 
3555  if (identical_buffer_sizes)
3556  {
3557  timpi_assert(this->verify(r.size()));
3558 
3559  // identical_buffer_sizes doesn't buy us much since we have to
3560  // communicate the lengths of strings within each buffer anyway
3561  if (r.empty())
3562  return;
3563  }
3564 
3565  // Concatenate the input buffer into a send buffer, and keep track
3566  // of input string lengths
3567  std::vector<CountType> mystrlengths (r.size());
3568  std::vector<T> concat_src;
3569 
3570  CountType myconcatsize = 0;
3571  for (std::size_t i=0; i != r.size(); ++i)
3572  {
3573  CountType stringlen = cast_int<CountType>(r[i].size());
3574  mystrlengths[i] = stringlen;
3575  myconcatsize += stringlen;
3576  }
3577  concat_src.reserve(myconcatsize);
3578  for (std::size_t i=0; i != r.size(); ++i)
3579  concat_src.insert
3580  (concat_src.end(), r[i].begin(), r[i].end());
3581 
3582  // Get the string lengths from all other processors
3583  std::vector<CountType> strlengths = mystrlengths;
3584  this->allgather(strlengths, identical_buffer_sizes);
3585 
3586  // We now know how many strings we'll be receiving
3587  r.resize(strlengths.size());
3588 
3589  // Get the concatenated data sizes from all other processors
3590  std::vector<CountType> concat_sizes;
3591  this->allgather(myconcatsize, concat_sizes);
3592 
3593  // Find the total size of the final concatenated array and
3594  // set up the displacement offsets for each processor.
3595  std::vector<DispType> displacements(this->size(), 0);
3596  CountType globalsize = 0;
3597  for (unsigned int i=0; i != this->size(); ++i)
3598  {
3599  displacements[i] = globalsize;
3600  globalsize += concat_sizes[i];
3601  }
3602 
3603  // Check for quick return
3604  if (globalsize == 0)
3605  return;
3606 
3607  // Get the concatenated data from the remote processors.
3608  // Pass nullptr if our vector is empty.
3609  std::vector<T> concat(globalsize);
3610 
3611  // We may have concat_src.empty(), but we know concat has at least
3612  // one element we can use as an example for StandardType
3613  StandardType<T> send_type(concat.data());
3614 
3615  timpi_call_mpi
3616  (TIMPI_ALLGATHERV(concat_src.empty() ?
3617  nullptr : concat_src.data(), myconcatsize,
3618  send_type, concat.data(), concat_sizes.data(),
3619  displacements.data(), send_type, this->get()));
3620 
3621  // Finally, split concatenated data into strings
3622  const T * begin = concat.data();
3623  for (std::size_t i=0; i != r.size(); ++i)
3624  {
3625  const T * end = begin + strlengths[i];
3626  r[i].assign(begin, end);
3627  begin = end;
3628  }
3629 }
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
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...

◆ 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.

Definition at line 4228 of file parallel_implementation.h.

References TIMPI::Communicator::allgather(), TIMPI::Communicator::max(), TIMPI::pack_range(), and TIMPI::unpack_range().

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

4233 {
4234  typedef typename std::iterator_traits<Iter>::value_type T;
4235  typedef typename Packing<T>::buffer_type buffer_t;
4236 
4237  bool nonempty_range = (range_begin != range_end);
4238  this->max(nonempty_range);
4239 
4240  // OutputIter might not have operator= implemented; for maximum
4241  // compatibility we'll rely on its copy constructor.
4242  std::unique_ptr<OutputIter> next_out_iter =
4243  std::make_unique<OutputIter>(out_iter);
4244 
4245  while (nonempty_range)
4246  {
4247  // We will serialize variable size objects from *range_begin to
4248  // *range_end as a sequence of ints in this buffer
4249  std::vector<buffer_t> buffer;
4250 
4251  range_begin = pack_range
4252  (context, range_begin, range_end, buffer, approx_buffer_size);
4253 
4254  this->allgather(buffer, false);
4255 
4256  timpi_assert(buffer.size());
4257 
4258  auto return_out_iter = unpack_range
4259  (buffer, context, *next_out_iter, (T*)nullptr);
4260  next_out_iter = std::make_unique<OutputIter>(return_out_iter);
4261 
4262  nonempty_range = (range_begin != range_end);
4263  this->max(nonempty_range);
4264  }
4265 }
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...
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
void max(const T &r, T &o, Request &req) const
Non-blocking maximum of the local value r into o with the request req.

◆ 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.

Definition at line 3830 of file parallel_implementation.h.

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

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

3831 {
3832  if (this->size() < 2 || buf.empty())
3833  return;
3834 
3835  TIMPI_LOG_SCOPE("alltoall()", "Parallel");
3836 
3837  // the per-processor size. this is the same for all
3838  // processors using MPI_Alltoall, could be variable
3839  // using MPI_Alltoallv
3840  const CountType size_per_proc =
3841  cast_int<CountType>(buf.size()/this->size());
3842  ignore(size_per_proc);
3843 
3844  timpi_assert_equal_to (buf.size()%this->size(), 0);
3845 
3846  timpi_assert(this->verify(size_per_proc));
3847 
3848  StandardType<T> send_type(buf.data());
3849 
3850  timpi_call_mpi
3851  (TIMPI_ALLTOALL(MPI_IN_PLACE, size_per_proc, send_type, buf.data(),
3852  size_per_proc, send_type, this->get()));
3853 }
void ignore(const Args &...)
Definition: timpi_assert.h:54
processor_id_type size() const
Definition: communicator.h:211
MPI_Count CountType
Definition: status.h:47
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...

◆ 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

◆ broadcast() [1/5]

template<typename T , typename std::enable_if< Has_buffer_type< Packing< T >>::value, int >::type >
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

Definition at line 3888 of file parallel_implementation.h.

References TIMPI::Communicator::broadcast_packed_range(), TIMPI::ignore(), TIMPI::Communicator::rank(), and TIMPI::Communicator::size().

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

3891 {
3892  ignore(root_id); // Only needed for MPI and/or dbg/devel
3893  if (this->size() == 1)
3894  {
3895  timpi_assert (!this->rank());
3896  timpi_assert (!root_id);
3897  return;
3898  }
3899 
3900  timpi_assert_less (root_id, this->size());
3901 
3902 // // If we don't have MPI, then we should be done, and calling the below can
3903 // // have the side effect of instantiating Packing<T> classes that are not
3904 // // defined. (Normally we would be calling a more specialized overload of
3905 // // broacast that would then call broadcast_packed_range with appropriate
3906 // // template arguments)
3907 // #ifdef TIMPI_HAVE_MPI
3908  std::vector<T> range = {data};
3909 
3910  this->broadcast_packed_range((void *)(nullptr),
3911  range.begin(),
3912  range.end(),
3913  (void *)(nullptr),
3914  range.begin(),
3915  root_id);
3916 
3917  data = range[0];
3918 // #endif
3919 }
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.
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

◆ broadcast() [2/5]

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/5]

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 1716 of file parallel_implementation.h.

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

1719 {
1720  if (this->size() == 1)
1721  {
1722  timpi_assert (!this->rank());
1723  timpi_assert (!root_id);
1724  return;
1725  }
1726 
1727  timpi_assert_less (root_id, this->size());
1728  timpi_assert (this->verify(identical_sizes));
1729 
1730  TIMPI_LOG_SCOPE("broadcast()", "Parallel");
1731 
1732  std::size_t data_size = data.size();
1733 
1734  if (identical_sizes)
1735  timpi_assert(this->verify(data_size));
1736  else
1737  this->broadcast(data_size, root_id);
1738 
1739  std::vector<T> data_c(data_size);
1740 #ifndef NDEBUG
1741  std::basic_string<T> orig(data);
1742 #endif
1743 
1744  if (this->rank() == root_id)
1745  for (std::size_t i=0; i<data.size(); i++)
1746  data_c[i] = data[i];
1747 
1748  this->broadcast (data_c, root_id, StandardType<T>::is_fixed_type);
1749 
1750  data.assign(data_c.begin(), data_c.end());
1751 
1752 #ifndef NDEBUG
1753  if (this->rank() == root_id)
1754  timpi_assert_equal_to (data, orig);
1755 #endif
1756 }
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/5]

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 1760 of file parallel_implementation.h.

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

1763 {
1764  if (this->size() == 1)
1765  {
1766  timpi_assert (!this->rank());
1767  timpi_assert (!root_id);
1768  return;
1769  }
1770 
1771  timpi_assert_less (root_id, this->size());
1772  timpi_assert (this->verify(identical_sizes));
1773 
1774  TIMPI_LOG_SCOPE("broadcast()", "Parallel");
1775 
1776  std::size_t bufsize=0;
1777  if (root_id == this->rank() || identical_sizes)
1778  {
1779  for (std::size_t i=0; i<data.size(); ++i)
1780  bufsize += data[i].size() + 1; // Add one for the string length word
1781  }
1782 
1783  if (identical_sizes)
1784  timpi_assert(this->verify(bufsize));
1785  else
1786  this->broadcast(bufsize, root_id);
1787 
1788  // Here we use unsigned int to store up to 32-bit characters
1789  std::vector<unsigned int> temp; temp.reserve(bufsize);
1790  // Pack the strings
1791  if (root_id == this->rank())
1792  {
1793  for (std::size_t i=0; i<data.size(); ++i)
1794  {
1795  temp.push_back(cast_int<unsigned int>(data[i].size()));
1796  for (std::size_t j=0; j != data[i].size(); ++j)
1801  temp.push_back(data[i][j]);
1802  }
1803  }
1804  else
1805  temp.resize(bufsize);
1806 
1807  // broad cast the packed strings
1808  this->broadcast(temp, root_id, true);
1809 
1810  // Unpack the strings
1811  if (root_id != this->rank())
1812  {
1813  data.clear();
1814  typename std::vector<unsigned int>::const_iterator iter = temp.begin();
1815  while (iter != temp.end())
1816  {
1817  std::size_t curr_len = *iter++;
1818  data.push_back(std::basic_string<T>(iter, iter+curr_len));
1819  iter += curr_len;
1820  }
1821  }
1822 }
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() [5/5]

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

Definition at line 3863 of file parallel_implementation.h.

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

3866 {
3867  ignore(root_id); // Only needed for MPI and/or dbg/devel
3868  if (this->size() == 1)
3869  {
3870  timpi_assert (!this->rank());
3871  timpi_assert (!root_id);
3872  return;
3873  }
3874 
3875  timpi_assert_less (root_id, this->size());
3876 
3877  TIMPI_LOG_SCOPE("broadcast()", "Parallel");
3878 
3879  // Spread data to remote processors.
3880  timpi_call_mpi
3881  (TIMPI_BCAST(&data, 1, StandardType<T>(&data), root_id,
3882  this->get()));
3883 }
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

◆ 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.

Definition at line 4130 of file parallel_implementation.h.

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

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

4137 {
4138  typedef typename std::iterator_traits<Iter>::value_type T;
4139  typedef typename Packing<T>::buffer_type buffer_t;
4140 
4141  if (this->size() == 1)
4142  {
4143  timpi_assert (!this->rank());
4144  timpi_assert (!root_id);
4145  return;
4146  }
4147 
4148  do
4149  {
4150  // We will serialize variable size objects from *range_begin to
4151  // *range_end as a sequence of ints in this buffer
4152  std::vector<buffer_t> buffer;
4153 
4154  if (this->rank() == root_id)
4155  range_begin = pack_range
4156  (context1, range_begin, range_end, buffer, approx_buffer_size);
4157 
4158  // this->broadcast(vector) requires the receiving vectors to
4159  // already be the appropriate size
4160  std::size_t buffer_size = buffer.size();
4161  this->broadcast (buffer_size, root_id);
4162 
4163  // We continue until there's nothing left to broadcast
4164  if (!buffer_size)
4165  break;
4166 
4167  buffer.resize(buffer_size);
4168 
4169  // Broadcast the packed data
4170  this->broadcast (buffer, root_id);
4171 
4172  // OutputIter might not have operator= implemented; for maximum
4173  // compatibility we'll rely on its copy constructor.
4174  std::unique_ptr<OutputIter> next_out_iter =
4175  std::make_unique<OutputIter>(out_iter);
4176 
4177  if (this->rank() != root_id)
4178  {
4179  auto return_out_iter = unpack_range
4180  (buffer, context2, *next_out_iter, (T*)nullptr);
4181  next_out_iter = std::make_unique<OutputIter>(return_out_iter);
4182  }
4183  } while (true); // break above when we reach buffer_size==0
4184 }
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
processor_id_type size() const
Definition: communicator.h:211
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 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.

◆ 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.

Definition at line 3218 of file parallel_implementation.h.

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

Referenced by TIMPI::Communicator::gather(), TIMPI::Communicator::gather_packed_range(), testGather(), testGatherString(), and testGatherString2().

3221 {
3222  timpi_assert_less (root_id, this->size());
3223 
3224  if (this->rank() == root_id)
3225  recv.resize(this->size());
3226 
3227  if (this->size() > 1)
3228  {
3229  TIMPI_LOG_SCOPE("gather()", "Parallel");
3230 
3231  StandardType<T> send_type(&sendval);
3232 
3233  timpi_assert_less(root_id, this->size());
3234 
3235  timpi_call_mpi
3236  (TIMPI_GATHER(const_cast<T*>(&sendval), 1, send_type,
3237  recv.empty() ? nullptr : recv.data(), 1, send_type,
3238  root_id, this->get()));
3239  }
3240  else
3241  recv[0] = sendval;
3242 }
processor_id_type rank() const
Definition: communicator.h:208
processor_id_type size() const
Definition: communicator.h:211

◆ 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.

Definition at line 3318 of file parallel_implementation.h.

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

3322 {
3323  timpi_assert_less (root_id, this->size());
3324 
3325  if (this->rank() == root_id)
3326  recv.resize(this->size());
3327 
3328  if (this->size() > 1)
3329  {
3330  TIMPI_LOG_SCOPE ("gather()","Parallel");
3331 
3332  std::vector<CountType>
3333  sendlengths (this->size(), 0);
3334  std::vector<DispType>
3335  displacements(this->size(), 0);
3336 
3337  const CountType mysize = cast_int<CountType>(sendval.size());
3338 
3339  if (identical_buffer_sizes)
3340  sendlengths.assign(this->size(), mysize);
3341  else
3342  // first comm step to determine buffer sizes from all processors
3343  this->gather(root_id, mysize, sendlengths);
3344 
3345  // Find the total size of the final array and
3346  // set up the displacement offsets for each processor
3347  CountType globalsize = 0;
3348  for (unsigned int i=0; i < this->size(); ++i)
3349  {
3350  displacements[i] = globalsize;
3351  globalsize += sendlengths[i];
3352  }
3353 
3354  // monolithic receive buffer
3355  std::basic_string<T> r;
3356  if (this->rank() == root_id)
3357  r.resize(globalsize, 0);
3358 
3359  timpi_assert_less(root_id, this->size());
3360 
3361  // and get the data from the remote processors.
3362  timpi_call_mpi
3363  (TIMPI_GATHERV(const_cast<T*>(sendval.data()),
3364  mysize, StandardType<T>(),
3365  this->rank() == root_id ? &r[0] : nullptr,
3366  sendlengths.data(), displacements.data(),
3367  StandardType<T>(), root_id, this->get()));
3368 
3369  // slice receive buffer up
3370  if (this->rank() == root_id)
3371  for (unsigned int i=0; i != this->size(); ++i)
3372  recv[i] = r.substr(displacements[i], sendlengths[i]);
3373  }
3374  else
3375  recv[0] = sendval;
3376 }
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 ...
processor_id_type rank() const
Definition: communicator.h:208
processor_id_type size() const
Definition: communicator.h:211
MPI_Count CountType
Definition: status.h:47

◆ gather() [3/4]

template<typename T , typename A , typename std::enable_if< Has_buffer_type< Packing< T >>::value, int >::type >
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.

Definition at line 3248 of file parallel_implementation.h.

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

3250 {
3251  if (this->size() == 1)
3252  {
3253  timpi_assert (!this->rank());
3254  timpi_assert (!root_id);
3255  return;
3256  }
3257 
3258  timpi_assert_less (root_id, this->size());
3259 
3260  std::vector<CountType>
3261  sendlengths (this->size(), 0);
3262  std::vector<DispType>
3263  displacements(this->size(), 0);
3264 
3265  const CountType mysize = cast_int<CountType>(r.size());
3266  this->allgather(mysize, sendlengths);
3267 
3268  TIMPI_LOG_SCOPE("gather()", "Parallel");
3269 
3270  // Find the total size of the final array and
3271  // set up the displacement offsets for each processor.
3272  CountType globalsize = 0;
3273  for (unsigned int i=0; i != this->size(); ++i)
3274  {
3275  displacements[i] = globalsize;
3276  globalsize += sendlengths[i];
3277  }
3278 
3279  // Check for quick return
3280  if (globalsize == 0)
3281  return;
3282 
3283  // copy the input buffer
3284  std::vector<T,A> r_src(r);
3285 
3286  // now resize it to hold the global data
3287  // on the receiving processor
3288  if (root_id == this->rank())
3289  r.resize(globalsize);
3290 
3291  timpi_assert_less(root_id, this->size());
3292 
3293  // and get the data from the remote processors
3294  timpi_call_mpi
3295  (TIMPI_GATHERV(r_src.empty() ? nullptr : r_src.data(), mysize,
3296  StandardType<T>(), r.empty() ? nullptr : r.data(),
3297  sendlengths.data(), displacements.data(),
3298  StandardType<T>(), root_id, this->get()));
3299 }
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 rank() const
Definition: communicator.h:208
processor_id_type size() const
Definition: communicator.h:211
MPI_Count CountType
Definition: status.h:47

◆ 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.

Definition at line 4188 of file parallel_implementation.h.

References TIMPI::Communicator::gather(), TIMPI::Communicator::max(), TIMPI::pack_range(), and TIMPI::unpack_range().

4194 {
4195  typedef typename std::iterator_traits<Iter>::value_type T;
4196  typedef typename Packing<T>::buffer_type buffer_t;
4197 
4198  bool nonempty_range = (range_begin != range_end);
4199  this->max(nonempty_range);
4200 
4201  // OutputIter might not have operator= implemented; for maximum
4202  // compatibility we'll rely on its copy constructor.
4203  std::unique_ptr<OutputIter> next_out_iter =
4204  std::make_unique<OutputIter>(out_iter);
4205 
4206  while (nonempty_range)
4207  {
4208  // We will serialize variable size objects from *range_begin to
4209  // *range_end as a sequence of ints in this buffer
4210  std::vector<buffer_t> buffer;
4211 
4212  range_begin = pack_range
4213  (context, range_begin, range_end, buffer, approx_buffer_size);
4214 
4215  this->gather(root_id, buffer);
4216 
4217  auto return_out_iter = unpack_range
4218  (buffer, context, *next_out_iter, (T*)(nullptr));
4219  next_out_iter = std::make_unique<OutputIter>(return_out_iter);
4220 
4221  nonempty_range = (range_begin != range_end);
4222  this->max(nonempty_range);
4223  }
4224 }
OutputIter unpack_range(const std::vector< buffertype > &buffer, Context *context, OutputIter out_iter, const T *)
Helper function for range unpacking.
Definition: packing.h:1103
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 ...
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 max(const T &r, T &o, Request &req) const
Non-blocking maximum of the local value r into o with the request req.

◆ 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.

◆ map_broadcast() [1/2]

template<typename Map , typename std::enable_if< std::is_base_of< DataType, StandardType< typename Map::key_type >>::value &&std::is_base_of< DataType, StandardType< typename Map::mapped_type >>::value, int >::type >
void TIMPI::Communicator::map_broadcast ( Map &  timpi_mpi_vardata,
const unsigned int  root_id,
const bool   timpi_mpi_varidentical_sizes 
) const
inlineinherited

Definition at line 4005 of file parallel_implementation.h.

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

4008 {
4009  ignore(root_id); // Only needed for MPI and/or dbg/devel
4010  if (this->size() == 1)
4011  {
4012  timpi_assert (!this->rank());
4013  timpi_assert (!root_id);
4014  return;
4015  }
4016 
4017 #ifdef TIMPI_HAVE_MPI
4018  timpi_assert_less (root_id, this->size());
4019  timpi_assert (this->verify(identical_sizes));
4020 
4021  TIMPI_LOG_SCOPE("broadcast(map)", "Parallel");
4022 
4023  std::size_t data_size=data.size();
4024  if (identical_sizes)
4025  timpi_assert(this->verify(data_size));
4026  else
4027  this->broadcast(data_size, root_id);
4028 
4029  std::vector<std::pair<typename Map::key_type,
4030  typename Map::mapped_type>> comm_data;
4031 
4032  if (root_id == this->rank())
4033  comm_data.assign(data.begin(), data.end());
4034  else
4035  comm_data.resize(data_size);
4036 
4037  this->broadcast(comm_data, root_id, true);
4038 
4039  if (this->rank() != root_id)
4040  {
4041  data.clear();
4042  data.insert(comm_data.begin(), comm_data.end());
4043  }
4044 #endif
4045 }
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
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...

◆ map_broadcast() [2/2]

template<typename Map >
void TIMPI::Communicator::map_broadcast ( Map &  timpi_mpi_vardata,
const unsigned int  root_id,
const bool   timpi_mpi_varidentical_sizes 
) const
inlineinherited

Definition at line 4051 of file parallel_implementation.h.

References TIMPI::ignore().

4054 {
4055  ignore(root_id); // Only needed for MPI and/or dbg/devel
4056  if (this->size() == 1)
4057  {
4058  timpi_assert (!this->rank());
4059  timpi_assert (!root_id);
4060  return;
4061  }
4062 
4063 #ifdef TIMPI_HAVE_MPI
4064  timpi_assert_less (root_id, this->size());
4065  timpi_assert (this->verify(identical_sizes));
4066 
4067  TIMPI_LOG_SCOPE("broadcast()", "Parallel");
4068 
4069  std::size_t data_size=data.size();
4070  if (identical_sizes)
4071  timpi_assert(this->verify(data_size));
4072  else
4073  this->broadcast(data_size, root_id);
4074 
4075  std::vector<typename Map::key_type> pair_first; pair_first.reserve(data_size);
4076  std::vector<typename Map::mapped_type> pair_second; pair_first.reserve(data_size);
4077 
4078  if (root_id == this->rank())
4079  {
4080  for (const auto & pr : data)
4081  {
4082  pair_first.push_back(pr.first);
4083  pair_second.push_back(pr.second);
4084  }
4085  }
4086  else
4087  {
4088  pair_first.resize(data_size);
4089  pair_second.resize(data_size);
4090  }
4091 
4092  this->broadcast
4093  (pair_first, root_id,
4095  this->broadcast
4096  (pair_second, root_id,
4098 
4099  timpi_assert(pair_first.size() == pair_first.size());
4100 
4101  if (this->rank() != root_id)
4102  {
4103  data.clear();
4104  for (std::size_t i=0; i<pair_first.size(); ++i)
4105  data[pair_first[i]] = pair_second[i];
4106  }
4107 #endif
4108 }
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
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...

◆ max() [1/4]

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

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

Definition at line 2356 of file parallel_implementation.h.

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

Referenced by TIMPI::Communicator::allgather_packed_range(), TIMPI::detail::empty_send_assertion(), TIMPI::Communicator::gather_packed_range(), TIMPI::Communicator::get_unique_tag(), TIMPI::detail::push_parallel_roundrobin_helper(), TIMPI::Communicator::semiverify(), testInfinityMax(), testMapMax(), testMax(), testMaxVecBool(), testNonblockingMax(), testNonFixedTypeMapMax(), and TIMPI::Communicator::verify().

2359 {
2360  if (this->size() > 1)
2361  {
2362  TIMPI_LOG_SCOPE("max()", "Parallel");
2363 
2364  timpi_call_mpi
2365  (TIMPI_IALLREDUCE(&r, &o, 1, StandardType<T>(&r),
2366  OpFunction<T>::max(), this->get(),
2367  req.get()));
2368  }
2369  else
2370  {
2371  o = r;
2372  req = Request::null_request;
2373  }
2374 }
static const request null_request
Definition: request.h:111
processor_id_type size() const
Definition: communicator.h:211

◆ max() [2/4]

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/4]

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

Definition at line 2378 of file parallel_implementation.h.

References TIMPI::Communicator::size().

2379 {
2380  if (this->size() > 1)
2381  {
2382  TIMPI_LOG_SCOPE("max(scalar)", "Parallel");
2383 
2384  timpi_call_mpi
2385  (TIMPI_ALLREDUCE (MPI_IN_PLACE, &r, 1, StandardType<T>(&r),
2386  OpFunction<T>::max(), this->get()));
2387  }
2388 }
processor_id_type size() const
Definition: communicator.h:211

◆ max() [4/4]

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

Definition at line 2410 of file parallel_implementation.h.

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

2411 {
2412  if (this->size() > 1 && !r.empty())
2413  {
2414  TIMPI_LOG_SCOPE("max(vector<bool>)", "Parallel");
2415 
2416  timpi_assert(this->verify(r.size()));
2417 
2418  std::vector<unsigned int> ruint;
2419  pack_vector_bool(r, ruint);
2420  std::vector<unsigned int> temp(ruint.size());
2421  timpi_call_mpi
2422  (TIMPI_ALLREDUCE (ruint.data(), temp.data(),
2423  cast_int<CountType>(ruint.size()),
2424  StandardType<unsigned int>(), MPI_BOR,
2425  this->get()));
2426  unpack_vector_bool(temp, r);
2427  }
2428 }
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 2548 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().

2550 {
2551  if (this->size() > 1)
2552  {
2553  TIMPI_LOG_SCOPE("maxloc(scalar)", "Parallel");
2554 
2555  DataPlusInt<T> data_in;
2556  ignore(data_in); // unused ifndef TIMPI_HAVE_MPI
2557  data_in.val = r;
2558  data_in.rank = this->rank();
2559 
2560  timpi_call_mpi
2561  (TIMPI_ALLREDUCE (MPI_IN_PLACE, &data_in, 1,
2562  dataplusint_type_acquire<T>().first,
2563  OpFunction<T>::max_location(), this->get()));
2564  r = data_in.val;
2565  max_id = data_in.rank;
2566  }
2567  else
2568  max_id = this->rank();
2569 }
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 2573 of file parallel_implementation.h.

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

2575 {
2576  if (this->size() > 1 && !r.empty())
2577  {
2578  TIMPI_LOG_SCOPE("maxloc(vector)", "Parallel");
2579 
2580  timpi_assert(this->verify(r.size()));
2581 
2582  std::vector<DataPlusInt<T>> data_in(r.size());
2583  for (std::size_t i=0; i != r.size(); ++i)
2584  {
2585  data_in[i].val = r[i];
2586  data_in[i].rank = this->rank();
2587  }
2588  std::vector<DataPlusInt<T>> data_out(r.size());
2589 
2590  timpi_call_mpi
2591  (TIMPI_ALLREDUCE(data_in.data(), data_out.data(),
2592  cast_int<CountType>(r.size()),
2593  dataplusint_type_acquire<T>().first,
2594  OpFunction<T>::max_location(),
2595  this->get()));
2596  for (std::size_t i=0; i != r.size(); ++i)
2597  {
2598  r[i] = data_out[i].val;
2599  max_id[i] = data_out[i].rank;
2600  }
2601  }
2602  else if (!r.empty())
2603  {
2604  for (std::size_t i=0; i != r.size(); ++i)
2605  max_id[i] = this->rank();
2606  }
2607 }
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 2611 of file parallel_implementation.h.

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

2613 {
2614  if (this->size() > 1 && !r.empty())
2615  {
2616  TIMPI_LOG_SCOPE("maxloc(vector<bool>)", "Parallel");
2617 
2618  timpi_assert(this->verify(r.size()));
2619 
2620  std::vector<DataPlusInt<int>> data_in(r.size());
2621  for (std::size_t i=0; i != r.size(); ++i)
2622  {
2623  data_in[i].val = r[i];
2624  data_in[i].rank = this->rank();
2625  }
2626  std::vector<DataPlusInt<int>> data_out(r.size());
2627  timpi_call_mpi
2628  (TIMPI_ALLREDUCE(data_in.data(), data_out.data(),
2629  cast_int<CountType>(r.size()),
2630  StandardType<int>(),
2631  OpFunction<int>::max_location(),
2632  this->get()));
2633  for (std::size_t i=0; i != r.size(); ++i)
2634  {
2635  r[i] = data_out[i].val;
2636  max_id[i] = data_out[i].rank;
2637  }
2638  }
2639  else if (!r.empty())
2640  {
2641  for (std::size_t i=0; i != r.size(); ++i)
2642  max_id[i] = this->rank();
2643  }
2644 }
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/4]

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

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

Definition at line 2179 of file parallel_implementation.h.

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

Referenced by TIMPI::Communicator::semiverify(), testInfinityMin(), testMin(), testMinLarge(), testMinVecBool(), testNonblockingMin(), testNonblockingTest(), testNonblockingWaitany(), and TIMPI::Communicator::verify().

2182 {
2183  if (this->size() > 1)
2184  {
2185  TIMPI_LOG_SCOPE("min()", "Parallel");
2186 
2187  timpi_call_mpi
2188  (TIMPI_IALLREDUCE(&r, &o, 1, StandardType<T>(&r),
2189  OpFunction<T>::min(), this->get(),
2190  req.get()));
2191  }
2192  else
2193  {
2194  o = r;
2195  req = Request::null_request;
2196  }
2197 }
static const request null_request
Definition: request.h:111
processor_id_type size() const
Definition: communicator.h:211

◆ min() [2/4]

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/4]

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

Definition at line 2202 of file parallel_implementation.h.

References TIMPI::Communicator::size().

2203 {
2204  if (this->size() > 1)
2205  {
2206  TIMPI_LOG_SCOPE("min(scalar)", "Parallel");
2207 
2208  timpi_call_mpi
2209  (TIMPI_ALLREDUCE(MPI_IN_PLACE, &r, 1,
2210  StandardType<T>(&r), OpFunction<T>::min(),
2211  this->get()));
2212  }
2213 }
processor_id_type size() const
Definition: communicator.h:211

◆ min() [4/4]

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

Definition at line 2236 of file parallel_implementation.h.

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

2237 {
2238  if (this->size() > 1 && !r.empty())
2239  {
2240  TIMPI_LOG_SCOPE("min(vector<bool>)", "Parallel");
2241 
2242  timpi_assert(this->verify(r.size()));
2243 
2244  std::vector<unsigned int> ruint;
2245  pack_vector_bool(r, ruint);
2246  std::vector<unsigned int> temp(ruint.size());
2247  timpi_call_mpi
2248  (TIMPI_ALLREDUCE
2249  (ruint.data(), temp.data(),
2250  cast_int<CountType>(ruint.size()),
2251  StandardType<unsigned int>(), MPI_BAND, this->get()));
2252  unpack_vector_bool(temp, r);
2253  }
2254 }
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 2258 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().

2260 {
2261  if (this->size() > 1)
2262  {
2263  TIMPI_LOG_SCOPE("minloc(scalar)", "Parallel");
2264 
2265  DataPlusInt<T> data_in;
2266  ignore(data_in); // unused ifndef TIMPI_HAVE_MPI
2267  data_in.val = r;
2268  data_in.rank = this->rank();
2269 
2270  timpi_call_mpi
2271  (TIMPI_ALLREDUCE (MPI_IN_PLACE, &data_in, 1,
2272  dataplusint_type_acquire<T>().first,
2273  OpFunction<T>::min_location(), this->get()));
2274  r = data_in.val;
2275  min_id = data_in.rank;
2276  }
2277  else
2278  min_id = this->rank();
2279 }
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 2283 of file parallel_implementation.h.

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

2285 {
2286  if (this->size() > 1 && !r.empty())
2287  {
2288  TIMPI_LOG_SCOPE("minloc(vector)", "Parallel");
2289 
2290  timpi_assert(this->verify(r.size()));
2291 
2292  std::vector<DataPlusInt<T>> data_in(r.size());
2293  for (std::size_t i=0; i != r.size(); ++i)
2294  {
2295  data_in[i].val = r[i];
2296  data_in[i].rank = this->rank();
2297  }
2298  std::vector<DataPlusInt<T>> data_out(r.size());
2299 
2300  timpi_call_mpi
2301  (TIMPI_ALLREDUCE (data_in.data(), data_out.data(),
2302  cast_int<CountType>(r.size()),
2303  dataplusint_type_acquire<T>().first,
2304  OpFunction<T>::min_location(), this->get()));
2305  for (std::size_t i=0; i != r.size(); ++i)
2306  {
2307  r[i] = data_out[i].val;
2308  min_id[i] = data_out[i].rank;
2309  }
2310  }
2311  else if (!r.empty())
2312  {
2313  for (std::size_t i=0; i != r.size(); ++i)
2314  min_id[i] = this->rank();
2315  }
2316 }
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 2320 of file parallel_implementation.h.

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

2322 {
2323  if (this->size() > 1 && !r.empty())
2324  {
2325  TIMPI_LOG_SCOPE("minloc(vector<bool>)", "Parallel");
2326 
2327  timpi_assert(this->verify(r.size()));
2328 
2329  std::vector<DataPlusInt<int>> data_in(r.size());
2330  for (std::size_t i=0; i != r.size(); ++i)
2331  {
2332  data_in[i].val = r[i];
2333  data_in[i].rank = this->rank();
2334  }
2335  std::vector<DataPlusInt<int>> data_out(r.size());
2336  timpi_call_mpi
2337  (TIMPI_ALLREDUCE
2338  (data_in.data(), data_out.data(),
2339  cast_int<CountType>(r.size()), StandardType<int>(),
2340  OpFunction<int>::min_location(), this->get()));
2341  for (std::size_t i=0; i != r.size(); ++i)
2342  {
2343  r[i] = data_out[i].val;
2344  min_id[i] = data_out[i].rank;
2345  }
2346  }
2347  else if (!r.empty())
2348  {
2349  for (std::size_t i=0; i != r.size(); ++i)
2350  min_id[i] = this->rank();
2351  }
2352 }
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 1286 of file parallel_implementation.h.

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

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

1293 {
1294  typedef typename Packing<T>::buffer_type buffer_t;
1295 
1296  // Receive serialized variable size objects as a sequence of
1297  // buffer_t.
1298  // Allocate a buffer on the heap so we don't have to free it until
1299  // after the Request::wait()
1300  std::vector<buffer_t> * buffer = new std::vector<buffer_t>(stat.size());
1301  this->receive(src_processor_id, *buffer, req, tag);
1302 
1303  // Make the Request::wait() handle unpacking the buffer
1304  req.add_post_wait_work
1305  (new PostWaitUnpackBuffer<std::vector<buffer_t>, Context, OutputIter, T>(*buffer, context, out));
1306 
1307  // Make the Request::wait() then handle deleting the buffer
1308  req.add_post_wait_work
1309  (new PostWaitDeleteBuffer<std::vector<buffer_t>>(buffer));
1310 
1311  // The MessageTag should stay registered for the Request lifetime
1312  req.add_post_wait_work
1313  (new PostWaitDereferenceTag(tag));
1314 }
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 1933 of file parallel_implementation.h.

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

1941 {
1942  // If they didn't pass in a buffer - let's make one
1943  if (buffer == nullptr)
1944  buffer = std::make_shared<std::vector<typename Packing<T>::buffer_type>>();
1945  else
1946  buffer->clear();
1947 
1948  // Receive serialized variable size objects as a sequence of
1949  // buffer_t.
1950  // Allocate a buffer on the heap so we don't have to free it until
1951  // after the Request::wait()
1952  buffer->resize(stat.size());
1953  this->receive(src_processor_id, *buffer, req, tag);
1954 
1955  // Make the Request::wait() handle unpacking the buffer
1956  req.add_post_wait_work
1957  (new PostWaitUnpackBuffer<std::vector<typename Packing<T>::buffer_type>, Context, OutputIter, T>(*buffer, context, out));
1958 
1959  // Make it dereference the shared pointer (possibly freeing the buffer)
1960  req.add_post_wait_work
1961  (new PostWaitDereferenceSharedPtr<std::vector<typename Packing<T>::buffer_type>>(buffer));
1962 }
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 773 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().

779 {
780  // Allocate a buffer on the heap so we don't have to free it until
781  // after the Request::wait()
782  typedef typename std::iterator_traits<Iter>::value_type T;
783  typedef typename Packing<T>::buffer_type buffer_t;
784 
785  if (range_begin != range_end)
786  {
787  std::vector<buffer_t> * buffer = new std::vector<buffer_t>();
788 
789  range_begin =
790  pack_range(context,
791  range_begin,
792  range_end,
793  *buffer,
794  // MPI-2/3 can only use signed integers for size,
795  // and with this API we need to fit a non-blocking
796  // send into one buffer
797  std::numeric_limits<CountType>::max());
798 
799  if (range_begin != range_end)
800  timpi_error_msg("Non-blocking packed range sends cannot exceed " << std::numeric_limits<CountType>::max() << "in size");
801 
802  // Make the Request::wait() handle deleting the buffer
803  req.add_post_wait_work
804  (new PostWaitDeleteBuffer<std::vector<buffer_t>>
805  (buffer));
806 
807  // Non-blocking send of the buffer
808  this->send(dest_processor_id, *buffer, req, tag);
809  }
810 }
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 1580 of file parallel_implementation.h.

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

1587 {
1588  // Allocate a buffer on the heap so we don't have to free it until
1589  // after the Request::wait()
1590  typedef typename std::iterator_traits<Iter>::value_type T;
1591  typedef typename Packing<T>::buffer_type buffer_t;
1592 
1593  if (range_begin != range_end)
1594  {
1595  if (buffer == nullptr)
1596  buffer = std::make_shared<std::vector<buffer_t>>();
1597  else
1598  buffer->clear();
1599 
1600  range_begin =
1601  pack_range(context,
1602  range_begin,
1603  range_end,
1604  *buffer,
1605  // MPI-2/3 can only use signed integers for size,
1606  // and with this API we need to fit a non-blocking
1607  // send into one buffer
1608  std::numeric_limits<CountType>::max());
1609 
1610  if (range_begin != range_end)
1611  timpi_error_msg("Non-blocking packed range sends cannot exceed " << std::numeric_limits<CountType>::max() << "in size");
1612 
1613  // Make it dereference the shared pointer (possibly freeing the buffer)
1614  req.add_post_wait_work
1615  (new PostWaitDereferenceSharedPtr<std::vector<buffer_t>>(buffer));
1616 
1617  // Non-blocking send of the buffer
1618  this->send(dest_processor_id, *buffer, req, tag);
1619  }
1620 }
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.

Definition at line 4270 of file parallel_implementation.h.

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

Referenced by TIMPI::push_parallel_packed_range().

4273 {
4274  TIMPI_LOG_SCOPE("packed_range_probe()", "Parallel");
4275 
4276  ignore(src_processor_id, tag); // unused in opt mode w/o MPI
4277 
4278  Status stat((StandardType<typename Packing<T>::buffer_type>()));
4279 
4280  int int_flag = 0;
4281 
4282  timpi_assert(src_processor_id < this->size() ||
4283  src_processor_id == any_source);
4284 
4285  timpi_call_mpi(MPI_Iprobe(int(src_processor_id),
4286  tag.value(),
4287  this->get(),
4288  &int_flag,
4289  stat.get()));
4290 
4291  flag = int_flag;
4292 
4293  return stat;
4294 }
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
processor_id_type size() const
Definition: communicator.h:211

◆ possibly_receive() [1/6]

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,
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

Definition at line 4300 of file parallel_implementation.h.

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

4304 {
4305  T * dataptr = buf.empty() ? nullptr : buf.data();
4306 
4307  return this->possibly_receive(src_processor_id, buf, StandardType<T>(dataptr), req, tag);
4308 }
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.

◆ possibly_receive() [2/6]

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/6]

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 1967 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().

1972 {
1973  TIMPI_LOG_SCOPE("possibly_receive()", "Parallel");
1974 
1975  Status stat(type);
1976 
1977  int int_flag = 0;
1978 
1979  timpi_assert(src_processor_id < this->size() ||
1980  src_processor_id == any_source);
1981 
1982  timpi_call_mpi(MPI_Iprobe(int(src_processor_id),
1983  tag.value(),
1984  this->get(),
1985  &int_flag,
1986  stat.get()));
1987 
1988  if (int_flag)
1989  {
1990  buf.resize(stat.size());
1991 
1992  src_processor_id = stat.source();
1993 
1994  timpi_call_mpi
1995  (TIMPI_IRECV(buf.data(), cast_int<CountType>(buf.size()), type,
1996  src_processor_id, tag.value(), this->get(),
1997  req.get()));
1998 
1999  // The MessageTag should stay registered for the Request lifetime
2000  req.add_post_wait_work
2001  (new PostWaitDereferenceTag(tag));
2002  }
2003 
2004  return int_flag;
2005 }
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/6]

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 2008 of file parallel_implementation.h.

References TIMPI::Communicator::possibly_receive_packed_range().

2013 {
2014  TIMPI_LOG_SCOPE("possibly_receive()", "Parallel");
2015 
2016  return this->possibly_receive_packed_range(src_processor_id,
2017  (void *)(nullptr),
2018  std::inserter(buf, buf.end()),
2019  (T *)(nullptr),
2020  req,
2021  tag);
2022 }
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/6]

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 2027 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().

2032 {
2033  TIMPI_LOG_SCOPE("possibly_receive()", "Parallel");
2034 
2035  Status stat(type);
2036 
2037  int int_flag = 0;
2038 
2039  timpi_assert(src_processor_id < this->size() ||
2040  src_processor_id == any_source);
2041 
2042  timpi_call_mpi(MPI_Iprobe(int(src_processor_id),
2043  tag.value(),
2044  this->get(),
2045  &int_flag,
2046  stat.get()));
2047 
2048  if (int_flag)
2049  {
2050  src_processor_id = stat.source();
2051 
2052  std::vector<char> * recvbuf =
2053  new std::vector<char>(stat.size(StandardType<char>()));
2054 
2055  this->receive(src_processor_id, *recvbuf, MPI_PACKED, req, tag);
2056 
2057  // When we wait on the receive, we'll unpack the temporary buffer
2058  req.add_post_wait_work
2059  (new PostWaitUnpackNestedBuffer<std::vector<std::vector<T,A1>,A2>>
2060  (*recvbuf, buf, type, *this));
2061 
2062  // And then we'll free the temporary buffer
2063  req.add_post_wait_work
2064  (new PostWaitDeleteBuffer<std::vector<char>>(recvbuf));
2065 
2066  // The MessageTag should stay registered for the Request lifetime
2067  req.add_post_wait_work
2068  (new PostWaitDereferenceTag(tag));
2069  }
2070 
2071  return int_flag;
2072 }
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() [6/6]

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,
Request req,
const MessageTag tag 
) const
inlineinherited

Definition at line 4328 of file parallel_implementation.h.

References TIMPI::Communicator::possibly_receive().

4332 {
4333  T * dataptr = buf.empty() ? nullptr : (buf[0].empty() ? nullptr : buf[0].data());
4334 
4335  return this->possibly_receive(src_processor_id, buf, StandardType<T>(dataptr), req, tag);
4336 }
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.

◆ 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
inlineinherited

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

Definition at line 4340 of file parallel_implementation.h.

References TIMPI::Request::add_post_wait_work(), TIMPI::any_source, TIMPI::Communicator::nonblocking_receive_packed_range(), and TIMPI::Communicator::size().

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

4346 {
4347  TIMPI_LOG_SCOPE("possibly_receive_packed_range()", "Parallel");
4348 
4349  bool int_flag = 0;
4350 
4351  auto stat = packed_range_probe<T>(src_processor_id, tag, int_flag);
4352 
4353  if (int_flag)
4354  {
4355  src_processor_id = stat.source();
4356 
4357  nonblocking_receive_packed_range(src_processor_id,
4358  context,
4359  out,
4360  type,
4361  req,
4362  stat,
4363  tag);
4364 
4365  // The MessageTag should stay registered for the Request lifetime
4366  req.add_post_wait_work
4367  (new PostWaitDereferenceTag(tag));
4368  }
4369 
4370  timpi_assert(!int_flag || (int_flag &&
4371  src_processor_id < this->size() &&
4372  src_processor_id != any_source));
4373 
4374  return int_flag;
4375 }
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.
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

◆ 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

◆ 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::Communicator::broadcast_packed_range(), TIMPI::detail::empty_send_assertion(), fill_data(), fill_scalar_data(), fill_vector_data(), TIMPI::Communicator::gather(), TIMPI::Communicator::map_broadcast(), 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::scatter(), 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(), 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 858 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(), testRecvIsendSets(), testRecvIsendVecVecs(), and testSendRecvVecVecs().

861 {
862  TIMPI_LOG_SCOPE("receive()", "Parallel");
863 
864  // Get the status of the message, explicitly provide the
865  // datatype so we can later query the size
866  Status stat(this->probe(src_processor_id, tag), StandardType<T>(&buf));
867 
868  timpi_assert(src_processor_id < this->size() ||
869  src_processor_id == any_source);
870 
871  timpi_call_mpi
872  (TIMPI_RECV (&buf, 1, StandardType<T>(&buf), src_processor_id,
873  tag.value(), this->get(), stat.get()));
874 
875  return stat;
876 }
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 881 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().

885 {
886  TIMPI_LOG_SCOPE("receive()", "Parallel");
887 
888  timpi_assert(src_processor_id < this->size() ||
889  src_processor_id == any_source);
890 
891  timpi_call_mpi
892  (TIMPI_IRECV (&buf, 1, StandardType<T>(&buf), src_processor_id,
893  tag.value(), this->get(), req.get()));
894 
895  // The MessageTag should stay registered for the Request lifetime
896  req.add_post_wait_work
897  (new PostWaitDereferenceTag(tag));
898 }
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 814 of file parallel_implementation.h.

References TIMPI::Communicator::receive().

817 {
818  std::vector<T> tempbuf; // Officially C++ won't let us get a
819  // modifiable array from a string
820 
821  Status stat = this->receive(src_processor_id, tempbuf, tag);
822  buf.assign(tempbuf.begin(), tempbuf.end());
823  return stat;
824 }
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 829 of file parallel_implementation.h.

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

833 {
834  // Officially C++ won't let us get a modifiable array from a
835  // string, and we can't even put one on the stack for the
836  // non-blocking case.
837  std::vector<T> * tempbuf = new std::vector<T>();
838 
839  // We can clear the string, but the Request::wait() will need to
840  // handle copying our temporary buffer to it
841  buf.clear();
842 
843  req.add_post_wait_work
844  (new PostWaitCopyBuffer<std::vector<T>,
845  std::back_insert_iterator<std::basic_string<T>>>
846  (tempbuf, std::back_inserter(buf)));
847 
848  // Make the Request::wait() then handle deleting the buffer
849  req.add_post_wait_work
850  (new PostWaitDeleteBuffer<std::vector<T>>(tempbuf));
851 
852  this->receive(src_processor_id, tempbuf, req, tag);
853 }
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 1222 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().

1227 {
1228  typedef typename Packing<T>::buffer_type buffer_t;
1229 
1230  // Receive serialized variable size objects as sequences of buffer_t
1231  std::size_t total_buffer_size = 0;
1232  Status stat = this->receive(src_processor_id, total_buffer_size, tag);
1233 
1234  // Use stat.source() and stat.tag() in subsequent receives - if
1235  // src_processor_id is or tag is "any" then we want to be sure we
1236  // try to receive messages all corresponding to the same send.
1237 
1238  std::size_t received_buffer_size = 0;
1239 
1240  // OutputIter might not have operator= implemented; for maximum
1241  // compatibility we'll rely on its copy constructor.
1242  std::unique_ptr<OutputIter> next_out_iter =
1243  std::make_unique<OutputIter>(out_iter);
1244 
1245  while (received_buffer_size < total_buffer_size)
1246  {
1247  std::vector<buffer_t> buffer;
1248  this->receive(stat.source(), buffer, MessageTag(stat.tag()));
1249  received_buffer_size += buffer.size();
1250  auto return_out_iter = unpack_range
1251  (buffer, context, *next_out_iter, output_type);
1252  next_out_iter = std::make_unique<OutputIter>(return_out_iter);
1253  }
1254 }
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.

Definition at line 3634 of file parallel_implementation.h.

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

Referenced by TIMPI::Communicator::scatter(), and testScatter().

3637 {
3638  ignore(root_id); // Only needed for MPI and/or dbg/devel
3639  timpi_assert_less (root_id, this->size());
3640 
3641  // Do not allow the root_id to scatter a nullptr vector.
3642  // That would leave recv in an indeterminate state.
3643  timpi_assert (this->rank() != root_id || this->size() == data.size());
3644 
3645  if (this->size() == 1)
3646  {
3647  timpi_assert (!this->rank());
3648  timpi_assert (!root_id);
3649  recv = data[0];
3650  return;
3651  }
3652 
3653  TIMPI_LOG_SCOPE("scatter()", "Parallel");
3654 
3655  T * data_ptr = const_cast<T*>(data.empty() ? nullptr : data.data());
3656  ignore(data_ptr); // unused ifndef TIMPI_HAVE_MPI
3657 
3658  timpi_assert_less(root_id, this->size());
3659 
3660  timpi_call_mpi
3661  (TIMPI_SCATTER(data_ptr, 1, StandardType<T>(data_ptr),
3662  &recv, 1, StandardType<T>(&recv), root_id, this->get()));
3663 }
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

◆ 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.

Definition at line 3668 of file parallel_implementation.h.

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

3671 {
3672  timpi_assert_less (root_id, this->size());
3673 
3674  if (this->size() == 1)
3675  {
3676  timpi_assert (!this->rank());
3677  timpi_assert (!root_id);
3678  recv.assign(data.begin(), data.end());
3679  return;
3680  }
3681 
3682  TIMPI_LOG_SCOPE("scatter()", "Parallel");
3683 
3684  std::size_t recv_buffer_size = 0;
3685  if (this->rank() == root_id)
3686  {
3687  timpi_assert(data.size() % this->size() == 0);
3688  recv_buffer_size = cast_int<std::size_t>(data.size() / this->size());
3689  }
3690 
3691  this->broadcast(recv_buffer_size);
3692  recv.resize(recv_buffer_size);
3693 
3694  T * data_ptr = const_cast<T*>(data.empty() ? nullptr : data.data());
3695  T * recv_ptr = recv.empty() ? nullptr : recv.data();
3696  ignore(data_ptr, recv_ptr); // unused ifndef TIMPI_HAVE_MPI
3697 
3698  timpi_assert_less(root_id, this->size());
3699 
3700  timpi_call_mpi
3701  (TIMPI_SCATTER(data_ptr, recv_buffer_size, StandardType<T>(data_ptr),
3702  recv_ptr, recv_buffer_size, StandardType<T>(recv_ptr),
3703  root_id, this->get()));
3704 }
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
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.

◆ 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.

Definition at line 3709 of file parallel_implementation.h.

References TIMPI::ignore(), TIMPI::Communicator::rank(), TIMPI::Communicator::scatter(), and TIMPI::Communicator::size().

3713 {
3714  timpi_assert_less (root_id, this->size());
3715 
3716  if (this->size() == 1)
3717  {
3718  timpi_assert (!this->rank());
3719  timpi_assert (!root_id);
3720  timpi_assert (counts.size() == this->size());
3721  recv.assign(data.begin(), data.begin() + counts[0]);
3722  return;
3723  }
3724 
3725  std::vector<DispType> displacements(this->size(), 0);
3726  if (root_id == this->rank())
3727  {
3728  timpi_assert(counts.size() == this->size());
3729 
3730  // Create a displacements vector from the incoming counts vector
3731  std::size_t globalsize = 0;
3732  for (unsigned int i=0; i < this->size(); ++i)
3733  {
3734  displacements[i] = globalsize;
3735  globalsize += counts[i];
3736  }
3737 
3738  timpi_assert(data.size() == globalsize);
3739  }
3740 
3741  TIMPI_LOG_SCOPE("scatter()", "Parallel");
3742 
3743  // Scatter the buffer sizes to size remote buffers
3744  CountType recv_buffer_size = 0;
3745  this->scatter(counts, recv_buffer_size, root_id);
3746  recv.resize(recv_buffer_size);
3747 
3748  T * data_ptr = const_cast<T*>(data.empty() ? nullptr : data.data());
3749  CountType * count_ptr = const_cast<CountType*>(counts.empty() ? nullptr : counts.data());
3750  T * recv_ptr = recv.empty() ? nullptr : recv.data();
3751  ignore(data_ptr, count_ptr, recv_ptr); // unused ifndef TIMPI_HAVE_MPI
3752 
3753  timpi_assert_less(root_id, this->size());
3754 
3755  // Scatter the non-uniform chunks
3756  timpi_call_mpi
3757  (TIMPI_SCATTERV(data_ptr, count_ptr, displacements.data(), StandardType<T>(data_ptr),
3758  recv_ptr, recv_buffer_size, StandardType<T>(recv_ptr), root_id, this->get()));
3759 }
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...
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
MPI_Count CountType
Definition: status.h:47

◆ 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

Definition at line 3768 of file parallel_implementation.h.

References TIMPI::Communicator::scatter().

3772 {
3773  std::vector<CountType> full_counts(counts.begin(), counts.end());
3774  this->scatter(data, full_counts, recv, root_id);
3775 }
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...

◆ 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.

Definition at line 3782 of file parallel_implementation.h.

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

3786 {
3787  timpi_assert_less (root_id, this->size());
3788 
3789  if (this->size() == 1)
3790  {
3791  timpi_assert (!this->rank());
3792  timpi_assert (!root_id);
3793  timpi_assert (data.size() == this->size());
3794  recv.assign(data[0].begin(), data[0].end());
3795  return;
3796  }
3797 
3798  std::vector<T,A1> stacked_data;
3799  std::vector<CountType> counts;
3800 
3801  if (root_id == this->rank())
3802  {
3803  timpi_assert (data.size() == this->size());
3804 
3805  if (!identical_buffer_sizes)
3806  counts.resize(this->size());
3807 
3808  for (std::size_t i=0; i < data.size(); ++i)
3809  {
3810  if (!identical_buffer_sizes)
3811  counts[i] = cast_int<CountType>(data[i].size());
3812 #ifndef NDEBUG
3813  else
3814  // Check that buffer sizes are indeed equal
3815  timpi_assert(!i || data[i-1].size() == data[i].size());
3816 #endif
3817  std::copy(data[i].begin(), data[i].end(), std::back_inserter(stacked_data));
3818  }
3819  }
3820 
3821  if (identical_buffer_sizes)
3822  this->scatter(stacked_data, recv, root_id);
3823  else
3824  this->scatter(stacked_data, counts, recv, root_id);
3825 }
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...
processor_id_type rank() const
Definition: communicator.h:208
processor_id_type size() const
Definition: communicator.h:211

◆ 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 2108 of file parallel_implementation.h.

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

2109 {
2110  if (this->size() > 1 && Attributes<T>::has_min_max == true)
2111  {
2112  T tempmin, tempmax;
2113  if (r)
2114  tempmin = tempmax = *r;
2115  else
2116  {
2117  Attributes<T>::set_highest(tempmin);
2118  Attributes<T>::set_lowest(tempmax);
2119  }
2120  this->min(tempmin);
2121  this->max(tempmax);
2122  bool invalid = r && ((*r != tempmin) ||
2123  (*r != tempmax));
2124  this->max(invalid);
2125  return !invalid;
2126  }
2127 
2128  static_assert(Attributes<T>::has_min_max,
2129  "Tried to semiverify an unverifiable type");
2130 
2131  return true;
2132 }
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(), 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 }
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 1393 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().

1399 {
1400  TIMPI_LOG_SCOPE("send_receive()", "Parallel");
1401 
1402  if (dest_processor_id == this->rank() &&
1403  source_processor_id == this->rank())
1404  {
1405  recv = sendvec;
1406  return;
1407  }
1408 
1409  timpi_assert_less(dest_processor_id, this->size());
1410  timpi_assert(source_processor_id < this->size() ||
1411  source_processor_id == any_source);
1412 
1413  // MPI_STATUS_IGNORE is from MPI-2; using it with some versions of
1414  // MPICH may cause a crash:
1415  // https://bugzilla.mcs.anl.gov/globus/show_bug.cgi?id=1798
1416  timpi_call_mpi
1417  (TIMPI_SENDRECV(const_cast<T1*>(&sendvec), 1, StandardType<T1>(&sendvec),
1418  dest_processor_id, send_tag.value(), &recv, 1,
1419  StandardType<T2>(&recv), source_processor_id,
1420  recv_tag.value(), this->get(), MPI_STATUS_IGNORE));
1421 }
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 1372 of file parallel_implementation.h.

References TIMPI::Communicator::send_receive_packed_range().

1378 {
1379  this->send_receive_packed_range(dest_processor_id, (void *)(nullptr),
1380  send_data.begin(), send_data.end(),
1381  source_processor_id, (void *)(nullptr),
1382  std::back_inserter(recv_data),
1383  (const T *)(nullptr),
1384  send_tag, recv_tag);
1385 }
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 1505 of file parallel_implementation.h.

1511 {
1512  send_receive_vec_of_vec
1513  (dest_processor_id, sendvec, source_processor_id, recv,
1514  send_tag, recv_tag, *this);
1515 }

◆ 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 1523 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().

1534 {
1535  TIMPI_LOG_SCOPE("send_receive()", "Parallel");
1536 
1537  timpi_assert_equal_to
1538  ((dest_processor_id == this->rank()),
1539  (source_processor_id == this->rank()));
1540 
1541  if (dest_processor_id == this->rank() &&
1542  source_processor_id == this->rank())
1543  {
1544  // We need to pack and unpack, even if we don't need to
1545  // communicate the buffer, just in case user Packing
1546  // specializations have side effects
1547 
1548  // OutputIter might not have operator= implemented; for maximum
1549  // compatibility we'll rely on its copy constructor.
1550  std::unique_ptr<OutputIter> next_out_iter =
1551  std::make_unique<OutputIter>(out_iter);
1552 
1553  typedef typename Packing<T>::buffer_type buffer_t;
1554  while (send_begin != send_end)
1555  {
1556  std::vector<buffer_t> buffer;
1557  send_begin = pack_range
1558  (context1, send_begin, send_end, buffer, approx_buffer_size);
1559  auto return_out_iter = unpack_range
1560  (buffer, context2, *next_out_iter, output_type);
1561  next_out_iter = std::make_unique<OutputIter>(return_out_iter);
1562  }
1563  return;
1564  }
1565 
1566  Request req;
1567 
1568  this->send_packed_range (dest_processor_id, context1, send_begin, send_end,
1569  req, send_tag, approx_buffer_size);
1570 
1571  this->receive_packed_range (source_processor_id, context2, out_iter,
1572  output_type, recv_tag);
1573 
1574  req.wait();
1575 }
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::alltoall(), TIMPI::Communicator::barrier(), TIMPI::Communicator::broadcast(), TIMPI::Communicator::broadcast_packed_range(), TIMPI::Communicator::gather(), TIMPI::Communicator::map_broadcast(), TIMPI::Communicator::map_max(), TIMPI::Communicator::map_sum(), TIMPI::Communicator::max(), TIMPI::Communicator::maxloc(), TIMPI::Communicator::min(), TIMPI::Communicator::minloc(), TIMPI::Communicator::nonblocking_barrier(), TIMPI::Communicator::packed_range_probe(), TIMPI::Communicator::packed_size_of(), TIMPI::Communicator::possibly_receive(), TIMPI::Communicator::possibly_receive_packed_range(), 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::scatter(), TIMPI::Communicator::semiverify(), TIMPI::Communicator::send(), TIMPI::Communicator::send_receive(), TIMPI::Communicator::sum(), 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(), 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/4]

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/4]

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.

Definition at line 2648 of file parallel_implementation.h.

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

2651 {
2652 #ifdef TIMPI_HAVE_MPI
2653  if (this->size() > 1)
2654  {
2655  TIMPI_LOG_SCOPE("sum()", "Parallel");
2656 
2657  timpi_call_mpi
2658  (TIMPI_IALLREDUCE(&r, &o, 1, StandardType<T>(&r),
2659  OpFunction<T>::sum(), this->get(),
2660  req.get()));
2661  }
2662  else
2663 #endif
2664  {
2665  o = r;
2666  req = Request::null_request;
2667  }
2668 }
static const request null_request
Definition: request.h:111
processor_id_type size() const
Definition: communicator.h:211

◆ sum() [3/4]

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

Definition at line 2672 of file parallel_implementation.h.

References TIMPI::Communicator::size().

2673 {
2674  if (this->size() > 1)
2675  {
2676  TIMPI_LOG_SCOPE("sum()", "Parallel");
2677 
2678  timpi_call_mpi
2679  (TIMPI_ALLREDUCE(MPI_IN_PLACE, &r, 1,
2680  StandardType<T>(&r),
2681  OpFunction<T>::sum(),
2682  this->get()));
2683  }
2684 }
processor_id_type size() const
Definition: communicator.h:211

◆ sum() [4/4]

template<typename T >
void TIMPI::Communicator::sum ( std::complex< T > &  timpi_mpi_varr) const
inlineinherited

Definition at line 2709 of file parallel_implementation.h.

References TIMPI::Communicator::size().

2710 {
2711  if (this->size() > 1)
2712  {
2713  TIMPI_LOG_SCOPE("sum()", "Parallel");
2714 
2715  timpi_call_mpi
2716  (TIMPI_ALLREDUCE(MPI_IN_PLACE, &r, 2,
2717  StandardType<T>(),
2718  OpFunction<T>::sum(),
2719  this->get()));
2720  }
2721 }
processor_id_type size() const
Definition: communicator.h:211

◆ 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::allgather(), TIMPI::Communicator::alltoall(), TIMPI::Communicator::broadcast(), TIMPI::Communicator::map_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 2088 of file parallel_implementation.h.

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

2089 {
2090  if (this->size() > 1 && Attributes<T>::has_min_max == true)
2091  {
2092  T tempmin = r, tempmax = r;
2093  this->min(tempmin);
2094  this->max(tempmax);
2095  bool verified = (r == tempmin) &&
2096  (r == tempmax);
2097  this->min(verified);
2098  return verified;
2099  }
2100 
2101  static_assert(Attributes<T>::has_min_max,
2102  "Tried to verify an unverifiable type");
2103 
2104  return true;
2105 }
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: