-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmpi_wrapper.hh
More file actions
194 lines (164 loc) · 4.67 KB
/
Copy pathmpi_wrapper.hh
File metadata and controls
194 lines (164 loc) · 4.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
#ifndef MPI_WRAPPER_HH
#define MPI_WRAPPER_HH MPI_WRAPPER_HH
#include <cmath>
#include <iostream>
#include <ostream>
#include <stdlib.h>
#include <string>
#include <vector>
#ifdef USE_MPI
#include <mpi.h>
#endif // USE_MPI
/** @brief Initialise MPI */
void mpi_init();
/** @brief Finalise MPI */
void mpi_finalize();
/** @brief Return MPI rank */
int mpi_comm_rank();
/** @brief Return total number of MPI ranks */
int mpi_comm_size();
/** @brief Return true on MPI master */
bool mpi_master();
/** @brief Parallel sum for scalar valued quantities
*
* @param x quantity to sum across all processes
*/
double mpi_allreduce_sum(const double x);
/** @brief Parallel average for scalar valued quantities
*
* @param x quantity to average across all processes
*/
double mpi_allreduce_avg(const double x);
/** @brief Parallel average for vector valued quantities
*
* @param x quantity to average across all processes
*/
std::vector<double> mpi_allreduce_avg(const std::vector<double> x);
/** @brief Parallel minimum for scalar valued quantities
*
* @param x quantity to take minimum of across all processes
*/
int mpi_allreduce_min(const int x);
/** @brief Parallel sum for scalar valued quantities
*
* @param x quantity to sum across all processes
*/
int mpi_allreduce_sum(const int x);
/** @brief Parallel sum for scalar valued quantities
*
* @param x quantity to sum across all processes
*/
unsigned int mpi_allreduce_sum(const unsigned int x);
/** @brief Parallel logical and for scalar valued quantities
*
* @param x quantity to take logical and of across all processes
*/
bool mpi_allreduce_and(const bool x);
/** @brief Broadcast double value to all processes
*
* @param x value to broadcast
* @param root processor to broadcast from
*/
void mpi_bcast(double &x, const int root = 0);
/** @brief Broadcast integer value to all processes
*
* @param x value to broadcast
* @param root processor to broadcast from
*/
void mpi_bcast(int &x, const int root = 0);
/** @brief Broadcast bool value to all processes
*
* @param x value to broadcast
* @param root processor to broadcast from
*/
void mpi_bcast(bool &x, const int root = 0);
/** @brief Broadcast string value to all processes
*
* @param x value to broadcast
* @param root processor to broadcast from
*/
void mpi_bcast(std::string &x, const int root = 0);
/** @brief Scatter values to all processes
*
* @param[in] data List to scatter
* @param[out] x Resulting values of all processes
*
* This takes the list [x[0],x[1],x[2],...,x[nproc-1]] and scatters it.
*/
void mpi_scatter(unsigned int *data, unsigned int &x);
/** @brief Call mpi_finalize and exit
*
* @param[in] exit_code Exit code
*/
void mpi_exit(const int exit_code);
/** @brief Barrier */
void mpi_barrier();
/** @brief distribute a number evenly between processors
*
* Split the number n as evenly as possible between processors, i.e.
* return n_p on processor p, such that n_0 + n_1 + ... + n_{nproc-1} = n.
*
* @param[in] n Number to distribute
*/
unsigned int distribute_n(const unsigned int n);
/* The following code implements output stream that can be used in parallel
* such that the output is only printed to std::cout/std::cerr on the
* master process.
*/
namespace mpi_parallel {
/** @class MPIMasterStream
*
* @brief Class for wrapping output stream to print on MPI master only
*
* Based on the ideas for the LoggedStream class described at
* https://stackoverflow.com/questions/772355/how-to-inherit-from-stdostream
*/
class MPIMasterStream {
public:
/** @brief Constructor
*
* @param[in] out_ Stream to wrap
*/
MPIMasterStream(std::ostream &out_) : is_dummy(true) {
mpi_init();
if (not mpi_master()) {
out = new (std::ostream)(nullptr);
out->setstate(std::ios_base::badbit);
} else {
is_dummy = false;
out = &out_;
}
}
/** @brief Destructor, free memory if it has been allocated */
~MPIMasterStream() {
if (is_dummy) {
delete (out);
}
}
template <typename T>
/** @brief Output only on MPI master
*
* @param[in] v Object to pass to << operator
*/
const MPIMasterStream &operator<<(const T &v) const {
*out << v;
return *this;
}
/** @brief Output only on MPI master
*
* @param[in] F Functor to use
*/
MPIMasterStream const &operator<<(std::ostream &(*F)(std::ostream &)) const {
F(*out);
return *this;
}
protected:
std::ostream *out; /** @brief Wrapped output stream */
bool is_dummy; /** @brief Set to true if not master process */
};
/** @brief wrapped std::cout object */
static MPIMasterStream cout(std::cout);
/** @brief wrapped std::cerr object */
static MPIMasterStream cerr(std::cerr);
} // namespace mpi_parallel
#endif // MPI_HH