17 #ifndef ALPS_UTILITIES_MPI_HPP_INCLUDED_90206380262d48f0bcbe98fd16edd65d    18 #define ALPS_UTILITIES_MPI_HPP_INCLUDED_90206380262d48f0bcbe98fd16edd65d    39         template <
typename T> 
class mpi_type {};
    41 #define ALPS_MPI_DETAIL_MAKETYPE(_mpitype_, _cxxtype_)          \    43         class mpi_type<_cxxtype_> {                             \    45             typedef _cxxtype_ value_type;                       \    46             operator MPI_Datatype() { return _mpitype_; }       \    49         ALPS_MPI_DETAIL_MAKETYPE(MPI_CHAR,
char);
    50         ALPS_MPI_DETAIL_MAKETYPE(MPI_SHORT,
signed short int);
    51         ALPS_MPI_DETAIL_MAKETYPE(MPI_INT,
signed int);
    52         ALPS_MPI_DETAIL_MAKETYPE(MPI_LONG,
signed long int);
    54         ALPS_MPI_DETAIL_MAKETYPE(MPI_LONG_LONG,
signed long long int);
    55         ALPS_MPI_DETAIL_MAKETYPE(MPI_SIGNED_CHAR,
signed char);
    56         ALPS_MPI_DETAIL_MAKETYPE(MPI_UNSIGNED_CHAR,
unsigned char);
    57         ALPS_MPI_DETAIL_MAKETYPE(MPI_UNSIGNED_SHORT,
unsigned short int);
    58         ALPS_MPI_DETAIL_MAKETYPE(MPI_UNSIGNED,
unsigned int);
    59         ALPS_MPI_DETAIL_MAKETYPE(MPI_UNSIGNED_LONG,
unsigned long int);
    60         ALPS_MPI_DETAIL_MAKETYPE(MPI_UNSIGNED_LONG_LONG,
unsigned long long int);
    61         ALPS_MPI_DETAIL_MAKETYPE(MPI_FLOAT,
float);
    62         ALPS_MPI_DETAIL_MAKETYPE(MPI_DOUBLE,
double);
    63         ALPS_MPI_DETAIL_MAKETYPE(MPI_LONG_DOUBLE,
long double);
    78 #ifdef ALPS_MPI_HAS_MPI_CXX_BOOL    79        ALPS_MPI_DETAIL_MAKETYPE(MPI_CXX_BOOL,
