33 #ifndef IOSS_Ioss_ParallelUtils_h
34 #define IOSS_Ioss_ParallelUtils_h
43 #ifdef SEACAS_HAVE_MPI
66 bool get_environment(
const std::string &
name, std::string &value,
bool sync_parallel)
const;
94 std::string
decode_filename(
const std::string &filename,
bool is_parallel)
const;
118 void memory_stats(int64_t &min, int64_t &max, int64_t &avg)
const;
134 template <
typename T>
137 template <
typename T>
void gather(T my_value, std::vector<T> &result)
const;
138 template <
typename T>
void all_gather(T my_value, std::vector<T> &result)
const;
139 template <
typename T>
void gather(std::vector<T> &my_values, std::vector<T> &result)
const;
140 template <
typename T>
void all_gather(std::vector<T> &my_values, std::vector<T> &result)
const;
141 template <
typename T>
142 int gather(
int vals_count,
int size_per_val, std::vector<T> &my_values,
143 std::vector<T> &result)
const;
145 void progress(
const std::string &output)
const;
151 #ifdef SEACAS_HAVE_MPI
152 inline MPI_Datatype mpi_type(
double ) {
return MPI_DOUBLE; }
153 inline MPI_Datatype mpi_type(
float ) {
return MPI_FLOAT; }
154 inline MPI_Datatype mpi_type(
int ) {
return MPI_INT; }
155 inline MPI_Datatype mpi_type(
char ) {
return MPI_CHAR; }
156 inline MPI_Datatype mpi_type(
long int ) {
return MPI_LONG_LONG_INT; }
157 inline MPI_Datatype mpi_type(
long long int ) {
return MPI_LONG_LONG_INT; }
158 inline MPI_Datatype mpi_type(
unsigned int ) {
return MPI_UNSIGNED; }
159 inline MPI_Datatype mpi_type(
unsigned long int ) {
return MPI_UNSIGNED_LONG; }
161 template <
typename T>
162 int MY_Alltoallv64(
const std::vector<T> &sendbuf,
const std::vector<int64_t> &sendcounts,
163 const std::vector<int64_t> &senddisp, std::vector<T> &recvbuf,
164 const std::vector<int64_t> &recvcounts,
const std::vector<int64_t> &recvdisp,
167 int processor_count = 0;
168 int my_processor = 0;
169 MPI_Comm_size(comm, &processor_count);
170 MPI_Comm_rank(comm, &my_processor);
174 for (
int i = 0; i < processor_count; i++) {
175 int snd_cnt = static_cast<int>(sendcounts[i]);
176 if (static_cast<int64_t>(snd_cnt) != sendcounts[i]) {
177 std::ostringstream errmsg;
178 errmsg <<
"ERROR: The number of items that must be communicated via MPI calls from\n"
179 <<
" processor " << my_processor <<
" to processor " << i <<
" is "
181 <<
"\n which exceeds the storage capacity of the integers "
182 "used by MPI functions.\n";
183 std::cerr << errmsg.str();
190 for (
size_t i = 1; i < pow_2; i++) {
194 size_t exchange_proc = i ^ my_processor;
195 if (exchange_proc < static_cast<size_t>(processor_count)) {
196 int snd_cnt = static_cast<int>(
197 sendcounts[exchange_proc]);
198 int rcv_cnt = static_cast<int>(recvcounts[exchange_proc]);
199 if (static_cast<size_t>(my_processor) < exchange_proc) {
200 MPI_Send((
void *)&sendbuf[senddisp[exchange_proc]], snd_cnt, mpi_type(T(0)),
201 exchange_proc, tag, comm);
202 MPI_Recv(&recvbuf[recvdisp[exchange_proc]], rcv_cnt, mpi_type(T(0)), exchange_proc, tag,
206 MPI_Recv(&recvbuf[recvdisp[exchange_proc]], rcv_cnt, mpi_type(T(0)), exchange_proc, tag,
208 MPI_Send((
void *)&sendbuf[senddisp[exchange_proc]], snd_cnt, mpi_type(T(0)),
209 exchange_proc, tag, comm);
215 std::copy(&sendbuf[senddisp[my_processor]],
216 &sendbuf[senddisp[my_processor] + sendcounts[my_processor]],
217 &recvbuf[recvdisp[my_processor]]);
221 template <
typename T>
222 int MY_Alltoallv(
const std::vector<T> &sendbuf,
const std::vector<int64_t> &sendcnts,
223 const std::vector<int64_t> &senddisp, std::vector<T> &recvbuf,
224 const std::vector<int64_t> &recvcnts,
const std::vector<int64_t> &recvdisp,
234 int processor_count = 0;
235 MPI_Comm_size(comm, &processor_count);
236 size_t max_comm = sendcnts[processor_count - 1] + senddisp[processor_count - 1];
238 if (max_comm < one << 31) {
240 std::vector<int> send_cnt(sendcnts.begin(), sendcnts.end());
241 std::vector<int> send_dis(senddisp.begin(), senddisp.end());
242 std::vector<int> recv_cnt(recvcnts.begin(), recvcnts.end());
243 std::vector<int> recv_dis(recvdisp.begin(), recvdisp.end());
244 return MPI_Alltoallv((
void *)sendbuf.data(), send_cnt.data(), send_dis.data(), mpi_type(T(0)),
245 (
void *)recvbuf.data(), recv_cnt.data(), recv_dis.data(), mpi_type(T(0)),
254 return MY_Alltoallv64(sendbuf, sendcnts, senddisp, recvbuf, recvcnts, recvdisp, comm);
260 template <
typename T>
261 int MY_Alltoallv(
const std::vector<T> &sendbuf,
const std::vector<int> &sendcnts,
262 const std::vector<int> &senddisp, std::vector<T> &recvbuf,
263 const std::vector<int> &recvcnts,
const std::vector<int> &recvdisp,
266 return MPI_Alltoallv((
void *)sendbuf.data(), const_cast<int *>(sendcnts.data()),
267 const_cast<int *>(senddisp.data()), mpi_type(T(0)), recvbuf.data(),
268 const_cast<int *>(recvcnts.data()), const_cast<int *>(recvdisp.data()),
269 mpi_type(T(0)), comm);
273 template <
typename T>
278 #ifdef SEACAS_HAVE_MPI
281 std::ostringstream errmsg;
286 std::vector<T> maxout(local_minmax.size());
287 MPI_Op oper = MPI_MAX;
299 MPI_Allreduce((
void *)(local_minmax.data()), maxout.data(),
300 static_cast<int>(local_minmax.size()), mpi_type(T()), oper,
communicator_);
301 if (success != MPI_SUCCESS) {
302 std::ostringstream errmsg;
303 errmsg <<
"Ioss::ParallelUtils::global_array_minmax - MPI_Allreduce failed";
307 for (
size_t i = 0; i < local_minmax.size(); i++) {
308 local_minmax[i] = maxout[i];