Interface Documentation
Version: invalid
parmetis_colorer.hh
Go to the documentation of this file.
1 /*
2  @@@@@@@@ @@ @@@@@@ @@@@@@@@ @@
3  /@@///// /@@ @@////@@ @@////// /@@
4  /@@ /@@ @@@@@ @@ // /@@ /@@
5  /@@@@@@@ /@@ @@///@@/@@ /@@@@@@@@@/@@
6  /@@//// /@@/@@@@@@@/@@ ////////@@/@@
7  /@@ /@@/@@//// //@@ @@ /@@/@@
8  /@@ @@@//@@@@@@ //@@@@@@ @@@@@@@@ /@@
9  // /// ////// ////// //////// //
10 
11  Copyright (c) 2016, Los Alamos National Security, LLC
12  All rights reserved.
13  */
14 #pragma once
15 
18 #include <flecsi-config.h>
19 
22 
23 #if !defined(FLECSI_ENABLE_PARMETIS)
24 #error FLECSI_ENABLE_PARMETIS not defined! This file depends on ParMETIS!
25 #endif
26 
27 #include <parmetis.h>
28 
29 #include <set>
30 
31 namespace flecsi {
32 namespace util {
33 namespace graph {
34 
40 struct parmetis_colorer : public colorer {
41 
46  std::set<size_t> color(const dcrs & naive) override {
47  int size;
48  int rank;
49 
50  MPI_Comm_size(MPI_COMM_WORLD, &size);
51  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
52 
53  //------------------------------------------------------------------------//
54  // Call ParMETIS partitioner.
55  //------------------------------------------------------------------------//
56 
57  idx_t wgtflag = 0;
58  idx_t numflag = 0;
59  idx_t ncon = 1;
60  std::vector<real_t> tpwgts(size);
61 
62  real_t sum = 0.0;
63  for(size_t i(0); i < tpwgts.size(); ++i) {
64  if(i == (tpwgts.size() - 1)) {
65  tpwgts[i] = 1.0 - sum;
66  }
67  else {
68  tpwgts[i] = 1.0 / size;
69  sum += tpwgts[i];
70  } // if
71 
72 #if 0
73  if(rank == 0) {
74  std::cout << tpwgts[i] << std::endl;
75  } // if
76 #endif
77  } // for
78 
79  // We may need to expose some of the ParMETIS configuration options.
80  real_t ubvec = 1.05;
81  idx_t options = 0;
82  idx_t edgecut;
83  MPI_Comm comm = MPI_COMM_WORLD;
84  std::vector<idx_t> part(naive.size(), std::numeric_limits<idx_t>::max());
85 
86 #if 0
87  const size_t output_rank(1);
88  if(rank == output_rank) {
89  std::cout << "rank " << rank << " naive: " << std::endl;
90  std::cout << "size: " << naive.size() << std::endl;
91  std::cout << naive << std::endl;
92  } // if
93 #endif
94 
95  // std::set<size_t> ret;
96  // return ret;
97 
98  // Get the dCRS information using ParMETIS types.
99  std::vector<idx_t> vtxdist = naive.distribution_as<idx_t>();
100  std::vector<idx_t> xadj = naive.offsets_as<idx_t>();
101  std::vector<idx_t> adjncy = naive.indices_as<idx_t>();
102 
103  // Actual call to ParMETIS.
104  int result = ParMETIS_V3_PartKway(&vtxdist[0],
105  &xadj[0],
106  &adjncy[0],
107  nullptr,
108  nullptr,
109  &wgtflag,
110  &numflag,
111  &ncon,
112  &size,
113  &tpwgts[0],
114  &ubvec,
115  &options,
116  &edgecut,
117  &part[0],
118  &comm);
119 
120  flog_assert(result == METIS_OK, "ParMETIS_V3_PartKway returned " << result);
121 #if 0
122  std::cout << "rank " << rank << ": ";
123  for(size_t i(0); i<naive.size(); ++i) {
124  std::cout << "[" << part[i] << ", " << vtxdist[rank]+i << "] ";
125  } // for
126  std::cout << std::endl;
127 #endif
128 
129  //------------------------------------------------------------------------//
130  // Exchange information with other ranks.
131  //------------------------------------------------------------------------//
132 
133  std::vector<idx_t> send_cnts(size, 0);
134  std::vector<std::vector<idx_t>> sbuffers;
135 
136  std::set<size_t> primary;
137 
138  // Find the indices we need to request.
139  for(int r(0); r < size; ++r) {
140  std::vector<idx_t> indices;
141 
142  for(size_t i(0); i < naive.size(); ++i) {
143  if(part[i] == r) {
144  indices.push_back(vtxdist[rank] + i);
145  }
146  else if(part[i] == rank) {
147  // If the index belongs to us, just add it...
148  primary.insert(vtxdist[rank] + i);
149  } // if
150  } // for
151 
152  sbuffers.push_back(indices);
153  send_cnts[r] = indices.size();
154  } // for
155 
156 #if 0
157  if(rank == 0) {
158  size_t rcnt(0);
159  for(auto r: sbuffers) {
160  std::cout << "rank " << rank << " sends " << rcnt++ <<
161  " " << send_cnts[rcnt] << ": ";
162  for(auto i: r) {
163  std::cout << i << " ";
164  } // for
165  std::cout << std::endl;
166  } // for
167  } // if
168 #endif
169 
170  // Do all-to-all to find out where everything belongs.
171  std::vector<idx_t> recv_cnts(size);
172  result = MPI_Alltoall(&send_cnts[0],
173  1,
175  &recv_cnts[0],
176  1,
178  MPI_COMM_WORLD);
179 
180 #if 0
181  if(rank == 0) {
182  std::cout << "rank " << rank << " receives: ";
183 
184  for(size_t i(0); i<size; ++i) {
185  std::cout << recv_cnts[i] << " ";
186  } // for
187 
188  std::cout << std::endl;
189  } // if
190 #endif
191 
192  // Start receive operations (non-blocking).
193  std::vector<std::vector<idx_t>> rbuffers(size);
194  std::vector<MPI_Request> requests;
195  for(int r(0); r < size; ++r) {
196  if(recv_cnts[r]) {
197  rbuffers[r].resize(recv_cnts[r]);
198  requests.push_back({});
199  MPI_Irecv(&rbuffers[r][0],
200  recv_cnts[r],
202  r,
203  0,
204  MPI_COMM_WORLD,
205  &requests[requests.size() - 1]);
206  } // if
207  } // for
208 
209  // Start send operations (blocking is probably ok here).
210  for(int r(0); r < size; ++r) {
211  if(send_cnts[r]) {
212  sbuffers[r].resize(send_cnts[r]);
213  MPI_Send(&sbuffers[r][0],
214  send_cnts[r],
216  r,
217  0,
218  MPI_COMM_WORLD);
219  } // if
220  } // for
221 
222  // Wait on the receive operations
223  std::vector<MPI_Status> status(requests.size());
224  MPI_Waitall(requests.size(), &requests[0], &status[0]);
225 
226  // Add indices to primary
227  for(int r(0); r < size; ++r) {
228  if(recv_cnts[r]) {
229  for(auto i : rbuffers[r]) {
230  primary.insert(i);
231  } // for
232  } // if
233  } // for
234 
235 #if 0
236  if(rank == 0) {
237  std::cout << "rank " << rank << " primary coloring:" << std::endl;
238  for(auto i: primary) {
239  std::cout << i << " ";
240  } // for
241  std::cout << std::endl;
242  } // if
243 #endif
244 
245  flog_assert(primary.size() > 0,
246  "At least one rank has an empty primary coloring. Please either "
247  "increase the problem size or use fewer ranks");
248 
249  return primary;
250  } // color
251 
256  std::vector<size_t> new_color(const dcrs & naive) override {
257  int size;
258  int rank;
259 
260  MPI_Comm_size(MPI_COMM_WORLD, &size);
261  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
262 
263  //------------------------------------------------------------------------//
264  // Call ParMETIS partitioner.
265  //------------------------------------------------------------------------//
266 
267  idx_t wgtflag = 0;
268  idx_t numflag = 0;
269  idx_t ncon = 1;
270  std::vector<real_t> tpwgts(ncon * size, 1.0 / size);
271 
272  // We may need to expose some of the ParMETIS configuration options.
273  std::vector<real_t> ubvec(ncon, 1.05);
274  idx_t options[3] = {0, 0, 0};
275  idx_t edgecut;
276  MPI_Comm comm = MPI_COMM_WORLD;
277  std::vector<idx_t> part(naive.size(), std::numeric_limits<idx_t>::max());
278 
279  // Get the dCRS information using ParMETIS types.
280  std::vector<idx_t> vtxdist = naive.distribution_as<idx_t>();
281  std::vector<idx_t> xadj = naive.offsets_as<idx_t>();
282  std::vector<idx_t> adjncy = naive.indices_as<idx_t>();
283 
284  // Actual call to ParMETIS.
285  int result = ParMETIS_V3_PartKway(&vtxdist[0],
286  &xadj[0],
287  &adjncy[0],
288  nullptr,
289  nullptr,
290  &wgtflag,
291  &numflag,
292  &ncon,
293  &size,
294  &tpwgts[0],
295  ubvec.data(),
296  options,
297  &edgecut,
298  &part[0],
299  &comm);
300 
301  flog_assert(result == METIS_OK, "ParMETIS_V3_PartKway returned " << result);
302 
303  std::vector<size_t> partitioning(part.begin(), part.end());
304 
305  return partitioning;
306 
307  } // color
308 
309 }; // struct parmetis_colorer
310 
311 } // namespace graph
312 } // namespace util
313 } // namespace flecsi
Definition: parmetis_colorer.hh:40
Definition: colorer.hh:31
#define flog_assert(test, message)
Definition: flog.hh:411
std::set< size_t > color(const dcrs &naive) override
Definition: parmetis_colorer.hh:46
Definition: crs.hh:254
std::vector< size_t > new_color(const dcrs &naive) override
Definition: parmetis_colorer.hh:256
Definition: mpi_type_traits.hh:38
Definition: control.hh:31