bool);
    82 #if defined(ALPS_MPI_HAS_MPI_CXX_DOUBLE_COMPLEX) && defined(ALPS_MPI_HAS_MPI_CXX_FLOAT_COMPLEX)    83         ALPS_MPI_DETAIL_MAKETYPE(MPI_CXX_DOUBLE_COMPLEX,std::complex<double>);
    84         ALPS_MPI_DETAIL_MAKETYPE(MPI_CXX_FLOAT_COMPLEX,std::complex<float>);
    87 #undef ALPS_MPI_DETAIL_MAKETYPE   112             std::shared_ptr<MPI_Comm> comm_ptr_;
   115             struct comm_deleter {
   116                 void operator()(MPI_Comm* comm_ptr) {
   118                     MPI_Finalized(&finalized);
   119                     if (!finalized) MPI_Comm_free(comm_ptr);
   139                       throw std::logic_error(
"alps::mpi::communicator(): unsupported `kind` argument.");
   142                       comm_ptr_.reset(
new MPI_Comm(comm));
   145                       comm_ptr_.reset(
new MPI_Comm(comm), comm_deleter());
   148                       MPI_Comm* newcomm_ptr=
new MPI_Comm();
   149                       MPI_Comm_dup(comm, newcomm_ptr);
   150                       comm_ptr_.reset(newcomm_ptr, comm_deleter());
   158                 MPI_Comm_rank(*comm_ptr_,&myrank);
   165                 MPI_Comm_size(*comm_ptr_,&sz);
   171                 MPI_Barrier(*comm_ptr_);
   175             operator MPI_Comm()
 const {
   184             bool abort_on_exception_;
   190                 MPI_Abort(MPI_COMM_WORLD,rc);
   197                 MPI_Initialized(&ini);
   217             environment(
int& argc, 
char**& argv, 
bool abort_on_exception=
true)
   218                 : initialized_(false), abort_on_exception_(abort_on_exception)
   220                 if (!initialized()) {
   221                     MPI_Init(&argc, &argv);
   232                 : initialized_(false), abort_on_exception_(abort_on_exception)
   234                 if (!initialized()) {
   246                 if (!initialized_) 
return; 
   247                 if (finalized()) 
return; 
   248                 if (abort_on_exception_ && std::uncaught_exception()) {
   257         template <
typename T>
   269         template <
typename T>
   271             MPI_Bcast(vals, count, detail::mpi_type<T>(), root, comm);
   274 #ifndef ALPS_MPI_HAS_MPI_CXX_BOOL   278             MPI_Bcast(vals, count*
sizeof(
bool), MPI_CHAR, root, comm);
   283 #if !defined(ALPS_MPI_HAS_MPI_CXX_DOUBLE_COMPLEX) || !defined(ALPS_MPI_HAS_MPI_CXX_FLOAT_COMPLEX)   284         template <
typename T>
   288             MPI_Bcast(vals, count*
sizeof(std::complex<T>), MPI_CHAR, root, comm);
   293         template <
typename T>
   302             std::size_t root_sz=val.size();
   304             if (comm.
rank()==root) {
   306                 broadcast(comm, const_cast<char*>(val.data()), root_sz, root);
   310                 std::unique_ptr<char[]> buf(
new char[root_sz]);
   311                 broadcast(comm, buf.get(), root_sz, root);
   312                 val.assign(buf.get(), root_sz);
   318         template <
typename T>
   320             return detail::mpi_type<T>();
   325         template <
typename T>
   327             out_vals.resize(comm.
size());
   328             MPI_Allgather((
void*)&in_val, 1, detail::mpi_type<T>(),
   329                           &out_vals.front(), 1, detail::mpi_type<T>(),
   335         template <
typename OP, 
typename T>
   339                 throw std::logic_error(std::string(
"is_mpi_op() is not implemented, called for types OP=")
   340                                        +
typeid(OP).name() + 
" and T="+
typeid(T).name());
   346         template <
typename T>
   356         template <
typename T>
   365         template <
typename T, 
typename OP>
   367                         T* out_val, 
const OP& )
   370                 throw std::invalid_argument(
"Non-positive array size in mpi::all_reduce()");
   374                 throw std::invalid_argument(
"Implicit in-place mpi::all_reduce() is not implemented");
   376             MPI_Allreduce(const_cast<T*>(val), out_val, n, detail::mpi_type<T>(),
   381         template <
typename T, 
typename OP>
   383                         T& out_val, 
const OP& op)
   389         template <
typename T, 
typename OP>
 do not duplicate, but destroy when going out of scope 
 
int size() const 
Returns the number of processes in this communicator. 
 
void all_reduce(const alps::mpi::communicator &comm, const T *val, int n, T *out_val, const OP &)
Performs MPI_Allreduce for array of a primitive type, T[n]. 
 
static bool initialized()
Returns initialized status of MPI. 
 
duplicate and destroy when going out of scope 
 
environment(int &argc, char **&argv, bool abort_on_exception=true)
Initializes MPI environment unless it's already active. 
 
communicator(const MPI_Comm &comm, comm_create_kind kind)
Creates a communicator object from an MPI communicator. 
 
Encapsulation of an MPI communicator and some communicator-related operations. 
 
void all_gather(const communicator &comm, const T &in_val, std::vector< T > &out_vals)
performs MPI_Allgather() for primitive type T 
 
MPI environment RAII class. 
 
static bool finalized()
Returns finalized status of MPI. 
 
static void abort(int rc=0)
Call MPI_Abort() 
 
Trait for MPI reduction operations. 
 
T operator()(const T &a, const T &b) const 
 
Class-holder for reduction operations (and a functor) for type T. 
 
communicator()
Creates an MPI_COMM_WORLD communicator object. 
 
void barrier() const 
Barrier on this communicator. 
 
int rank() const 
Returns process rank in this communicator. 
 
do not destroy when going out of scope 
 
void broadcast(const communicator &comm, T *vals, std::size_t count, int root)
Broadcasts array vals of a primitive type T, length count on communicator comm with root root ...
 
MPI_Datatype get_mpi_datatype(const T &)
Returns MPI datatype for the value of type T 
 
~environment()
Finalizes MPI unless already finalized or was already initilaized when ctor was called. 
 
environment(bool abort_on_exception=true)
Initializes MPI environment unless it's already active. 
 
count_type< T >::type count(T const &arg)
 
comm_create_kind
Possible ways to make a C++ object from MPI communicator.