IPPL (Independent Parallel Particle Layer)
IPPL
Loading...
Searching...
No Matches
Communicator.h
Go to the documentation of this file.
1//
2// Class Communicator
3// Defines a class to do MPI communication.
4//
5#ifndef IPPL_MPI_COMMUNICATOR_H
6#define IPPL_MPI_COMMUNICATOR_H
7
8#include <memory>
9#include <mpi.h>
10
13#include "Communicate/Request.h"
14#include "Communicate/Status.h"
15
17// For message size check; see below
18#include <climits>
19#include <cstdlib>
20
21#include "Utility/TypeUtils.h"
22
23#include "Communicate/Archive.h"
25#include "Communicate/Tags.h"
27
28namespace ippl {
29 namespace mpi {
30
31 class Communicator : public TagMaker {
32 public:
34
35 Communicator(MPI_Comm comm);
36
37 Communicator& operator=(MPI_Comm comm);
38
39 ~Communicator() = default;
40
41 Communicator split(int color, int key) const;
42
43 operator const MPI_Comm&() const noexcept { return *comm_m; }
44
45 int size() const noexcept { return size_m; }
46
47 int rank() const noexcept { return rank_m; }
48
49 void barrier() { MPI_Barrier(*comm_m); }
50
51 void abort(int errorcode = -1) { MPI_Abort(*comm_m, errorcode); }
52
53 /*
54 * Blocking point-to-point communication
55 *
56 */
57
58 template <typename T>
59 void send(const T& buffer, int count, int dest, int tag);
60
61 template <typename T>
62 void send(const T* buffer, int count, int dest, int tag);
63
64 template <typename T>
65 void recv(T& output, int count, int source, int tag, Status& status);
66
67 template <typename T>
68 void recv(T* output, int count, int source, int tag, Status& status);
69
70 void probe(int source, int tag, Status& status);
71
72 /*
73 * Non-blocking point-to-point communication
74 *
75 */
76
77 template <typename T>
78 void isend(const T& buffer, int count, int dest, int tag, Request& request);
79
80 template <typename T>
81 void isend(const T* buffer, int count, int dest, int tag, Request& request);
82
83 template <typename T>
84 void irecv(T& buffer, int count, int source, int tag, Request& request);
85
86 template <typename T>
87 void irecv(T* buffer, int count, int source, int tag, Request& request);
88
89 bool iprobe(int source, int tag, Status& status);
90
91 /*
92 * Collective communication
93 */
94
95 /* Gather the data in the given source container from all other nodes to a
96 * specific node (default: 0).
97 */
98 template <typename T>
99 void gather(const T* input, T* output, int count, int root = 0);
100
101 /* Scatter the data from all other nodes to a
102 * specific node (default: 0).
103 */
104 template <typename T>
105 void scatter(const T* input, T* output, int count, int root = 0);
106
107 /* Reduce data coming from all nodes to a specific node
108 * (default: 0). Apply certain operation
109 *
110 */
111 template <typename T, class Op>
112 void reduce(const T* input, T* output, int count, Op op, int root = 0);
113
114 template <typename T, class Op>
115 void reduce(const T& input, T& output, int count, Op op, int root = 0);
116
117 template <typename T, class Op>
118 void allreduce(const T* input, T* output, int count, Op op);
119
120 template <typename T, class Op>
121 void allreduce(const T& input, T& output, int count, Op op);
122
123 template <typename T, class Op>
124 void allreduce(T* inout, int count, Op op);
125
126 template <typename T, class Op>
127 void allreduce(T& inout, int count, Op op);
128
130 template <typename MemorySpace = Kokkos::DefaultExecutionSpace::memory_space>
132
133 template <typename MemorySpace = Kokkos::DefaultExecutionSpace::memory_space>
134 using buffer_type = std::shared_ptr<archive_type<MemorySpace>>;
135
136 private:
137 template <typename MemorySpace>
139
142
143 public:
146 void setDefaultOverallocation(double factor);
147
148 template <typename MemorySpace = Kokkos::DefaultExecutionSpace::memory_space,
149 typename T = char>
150 buffer_type<MemorySpace> getBuffer(size_type size, double overallocation = 1.0);
151
152 void deleteAllBuffers();
153 void freeAllBuffers();
154
155 template <typename MemorySpace = Kokkos::DefaultExecutionSpace::memory_space>
157
158 const MPI_Comm& getCommunicator() const noexcept { return *comm_m; }
159
160 template <class Buffer, typename Archive>
161 void recv(int src, int tag, Buffer& buffer, Archive& ar, size_type msize,
162 size_type nrecvs) {
163 // Temporary fix. MPI communication seems to have problems when the
164 // count argument exceeds the range of int, so large messages should
165 // be split into smaller messages
166 if (msize > INT_MAX) {
167 std::cerr << "Message size exceeds range of int" << std::endl;
168 this->abort();
169 }
170 MPI_Status status;
171 MPI_Recv(ar.getBuffer(), msize, MPI_BYTE, src, tag, *comm_m, &status);
172
173 buffer.deserialize(ar, nrecvs);
174 }
175
176 template <class Buffer, typename Archive>
177 void isend(int dest, int tag, Buffer& buffer, Archive& ar, MPI_Request& request,
178 size_type nsends) {
179 if (ar.getSize() > INT_MAX) {
180 std::cerr << "Message size exceeds range of int" << std::endl;
181 this->abort();
182 }
183 buffer.serialize(ar, nsends);
184 MPI_Isend(ar.getBuffer(), ar.getSize(), MPI_BYTE, dest, tag, *comm_m, &request);
185 }
186
187 template <typename Archive>
188 void irecv(int src, int tag, Archive& ar, MPI_Request& request, size_type msize) {
189 if (msize > INT_MAX) {
190 std::cerr << "Message size exceeds range of int" << std::endl;
191 this->abort();
192 }
193 MPI_Irecv(ar.getBuffer(), msize, MPI_BYTE, src, tag, *comm_m, &request);
194 }
195
196 void printLogs(const std::string& filename);
197
198 private:
199 std::vector<LogEntry> gatherLocalLogs();
200 void sendLogsToRank0(const std::vector<LogEntry>& localLogs);
201 std::vector<LogEntry> gatherLogsFromAllRanks(const std::vector<LogEntry>& localLogs);
202 void writeLogsToFile(const std::vector<LogEntry>& allLogs, const std::string& filename);
203
205
206 double defaultOveralloc_m = 1.0;
207
209
210 protected:
211 std::shared_ptr<MPI_Comm> comm_m;
214 };
215 } // namespace mpi
216} // namespace ippl
217
220
222
224
226
227#endif
ippl::detail::size_type size_type
Definition datatypes.h:23
Definition Archive.h:20
std::size_t size_type
Definition IpplTypes.h:13
void writeLogsToFile(const std::vector< LogEntry > &allLogs, const std::string &filename)
void scatter(const T *input, T *output, int count, int root=0)
void send(const T &buffer, int count, int dest, int tag)
const MPI_Comm & getCommunicator() const noexcept
void isend(int dest, int tag, Buffer &buffer, Archive &ar, MPI_Request &request, size_type nsends)
typename detail::ContainerForAllSpaces< buffer_container_type >::type buffer_handler_type
void irecv(T &buffer, int count, int source, int tag, Request &request)
void abort(int errorcode=-1)
Communicator & operator=(MPI_Comm comm)
void printLogs(const std::string &filename)
void freeBuffer(buffer_type< MemorySpace > buffer)
Definition Buffers.hpp:36
void setDefaultOverallocation(double factor)
Definition Buffers.cpp:30
Communicator split(int color, int key) const
int rank() const noexcept
void reduce(const T *input, T *output, int count, Op op, int root=0)
void recv(T &output, int count, int source, int tag, Status &status)
std::shared_ptr< MPI_Comm > comm_m
std::shared_ptr< archive_type< MemorySpace > > buffer_type
int size() const noexcept
buffer_type< MemorySpace > getBuffer(size_type size, double overallocation=1.0)
Definition Buffers.hpp:27
detail::size_type size_type
bool iprobe(int source, int tag, Status &status)
std::vector< LogEntry > gatherLocalLogs()
buffer_handler_type buffer_handlers_m
void isend(const T &buffer, int count, int dest, int tag, Request &request)
void allreduce(const T *input, T *output, int count, Op op)
std::vector< LogEntry > gatherLogsFromAllRanks(const std::vector< LogEntry > &localLogs)
void probe(int source, int tag, Status &status)
LoggingBufferHandler< MemorySpace > buffer_container_type
void gather(const T *input, T *output, int count, int root=0)
double getDefaultOverallocation() const
void recv(int src, int tag, Buffer &buffer, Archive &ar, size_type msize, size_type nrecvs)
void sendLogsToRank0(const std::vector< LogEntry > &localLogs)
void irecv(int src, int tag, Archive &ar, MPI_Request &request, size_type msize)
detail::Archive< MemorySpace > archive_type
Decorator class for buffer management that adds logging capabilities to buffer operations.
TagMaker(void)
Definition TagMaker.h:27
typename TypeForAllSpaces< container_type >::memory_spaces_type type
Definition TypeUtils.h:412