mpi_partition_init.cpp
Go to the documentation of this file.
1 // Copyright 2019, University of Maryland and the MANGO development team.
2 //
3 // This file is part of MANGO.
4 //
5 // MANGO is free software: you can redistribute it and/or modify it
6 // under the terms of the GNU Lesser General Public License as
7 // published by the Free Software Foundation, either version 3 of the
8 // License, or (at your option) any later version.
9 //
10 // MANGO is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with MANGO. If not, see
17 // <https://www.gnu.org/licenses/>.
18 
19 #include<iostream>
20 #include<mpi.h>
21 #include<stdexcept>
22 #include "mango.hpp"
23 
24 void mango::MPI_Partition::init(MPI_Comm mpi_comm_world_in) {
25  int ierr;
26 
27  ierr = MPI_Comm_dup(mpi_comm_world_in, &comm_world);
28  if (ierr != 0) throw std::runtime_error("Error 1 in mango::MPI_Partition::init.");
29 
30  ierr = MPI_Comm_size(comm_world, &N_procs_world);
31  ierr = MPI_Comm_rank(comm_world, &rank_world);
32  proc0_world = (rank_world == 0);
33 
34  // if (proc0_world) std::cout << "Number of worker groups, before validation: " << N_worker_groups << std::endl;
35 
36  // Make sure all procs agree on certain variables that will be used here.
37  MPI_Bcast(&N_worker_groups, 1, MPI_INT, 0, comm_world);
38 
39  // Ensure N_worker_groups is within the range [1, N_procs_world]
40  if (N_worker_groups > N_procs_world) N_worker_groups = N_procs_world;
41  // Negative or 0 value for N_worker_groups on input means treat each proc as a worker group
42  if (N_worker_groups < 1) N_worker_groups = N_procs_world;
43 
44  // if (proc0_world) std::cout << "Number of worker groups, after validation: " << N_worker_groups << std::endl;
45 
46  worker_group = (rank_world * N_worker_groups) / N_procs_world; // Note integer division, so there is an implied floor()
47 
48  // color = worker_group, key = rank_world
49 
50  ierr = MPI_Comm_split(comm_world, worker_group, rank_world, &comm_worker_groups);
51  if (ierr != 0) throw std::runtime_error("Error 2 in mango::MPI_Partition::init.");
52  MPI_Comm_rank(comm_worker_groups, &rank_worker_groups);
53  MPI_Comm_size(comm_worker_groups, &N_procs_worker_groups);
54  proc0_worker_groups = (rank_worker_groups == 0);
55 
56  // Now set up the group_leaders communicator
57  int color;
58  if (proc0_worker_groups) {
59  color = 0;
60  } else {
61  color = MPI_UNDEFINED;
62  }
63  ierr = MPI_Comm_split(comm_world, color, rank_world, &comm_group_leaders);
64  if (ierr != 0) throw std::runtime_error("Error 3 in mango::MPI_Partition::init.");
65 
66  if (proc0_worker_groups) {
67  MPI_Comm_rank(comm_group_leaders, &rank_group_leaders);
68  MPI_Comm_size(comm_group_leaders, &N_procs_group_leaders);
69  } else {
70  // We are not allowed to query the rank from procs that are not members of comm_group_leaders.
71  rank_group_leaders = -1;
72  N_procs_group_leaders = -1;
73  }
74 
75  print();
76  initialized = true;
77 }
78 
mango.hpp
mango::MPI_Partition::init
void init(MPI_Comm comm_world)
Divide up a given "world" communicator into worker groups.
Definition: mpi_partition_init.cpp:24