OpenMPCD
MPI.cpp
1 #include <OpenMPCD/MPI.hpp>
2 
6 
7 #include <limits>
8 
9 namespace OpenMPCD
10 {
11 
13  : initializedByThisInstance(false)
14 {
15  int initialized;
16  const int ret = MPI_Initialized(&initialized);
17 
18  if(ret != MPI_SUCCESS)
19  OPENMPCD_THROW(Exception, "`MPI_Initialized`");
20 
21  if(!initialized)
22  {
23  int provided;
24  const int ret =
25  MPI_Init_thread(NULL, NULL, MPI_THREAD_FUNNELED, &provided);
26 
27  if(ret != MPI_SUCCESS)
28  OPENMPCD_THROW(Exception, "`MPI_Init_thread`");
29 
30  if(provided < MPI_THREAD_FUNNELED)
31  {
32  MPI_Finalize();
33 
35  Exception,
36  "`MPI_Init_thread` failed to provide a thread-safe "
37  "environment.");
38  }
39 
40  initializedByThisInstance = true;
41  }
42 }
43 
45 {
46  #if defined(OPENMPCD_COMPILER_GCC) && __GNUC__ >= 6
47  #pragma GCC diagnostic push
48  #pragma GCC diagnostic ignored "-Wterminate"
49  #endif
50 
51  int finalized;
52  const int ret = MPI_Finalized(&finalized);
53 
54  if(ret != MPI_SUCCESS)
55  OPENMPCD_THROW(Exception, "`MPI_Finalized`");
56 
57  if(finalized)
58  {
59  if(initializedByThisInstance)
61  Exception,
62  "`MPI_Finalized` has been called by the wrong instance.");
63  }
64  else
65  {
66  if(initializedByThisInstance)
67  {
68  const int ret = MPI_Finalize();
69  if(ret != MPI_SUCCESS)
70  OPENMPCD_THROW(Exception, "`MPI_Finalize`");
71  }
72  }
73 
74  #if defined(OPENMPCD_COMPILER_GCC) && __GNUC__ >= 6
75  #pragma GCC diagnostic push
76  #endif
77 }
78 
79 std::size_t MPI::getNumberOfProcesses() const
80 {
81  int size;
82 
83  const int ret = MPI_Comm_size(MPI_COMM_WORLD, &size);
84  if(ret != MPI_SUCCESS)
85  OPENMPCD_THROW(Exception, "`MPI_Comm_size`");
86 
87  #ifdef OPENMPCD_COMPILER_GCC
88  #pragma GCC diagnostic push
89  #pragma GCC diagnostic ignored "-Wsign-compare"
90  #endif
91  OPENMPCD_DEBUG_ASSERT(size > 0);
92  OPENMPCD_DEBUG_ASSERT(size <= std::numeric_limits<std::size_t>::max());
93  #ifdef OPENMPCD_COMPILER_GCC
94  #pragma GCC diagnostic push
95  #endif
96 
97  return static_cast<std::size_t>(size);
98 }
99 
100 std::size_t MPI::getRank() const
101 {
102  int rank;
103 
104  const int ret = MPI_Comm_rank(MPI_COMM_WORLD, &rank);
105  if(ret != MPI_SUCCESS)
106  OPENMPCD_THROW(Exception, "`MPI_Comm_rank`");
107 
108  #ifdef OPENMPCD_COMPILER_GCC
109  #pragma GCC diagnostic push
110  #pragma GCC diagnostic ignored "-Wsign-compare"
111  #endif
112  OPENMPCD_DEBUG_ASSERT(rank >= 0);
113  OPENMPCD_DEBUG_ASSERT(rank <= std::numeric_limits<std::size_t>::max());
114  #ifdef OPENMPCD_COMPILER_GCC
115  #pragma GCC diagnostic push
116  #endif
117 
118  return static_cast<std::size_t>(rank);
119 }
120 
122 {
123  if(MPI_Barrier(MPI_COMM_WORLD) != MPI_SUCCESS)
124  OPENMPCD_THROW(Exception, "`MPI_Barrier`");
125 }
126 
128  MPI_Request* const request, std::size_t* const sender) const
129 {
130  #ifdef OPENMPCD_DEBUG
131  if(request == NULL)
132  OPENMPCD_THROW(NULLPointerException, "`request`");
133 
134  if(*request == MPI_REQUEST_NULL)
136  #endif
137 
138  int completed;
139  MPI_Status status;
140  const int ret = MPI_Test(request, &completed, &status);
141  if(ret != MPI_SUCCESS)
142  OPENMPCD_THROW(Exception, "`MPI_Test`");
143 
144  if(completed && sender != NULL)
145  {
146  #ifdef OPENMPCD_COMPILER_GCC
147  #pragma GCC diagnostic push
148  #pragma GCC diagnostic ignored "-Wsign-compare"
149  #endif
150  OPENMPCD_DEBUG_ASSERT(status.MPI_SOURCE >= 0);
152  status.MPI_SOURCE <= std::numeric_limits<std::size_t>::max());
153  #ifdef OPENMPCD_COMPILER_GCC
154  #pragma GCC diagnostic push
155  #endif
156 
157  *sender = static_cast<std::size_t>(status.MPI_SOURCE);
158  }
159 
160  return completed;
161 }
162 
163 } //namespace OpenMPCD
OpenMPCD::MPI::getRank
std::size_t getRank() const
Returns the rank of the current process.
Definition: MPI.cpp:100
OpenMPCD::MPI::~MPI
~MPI()
The destructor.
Definition: MPI.cpp:44
CompilerDetection.hpp
Exceptions.hpp
OPENMPCD_THROW
#define OPENMPCD_THROW(ExceptionType, message)
Throws the given ExceptionType, passing the given message along with file and line number information...
Definition: Exceptions.hpp:22
MPI.hpp
OPENMPCD_DEBUG_ASSERT
#define OPENMPCD_DEBUG_ASSERT(assertion)
Asserts that the given expression evaluates to true, but only if OPENMPCD_DEBUG is defined.
Definition: OPENMPCD_DEBUG_ASSERT.hpp:88
OpenMPCD::MPI::MPI
MPI()
The constructor.
Definition: MPI.cpp:12
OpenMPCD::MPI::getNumberOfProcesses
std::size_t getNumberOfProcesses() const
Returns the total number of processes.
Definition: MPI.cpp:79
OPENMPCD_DEBUG_ASSERT.hpp
OpenMPCD::MPI::barrier
void barrier()
Implements the MPI_BARRIER functionality.
Definition: MPI.cpp:121
OpenMPCD::Exception
The base exception class for OpenMPCD.
Definition: Exceptions.hpp:37
OpenMPCD::MPI::test
bool test(MPI_Request *const request, std::size_t *const sender=NULL) const
Calls MPI_TEST on the given request.
Definition: MPI.cpp:127
OpenMPCD::NULLPointerException
NULL-pointer exception.
Definition: Exceptions.hpp:96
OpenMPCD::InvalidArgumentException
Invalid argument exception.
Definition: Exceptions.hpp:128