17 #include <deal.II/base/exceptions.h> 18 #include <deal.II/base/mpi.h> 19 #include <deal.II/base/mpi.templates.h> 20 #include <deal.II/base/multithread_info.h> 21 #include <deal.II/base/utilities.h> 23 #include <deal.II/lac/la_parallel_block_vector.h> 24 #include <deal.II/lac/la_parallel_vector.h> 25 #include <deal.II/lac/vector_memory.h> 29 #ifdef DEAL_II_WITH_TRILINOS 30 # ifdef DEAL_II_WITH_MPI 31 # include <deal.II/lac/trilinos_parallel_block_vector.h> 32 # include <deal.II/lac/trilinos_vector.h> 33 # include <deal.II/lac/vector_memory.h> 35 # include <Epetra_MpiComm.h> 39 #ifdef DEAL_II_WITH_PETSC 40 # include <deal.II/lac/petsc_block_vector.h> 41 # include <deal.II/lac/petsc_vector.h> 43 # include <petscsys.h> 46 #ifdef DEAL_II_WITH_SLEPC 47 # include <deal.II/lac/slepc_solver.h> 49 # include <slepcsys.h> 52 #ifdef DEAL_II_WITH_P4EST 53 # include <p4est_bits.h> 56 #ifdef DEAL_II_TRILINOS_WITH_ZOLTAN 57 # include <zoltan_cpp.h> 60 DEAL_II_NAMESPACE_OPEN
67 #ifdef DEAL_II_WITH_MPI 72 const int ierr = MPI_Comm_size(mpi_communicator, &n_jobs);
83 const int ierr = MPI_Comm_rank(mpi_communicator, &rank);
93 MPI_Comm new_communicator;
94 const int ierr = MPI_Comm_dup(mpi_communicator, &new_communicator);
96 return new_communicator;
103 const MPI_Group &group,
107 # if DEAL_II_MPI_VERSION_GTE(3, 0) 108 return MPI_Comm_create_group(comm, group, tag, new_comm);
111 int ierr = MPI_Comm_rank(comm, &rank);
115 ierr = MPI_Group_rank(group, &grp_rank);
117 if (grp_rank == MPI_UNDEFINED)
119 *new_comm = MPI_COMM_NULL;
124 ierr = MPI_Group_size(group, &grp_size);
127 ierr = MPI_Comm_dup(MPI_COMM_SELF, new_comm);
130 MPI_Group parent_grp;
131 ierr = MPI_Comm_group(comm, &parent_grp);
134 std::vector<int> pids(grp_size);
135 std::vector<int> grp_pids(grp_size);
136 std::iota(grp_pids.begin(), grp_pids.end(), 0);
137 ierr = MPI_Group_translate_ranks(
138 group, grp_size, grp_pids.data(), parent_grp, pids.data());
140 ierr = MPI_Group_free(&parent_grp);
143 MPI_Comm comm_old = *new_comm;
145 for (
int merge_sz = 1; merge_sz < grp_size; merge_sz *= 2)
147 const int gid = grp_rank / merge_sz;
148 comm_old = *new_comm;
151 if ((gid + 1) * merge_sz < grp_size)
153 ierr = (MPI_Intercomm_create(
154 *new_comm, 0, comm, pids[(gid + 1) * merge_sz], tag, &ic));
156 ierr = MPI_Intercomm_merge(ic, 0 , new_comm);
162 ierr = MPI_Intercomm_create(
163 *new_comm, 0, comm, pids[(gid - 1) * merge_sz], tag, &ic);
165 ierr = MPI_Intercomm_merge(ic, 1 , new_comm);
168 if (*new_comm != comm_old)
170 ierr = MPI_Comm_free(&ic);
172 ierr = MPI_Comm_free(&comm_old);
183 std::vector<unsigned int>
185 const MPI_Comm & mpi_comm,
186 const std::vector<unsigned int> &destinations)
191 for (
unsigned int i = 0; i < destinations.size(); ++i)
193 Assert(destinations[i] < n_procs,
195 Assert(destinations[i] != myid,
197 "There is no point in communicating with ourselves."));
200 # if DEAL_II_MPI_VERSION_GTE(2, 2) 202 std::vector<unsigned int> dest_vector(n_procs);
203 for (
const auto &el : destinations)
209 unsigned int n_recv_from;
210 const int ierr = MPI_Reduce_scatter_block(
211 &dest_vector[0], &n_recv_from, 1, MPI_UNSIGNED, MPI_SUM, mpi_comm);
216 std::vector<MPI_Request> send_requests(destinations.size());
217 for (
const auto &el : destinations)
224 &send_requests[&el - &destinations[0]]);
227 if (n_recv_from == 0)
228 return std::vector<unsigned int>();
233 std::vector<unsigned int> origins(n_recv_from);
234 for (
auto &el : origins)
243 MPI_Waitall(destinations.size(),
244 send_requests.data(),
245 MPI_STATUSES_IGNORE);
250 const unsigned int max_n_destinations =
253 if (max_n_destinations == 0)
255 return std::vector<unsigned int>();
260 std::vector<unsigned int> my_destinations(max_n_destinations,
262 std::copy(destinations.begin(),
264 my_destinations.begin());
270 std::vector<unsigned int> all_destinations(max_n_destinations * n_procs);
271 const int ierr = MPI_Allgather(my_destinations.data(),
274 all_destinations.data(),
282 std::vector<unsigned int> origins;
283 for (
unsigned int i = 0; i < n_procs; ++i)
284 for (
unsigned int j = 0; j < max_n_destinations; ++j)
285 if (all_destinations[i * max_n_destinations + j] == myid)
286 origins.push_back(i);
287 else if (all_destinations[i * max_n_destinations + j] ==
300 max_reduce(
const void *in_lhs_,
311 inout_rhs->
sum += in_lhs->
sum;
312 if (inout_rhs->
min > in_lhs->
min)
314 inout_rhs->
min = in_lhs->
min;
317 else if (inout_rhs->
min == in_lhs->
min)
324 if (inout_rhs->
max < in_lhs->
max)
326 inout_rhs->
max = in_lhs->
max;
329 else if (inout_rhs->
max == in_lhs->
max)
341 min_max_avg(
const double my_value,
const MPI_Comm &mpi_communicator)
348 result.
sum = my_value;
349 result.
avg = my_value;
350 result.
min = my_value;
351 result.
max = my_value;
361 std::numeric_limits<double>::max(),
362 -std::numeric_limits<double>::max(),
367 const unsigned int my_id =
368 ::Utilities::MPI::this_mpi_process(mpi_communicator);
369 const unsigned int numproc =
370 ::Utilities::MPI::n_mpi_processes(mpi_communicator);
373 int ierr = MPI_Op_create((MPI_User_function *)&max_reduce,
true, &op);
381 int lengths[] = {3, 2};
382 MPI_Aint displacements[] = {0, offsetof(
MinMaxAvg, min_index)};
383 MPI_Datatype
types[] = {MPI_DOUBLE, MPI_INT};
385 ierr = MPI_Type_struct(2, lengths, displacements, types, &type);
388 ierr = MPI_Type_commit(&type);
390 ierr = MPI_Allreduce(&in, &result, 1, type, op, mpi_communicator);
393 ierr = MPI_Type_free(&type);
396 ierr = MPI_Op_free(&op);
399 result.
avg = result.
sum / numproc;
424 return mpi_communicator;
430 min_max_avg(
const double my_value,
const MPI_Comm &)
434 result.
sum = my_value;
435 result.
avg = my_value;
436 result.
min = my_value;
437 result.
max = my_value;
450 const unsigned int max_num_threads)
452 static bool constructor_has_already_run =
false;
453 (void)constructor_has_already_run;
454 Assert(constructor_has_already_run ==
false,
455 ExcMessage(
"You can only create a single object of this class " 456 "in a program since it initializes the MPI system."));
460 #ifdef DEAL_II_WITH_MPI 463 int MPI_has_been_started = 0;
464 ierr = MPI_Initialized(&MPI_has_been_started);
467 ExcMessage(
"MPI error. You can only start MPI once!"));
474 int wanted = MPI_THREAD_SERIALIZED;
475 ierr = MPI_Init_thread(&argc, &argv, wanted, &provided);
492 #ifdef DEAL_II_WITH_PETSC 493 # ifdef DEAL_II_WITH_SLEPC 495 ierr = SlepcInitialize(&argc, &argv,
nullptr,
nullptr);
499 ierr = PetscInitialize(&argc, &argv,
nullptr,
nullptr);
505 PetscPopSignalHandler();
509 #ifdef DEAL_II_TRILINOS_WITH_ZOLTAN 511 Zoltan_Initialize(argc, argv, &version);
514 #ifdef DEAL_II_WITH_P4EST 516 # if !(DEAL_II_P4EST_VERSION_GTE(2, 0, 0, 0)) 521 sc_init(MPI_COMM_WORLD, 0, 0,
nullptr, SC_LP_SILENT);
523 p4est_init(
nullptr, SC_LP_SILENT);
526 constructor_has_already_run =
true;
540 #ifdef DEAL_II_WITH_MPI 549 const unsigned int max_hostname_size =
551 std::vector<char> hostname_array(max_hostname_size);
552 std::copy(hostname.c_str(),
553 hostname.c_str() + hostname.size() + 1,
554 hostname_array.begin());
556 std::vector<char> all_hostnames(max_hostname_size *
558 const int ierr = MPI_Allgather(hostname_array.data(),
561 all_hostnames.data(),
569 unsigned int n_local_processes = 0;
570 unsigned int nth_process_on_host = 0;
573 if (std::string(all_hostnames.data() + i * max_hostname_size) ==
578 ++nth_process_on_host;
589 const unsigned int n_threads =
591 (nth_process_on_host <=
613 #ifdef DEAL_II_WITH_MPI 619 release_unused_memory();
623 release_unused_memory();
626 # if defined(DEAL_II_WITH_TRILINOS) 637 #ifdef DEAL_II_WITH_PETSC 638 if ((PetscInitializeCalled == PETSC_TRUE) &&
639 (PetscFinalizeCalled == PETSC_FALSE))
646 # ifdef DEAL_II_WITH_SLEPC 656 #ifdef DEAL_II_WITH_P4EST 666 #ifdef DEAL_II_WITH_MPI 669 if (std::uncaught_exception())
672 <<
"ERROR: Uncaught exception in MPI_InitFinalize on proc " 674 <<
". Skipping MPI_Finalize() to avoid a deadlock." 679 const int ierr = MPI_Finalize();
692 #ifdef DEAL_II_WITH_MPI 693 int MPI_has_been_started = 0;
694 const int ierr = MPI_Initialized(&MPI_has_been_started);
697 return (MPI_has_been_started > 0);
709 DEAL_II_NAMESPACE_CLOSE
static const unsigned int invalid_unsigned_int
#define AssertNothrow(cond, exc)
static unsigned int n_cores()
MPI_InitFinalize(int &argc, char **&argv, const unsigned int max_num_threads=numbers::invalid_unsigned_int)
#define AssertThrow(cond, exc)
static::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
static::ExceptionBase & ExcMessage(std::string arg1)
#define Assert(cond, exc)
int create_group(const MPI_Comm &comm, const MPI_Group &group, const int tag, MPI_Comm *new_comm)
unsigned int n_mpi_processes(const MPI_Comm &mpi_communicator)
std::string get_hostname()
#define AssertThrowMPI(error_code)
MPI_Comm duplicate_communicator(const MPI_Comm &mpi_communicator)
static void set_thread_limit(const unsigned int max_threads=numbers::invalid_unsigned_int)
unsigned int this_mpi_process(const MPI_Comm &mpi_communicator)
static::ExceptionBase & ExcSLEPcError(int arg1)
MinMaxAvg min_max_avg(const double my_value, const MPI_Comm &mpi_communicator)
std::vector< unsigned int > compute_point_to_point_communication_pattern(const MPI_Comm &mpi_comm, const std::vector< unsigned int > &destinations)
T max(const T &t, const MPI_Comm &mpi_communicator)
static::ExceptionBase & ExcInternalError()