ALPSCore reference
mpi.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1998-2018 ALPS Collaboration. See COPYRIGHT.TXT
3  * All rights reserved. Use is subject to license terms. See LICENSE.TXT
4  * For use in publications, see ACKNOWLEDGE.TXT
5  */
6 #pragma once
7 
8 #include <alps/alea/core.hpp>
9 #include <alps/utilities/mpi.hpp> /* provides mpi.h */
10 
11 // TODO: merge into MPI
12 namespace alps { namespace mpi {
13 
14 struct failed_operation : std::exception { };
15 
16 inline void checked(int retcode)
17 {
18  if (retcode != MPI_SUCCESS)
19  throw failed_operation();
20 }
21 
22 inline bool is_intercomm(const communicator &comm)
23 {
24  int flag;
25  checked(MPI_Comm_test_inter(comm, &flag));
26  return flag;
27 }
28 
29 }}
30 
31 namespace alps { namespace alea {
32 
33 namespace mpi = alps::mpi;
34 
39  : public reducer
40 {
41 
42  mpi_reducer(const mpi::communicator &comm=mpi::communicator(), int root=0)
43  : comm_(comm)
44  , root_(root)
45  {
46  if (mpi::is_intercomm(comm))
47  throw std::runtime_error("Unable to use in-place communication");
48  }
49 
50  reducer_setup get_setup() const override
51  {
52  reducer_setup mpi_setup = { (size_t) comm_.rank(),
53  (size_t) comm_.size(),
54  am_root() };
55  return mpi_setup;
56  }
57 
58  long get_max(long data) const override
59  {
60  mpi::checked(MPI_Allreduce(MPI_IN_PLACE, &data, 1, MPI_LONG,
61  MPI_MAX, comm_));
62  return data;
63  }
64 
65  void reduce(view<double> data) const override { inplace_reduce(data); }
66 
67  void reduce(view<long> data) const override { inplace_reduce(data); }
68 
69  void commit() const override { }
70 
71  const mpi::communicator &comm() const { return comm_; }
72 
73  int root() const { return root_; }
74 
75  bool am_root() const { return comm_.rank() == root_; }
76 
77 protected:
78  template <typename T>
79  void inplace_reduce(view<T> data) const
80  {
81  // NO-OP in the case of empty data (strange though)
82  if (data.size() == 0)
83  return;
84 
85  // Extract data type and get on with it
86  MPI_Datatype dtype_tag = alps::mpi::get_mpi_datatype(T());
87 
88  // In-place requires special value for sendbuf, but only on root
89  const void *sendbuf = am_root() ? MPI_IN_PLACE : data.data();
90  // To maintain MPI-2.0 compatibility `const` modifier should be removed
91  mpi::checked(MPI_Reduce(const_cast<void*>(sendbuf), data.data(), data.size(), dtype_tag,
92  MPI_SUM, root_, comm_));
93  }
94 
95 private:
97  int root_;
98 };
99 
100 }}
T * data()
Definition: core.hpp:68
reducer_setup get_setup() const override
Definition: mpi.hpp:50
long get_max(long data) const override
Definition: mpi.hpp:58
void reduce(view< double > data) const override
Definition: mpi.hpp:65
void commit() const override
Definition: mpi.hpp:69
bool am_root() const
Definition: mpi.hpp:75
void reduce(view< long > data) const override
Definition: mpi.hpp:67
mpi_reducer(const mpi::communicator &comm=mpi::communicator(), int root=0)
Definition: mpi.hpp:42
Header for object-oriented interface to MPI (similar to boost::mpi)
Encapsulation of an MPI communicator and some communicator-related operations.
Definition: mpi.hpp:111
bool is_intercomm(const communicator &comm)
Definition: mpi.hpp:22
size_t size() const
Definition: core.hpp:74
int root() const
Definition: mpi.hpp:73
void inplace_reduce(view< T > data) const
Definition: mpi.hpp:79
void checked(int retcode)
Definition: mpi.hpp:16
MPI_Datatype get_mpi_datatype(const T &)
Returns MPI datatype for the value of type T
Definition: mpi.hpp:319
const mpi::communicator & comm() const
Definition: mpi.hpp:71