17#include "ioss_export.h"
19#include <fmt/format.h>
20#include <fmt/ostream.h>
21#include <fmt/ranges.h>
29 class PropertyManager;
39#if defined(SEACAS_HAVE_MPI)
66 bool get_environment(
const std::string &name, std::string &value,
77 bool get_environment(
const std::string &name,
int &value,
89 IOSS_NODISCARD std::string decode_filename(
const std::string &filename,
bool is_parallel)
const;
113 void memory_stats(int64_t &min, int64_t &max, int64_t &avg)
const;
117 void hwm_memory_stats(int64_t &min, int64_t &max, int64_t &avg)
const;
127 template <
typename T>
131 template <
typename T>
135 template <
typename T>
void gather(T my_value, std::vector<T> &result)
const;
136 template <
typename T>
void all_gather(T my_value, std::vector<T> &result)
const;
137 template <
typename T>
void gather(std::vector<T> &my_values, std::vector<T> &result)
const;
138 template <
typename T>
void all_gather(std::vector<T> &my_values, std::vector<T> &result)
const;
139 template <
typename T>
140 int gather(
int vals_count,
int size_per_val, std::vector<T> &my_values,
141 std::vector<T> &result)
const;
143 template <
typename T>
void broadcast(T &my_value,
int root = 0)
const;
144 template <
typename T>
void broadcast(std::vector<T> &my_value,
int root = 0)
const;
146 void progress(
const std::string &output)
const;
150 mutable int parallelSize_{-1};
151 mutable int parallelRank_{-1};
154#ifdef SEACAS_HAVE_MPI
155 IOSS_NODISCARD inline MPI_Datatype mpi_type(
double ) {
return MPI_DOUBLE; }
156 IOSS_NODISCARD inline MPI_Datatype mpi_type(
float ) {
return MPI_FLOAT; }
157 IOSS_NODISCARD inline MPI_Datatype mpi_type(
int ) {
return MPI_INT; }
158 IOSS_NODISCARD inline MPI_Datatype mpi_type(
long int ) {
return MPI_LONG_LONG_INT; }
159 IOSS_NODISCARD inline MPI_Datatype mpi_type(
long long int ) {
return MPI_LONG_LONG_INT; }
160 IOSS_NODISCARD inline MPI_Datatype mpi_type(
unsigned int ) {
return MPI_UNSIGNED; }
163 return MPI_UNSIGNED_LONG;
165 IOSS_NODISCARD inline MPI_Datatype mpi_type(
unsigned long long int )
167 return MPI_UNSIGNED_LONG_LONG;
169 IOSS_NODISCARD inline MPI_Datatype mpi_type(
char ) {
return MPI_CHAR; }
171 template <
typename T>
172 int MY_Alltoallv64(
const std::vector<T> &sendbuf,
const std::vector<int64_t> &sendcounts,
173 const std::vector<int64_t> &senddisp, std::vector<T> &recvbuf,
174 const std::vector<int64_t> &recvcounts,
const std::vector<int64_t> &recvdisp,
177 int processor_count = 0;
178 int my_processor = 0;
179 MPI_Comm_size(comm, &processor_count);
180 MPI_Comm_rank(comm, &my_processor);
184 for (
int i = 0; i < processor_count; i++) {
185 int snd_cnt =
static_cast<int>(sendcounts[i]);
186 if (
static_cast<int64_t
>(snd_cnt) != sendcounts[i]) {
187 std::ostringstream errmsg;
188 errmsg <<
"ERROR: The number of items that must be communicated via MPI calls from\n"
189 <<
" processor " << my_processor <<
" to processor " << i <<
" is "
191 <<
"\n which exceeds the storage capacity of the integers "
192 "used by MPI functions.\n";
199 for (
size_t i = 1; i < pow_2; i++) {
202 size_t exchange_proc = i ^ my_processor;
203 if (exchange_proc <
static_cast<size_t>(processor_count)) {
204 int snd_cnt =
static_cast<int>(
205 sendcounts[exchange_proc]);
206 int rcv_cnt =
static_cast<int>(recvcounts[exchange_proc]);
208 if (
static_cast<size_t>(my_processor) < exchange_proc) {
209 MPI_Send((
void *)&sendbuf[senddisp[exchange_proc]], snd_cnt, mpi_type(T(0)),
210 exchange_proc, tag, comm);
211 MPI_Recv(&recvbuf[recvdisp[exchange_proc]], rcv_cnt, mpi_type(T(0)), exchange_proc, tag,
215 MPI_Recv(&recvbuf[recvdisp[exchange_proc]], rcv_cnt, mpi_type(T(0)), exchange_proc, tag,
217 MPI_Send((
void *)&sendbuf[senddisp[exchange_proc]], snd_cnt, mpi_type(T(0)),
218 exchange_proc, tag, comm);
224 std::copy(&sendbuf[senddisp[my_processor]],
225 &sendbuf[senddisp[my_processor] + sendcounts[my_processor]],
226 &recvbuf[recvdisp[my_processor]]);
230 template <
typename T>
231 int MY_Alltoallv(
const std::vector<T> &sendbuf,
const std::vector<int64_t> &sendcnts,
232 const std::vector<int64_t> &senddisp, std::vector<T> &recvbuf,
233 const std::vector<int64_t> &recvcnts,
const std::vector<int64_t> &recvdisp,
245 int processor_count = utils.parallel_size();
247 int max_comm = sendcnts[processor_count - 1] + senddisp[processor_count - 1];
248 std::vector<int> comm_size;
250 utils.gather(max_comm, comm_size);
251 int my_rank = utils.parallel_rank();
253 fmt::print(
"Send Communication Size: {}\n", fmt::join(comm_size,
", "));
258 int processor_count = 0;
259 MPI_Comm_size(comm, &processor_count);
260 size_t max_comm = sendcnts[processor_count - 1] + senddisp[processor_count - 1];
262 if (max_comm < one << 31) {
264 std::vector<int> send_cnt(sendcnts.begin(), sendcnts.end());
265 std::vector<int> send_dis(senddisp.begin(), senddisp.end());
266 std::vector<int> recv_cnt(recvcnts.begin(), recvcnts.end());
267 std::vector<int> recv_dis(recvdisp.begin(), recvdisp.end());
268 return MPI_Alltoallv((
void *)
Data(sendbuf),
Data(send_cnt),
Data(send_dis), mpi_type(T(0)),
269 (
void *)
Data(recvbuf),
Data(recv_cnt),
Data(recv_dis), mpi_type(T(0)),
278 return MY_Alltoallv64(sendbuf, sendcnts, senddisp, recvbuf, recvcnts, recvdisp, comm);
284 template <
typename T>
285 int MY_Alltoallv(
const std::vector<T> &sendbuf,
const std::vector<int> &sendcnts,
286 const std::vector<int> &senddisp, std::vector<T> &recvbuf,
287 const std::vector<int> &recvcnts,
const std::vector<int> &recvdisp,
293 int processor_count = utils.parallel_size();
295 int max_comm = sendcnts[processor_count - 1] + senddisp[processor_count - 1];
296 std::vector<int> comm_size;
298 utils.gather(max_comm, comm_size);
299 int my_rank = utils.parallel_rank();
301 fmt::print(
"Send Communication Size: {}\n", fmt::join(comm_size,
", "));
305 return MPI_Alltoallv((
void *)
Data(sendbuf),
const_cast<int *
>(
Data(sendcnts)),
306 const_cast<int *
>(
Data(senddisp)), mpi_type(T(0)),
Data(recvbuf),
307 const_cast<int *
>(
Data(recvcnts)),
const_cast<int *
>(
Data(recvdisp)),
308 mpi_type(T(0)), comm);
312 template <
typename T>
318#ifdef SEACAS_HAVE_MPI
321 std::ostringstream errmsg;
326 std::vector<T> maxout(local_minmax.size());
327 MPI_Op oper = MPI_MAX;
339 MPI_Allreduce((
void *)(
Data(local_minmax)),
Data(maxout),
340 static_cast<int>(local_minmax.size()), mpi_type(T()), oper,
communicator_);
341 if (success != MPI_SUCCESS) {
342 std::ostringstream errmsg;
343 errmsg <<
"Ioss::ParallelUtils::global_array_minmax - MPI_Allreduce failed";
347 for (
size_t i = 0; i < local_minmax.size(); i++) {
348 local_minmax[i] = maxout[i];
#define IOSS_MAYBE_UNUSED
Definition Ioss_CodeTypes.h:54
#define IOSS_NODISCARD
Definition Ioss_CodeTypes.h:55
int Ioss_MPI_Comm
Definition Ioss_CodeTypes.h:64
#define IOSS_PAR_UNUSED(x)
Definition Ioss_CodeTypes.h:69
IOSS_NODISCARD constexpr T * Data(std::vector< T > &vec)
Definition Ioss_Utils.h:56
void IOSS_ERROR(const std::ostringstream &errmsg)
Definition Ioss_Utils.h:38
Definition Ioss_ParallelUtils.h:32
void global_array_minmax(IOSS_MAYBE_UNUSED std::vector< T > &local_minmax, IOSS_MAYBE_UNUSED MinMax which) const
Definition Ioss_ParallelUtils.h:313
int gather(int vals_count, int size_per_val, std::vector< T > &my_values, std::vector< T > &result) const
void broadcast(std::vector< T > &my_value, int root=0) const
static IOSS_NODISCARD constexpr Ioss_MPI_Comm comm_self()
Definition Ioss_ParallelUtils.h:49
IOSS_NODISCARD int parallel_size() const
Definition Ioss_ParallelUtils.C:206
static IOSS_NODISCARD constexpr Ioss_MPI_Comm comm_null()
Definition Ioss_ParallelUtils.h:50
void broadcast(T &my_value, int root=0) const
static IOSS_NODISCARD constexpr Ioss_MPI_Comm comm_world()
Definition Ioss_ParallelUtils.h:48
IOSS_NODISCARD T global_minmax(IOSS_MAYBE_UNUSED T local_minmax, IOSS_MAYBE_UNUSED MinMax which) const
MinMax
Definition Ioss_ParallelUtils.h:37
@ DO_MAX
Definition Ioss_ParallelUtils.h:37
@ DO_MIN
Definition Ioss_ParallelUtils.h:37
@ DO_SUM
Definition Ioss_ParallelUtils.h:37
Ioss_MPI_Comm communicator_
Definition Ioss_ParallelUtils.h:149
IOSS_NODISCARD Ioss_MPI_Comm communicator() const
Definition Ioss_ParallelUtils.h:91
A collection of Ioss::Property objects.
Definition Ioss_PropertyManager.h:36
static IOSS_NODISCARD bool isEnabled()
Definition Ioss_SerializeIO.h:81
static IOSS_NODISCARD int getOwner()
Definition Ioss_SerializeIO.h:69
static IOSS_NODISCARD bool inBarrier()
Definition Ioss_SerializeIO.h:83
static IOSS_NODISCARD int power_2(int count)
Definition Ioss_Utils.h:270
The main namespace for the Ioss library.
Definition Ioad_DatabaseIO.C:40
std::vector< int64_t > Int64Vector
Definition Ioss_CodeTypes.h:22
std::vector< int > IntVector
Definition Ioss_CodeTypes.h:21