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.