Zoltan2
Zoltan2_TpetraCrsColorer_Zoltan.hpp
Go to the documentation of this file.
1 #pragma once
2 
4 
5 #include "Teuchos_Array.hpp"
6 #include "Teuchos_ArrayView.hpp"
7 #include "Teuchos_TestForException.hpp"
8 #include "Teuchos_DefaultMpiComm.hpp"
9 
10 #include "zoltan_cpp.h"
11 
12 namespace Zoltan2
13 {
14 
15 // Implementation of CrsColorer<> using Zoltan partial distance-2 coloring.
16 // This is distributed-parallel, but not shared.
17 template <typename CrsMatrixType>
19 {
20 public:
21 
22  typedef CrsMatrixType matrix_t;
23  typedef typename matrix_t::crs_graph_type graph_t;
24  typedef typename matrix_t::scalar_type scalar_t;
25  typedef typename matrix_t::local_ordinal_type lno_t;
26  typedef typename matrix_t::global_ordinal_type gno_t;
27  typedef typename matrix_t::node_type node_t;
28  typedef typename node_t::device_type device_t;
29  typedef typename device_t::execution_space execution_space;
30  typedef Kokkos::View<int *, device_t> list_of_colors_t;
31  typedef typename list_of_colors_t::HostMirror list_of_colors_host_t;
32 
33  // Constructor
34  ZoltanCrsColorer(const Teuchos::RCP<matrix_t> &matrix_)
35  : matrix(matrix_), graph(matrix_->getCrsGraph()), transpose_graph()
36  {}
37 
38  // Destructor
40 
41  // Compute coloring data
42  void
44  Teuchos::ParameterList &coloring_params,
45  int &num_colors,
46  list_of_colors_host_t &list_of_colors_host,
47  list_of_colors_t &list_of_colors) const;
48 
49 private:
50 
51  const Teuchos::RCP<const matrix_t> matrix;
52  const Teuchos::RCP<const graph_t> graph;
53  Teuchos::RCP<const graph_t> transpose_graph;
54 
55  //
56  // Call-back functions for Zoltan interface
57  //
58 
59  // Data for call-back functions
60  struct ZoltanData
61  {
62  Teuchos::RCP<const graph_t> graph, trans_graph;
63  Teuchos::Array<int> col_procs, trans_col_procs;
64 
65  // Set matrix graphs (trans_graph_ may be null for symmetric/symmetrized
66  // problems). Computes the remote processor ID's for each entry in the
67  // graph's/trans_graph's column maps (involves communication, and so can't
68  // be done inside the Zoltan call-back functions).
69  void
70  setGraphs(
71  const Teuchos::RCP<const graph_t> &graph_,
72  const Teuchos::RCP<const graph_t> &trans_graph_ = Teuchos::null)
73  {
74  graph = graph_;
75  trans_graph = trans_graph_;
76  col_procs.resize(graph->getColMap()->getNodeNumElements());
77  auto gids = graph->getColMap()->getNodeElementList();
78 
79  Tpetra::LookupStatus ret =
80  graph->getRowMap()->getRemoteIndexList(gids, col_procs());
81  TEUCHOS_TEST_FOR_EXCEPTION(ret != Tpetra::AllIDsPresent, std::logic_error,
82  "Zoltan2::CrsColorer: getRemoteIndexList() "
83  "failed!");
84 
85  if (trans_graph != Teuchos::null)
86  {
87  trans_col_procs.resize(trans_graph->getColMap()->getNodeNumElements());
88  gids = trans_graph->getColMap()->getNodeElementList();
89  ret = trans_graph->getRowMap()->getRemoteIndexList(gids,
90  trans_col_procs());
91  TEUCHOS_TEST_FOR_EXCEPTION(ret != Tpetra::AllIDsPresent,
92  std::logic_error,
93  "Zoltan2::CrsColorer getRemoteIndexList() "
94  "failed!");
95  }
96  }
97  };
98 
99  // Number of vertices
100  static int
101  get_number_of_vertices(void *data, int *ierr);
102 
103  // Vertex IDs on this processor
104  static void
105  get_vertex_list(
106  void *data,
107  int sizeGID,
108  int sizeLID,
109  ZOLTAN_ID_PTR global_ids,
110  ZOLTAN_ID_PTR local_ids,
111  int wgt_dim,
112  float *obj_wgts,
113  int *ierr);
114 
115  // Get number of edges on this processor
116  static int
117  get_number_of_edges(
118  void *data,
119  int sizeGID,
120  int sizeLID,
121  ZOLTAN_ID_PTR global_id,
122  ZOLTAN_ID_PTR local_id,
123  int *ierr);
124 
125  // Get edge ids on this processor
126  static void
127  get_edge_list(
128  void *data,
129  int sizeGID,
130  int sizeLID,
131  ZOLTAN_ID_PTR global_id,
132  ZOLTAN_ID_PTR local_id,
133  ZOLTAN_ID_PTR nbor_global_ids,
134  int *nbor_procs,
135  int wgt_dim,
136  float *ewgts,
137  int *ierr);
138 
139  //
140  // Call-back functions for Zoltan interface with symmetric graph
141  //
142 
143  // Number of vertices
144  static int
145  sym_get_number_of_vertices(void *data, int *ierr);
146 
147  // Vertex IDs on this processor
148  static void
149  sym_get_vertex_list(
150  void *data,
151  int sizeGID,
152  int sizeLID,
153  ZOLTAN_ID_PTR global_ids,
154  ZOLTAN_ID_PTR local_ids,
155  int wgt_dim,
156  float *obj_wgts,
157  int *ierr);
158 
159  // Get number of edges on this processor
160  static int
161  sym_get_number_of_edges(
162  void *data,
163  int sizeGID,
164  int sizeLID,
165  ZOLTAN_ID_PTR global_id,
166  ZOLTAN_ID_PTR local_id,
167  int *ierr);
168 
169  // Get edge ids on this processor
170  static void
171  sym_get_edge_list(
172  void *data,
173  int sizeGID,
174  int sizeLID,
175  ZOLTAN_ID_PTR global_id,
176  ZOLTAN_ID_PTR local_id,
177  ZOLTAN_ID_PTR nbor_global_ids,
178  int *nbor_procs,
179  int wgt_dim,
180  float *ewgts,
181  int *ierr);
182 };
183 
185 template <typename CrsMatrixType>
186 void
188  Teuchos::ParameterList &coloring_params,
189  int &num_colors,
190  list_of_colors_host_t &list_of_colors_host,
191  list_of_colors_t &list_of_colors
192 ) const
193 {
194  // User can tell us that the matrix is symmetric;
195  // otherwise, guess based on the matrix type
196  const std::string matrixType = coloring_params.get("matrixType", "Jacobian");
197  const bool symmetric = coloring_params.get("symmetric",
198  (matrixType == "Jacobian" ? false
199  : true));
200 
201  // User request to use Zoltan's TRANSPOSE symmetrization, if needed
202  const bool symmetrize = coloring_params.get<bool>("symmetrize", false);
203 
204  // Get MPI communicator, and throw an exception if our comm isn't MPI
205  Teuchos::RCP<const Teuchos::Comm<int>> comm =
206  this->graph->getRowMap()->getComm();
207 #ifdef HAVE_ZOLTAN2_MPI
208  Teuchos::RCP<const Teuchos::MpiComm<int>> tmpicomm =
209  Teuchos::rcp_dynamic_cast<const Teuchos::MpiComm<int>>(comm, true);
210  MPI_Comm mpicomm = *tmpicomm->getRawMpiComm();
211 #else
212  // Zoltan's siMPI will be used here
213  {
214  int flag;
215  MPI_Initialized(&flag);
216  if (!flag) {
217  int narg = 0;
218  char **argv = NULL;
219  MPI_Init(&narg, &argv);
220  }
221  }
222  MPI_Comm mpicomm = MPI_COMM_WORLD; // Will get MPI_COMM_WORLD from siMPI
223 #endif
224 
225  // Create Zoltan for coloring
226  Zoltan *zz = new Zoltan(mpicomm);
227  if (symmetric || symmetrize) {
228  zz->Set_Param("COLORING_PROBLEM", "DISTANCE-2");
229  }
230  else {
231  zz->Set_Param("COLORING_PROBLEM", "PARTIAL-DISTANCE-2");
232  }
233 
234  if (!symmetric && symmetrize)
235  zz->Set_Param("GRAPH_SYMMETRIZE", "TRANSPOSE");
236 
237  zz->Set_Param("DEBUG_LEVEL", "0");
238 
239  // Set Zoltan params
240  Teuchos::ParameterList &zoltan_params = coloring_params.sublist("Zoltan");
241  for (auto p : zoltan_params)
242  zz->Set_Param(p.first, Teuchos::getValue<std::string>(p.second));
243 
244  // Compute transpose graph
245  Teuchos::RCP<const graph_t> transpose_graph;
246  if (!symmetric && !symmetrize)
247  {
248  transpose_graph = Impl::compute_transpose_graph(*(this->matrix));
249  }
250 
251  // Setup interface functions
252  ZoltanData zd;
253  if (symmetric || symmetrize)
254  {
255  zd.setGraphs(this->graph);
256  zz->Set_Num_Obj_Fn(sym_get_number_of_vertices, &zd);
257  zz->Set_Obj_List_Fn(sym_get_vertex_list, &zd);
258  zz->Set_Num_Edges_Fn(sym_get_number_of_edges, &zd);
259  zz->Set_Edge_List_Fn(sym_get_edge_list, &zd);
260  }
261  else
262  {
263  zd.setGraphs(this->graph, transpose_graph);
264  zz->Set_Num_Obj_Fn(get_number_of_vertices, &zd);
265  zz->Set_Obj_List_Fn(get_vertex_list, &zd);
266  zz->Set_Num_Edges_Fn(get_number_of_edges, &zd);
267  zz->Set_Edge_List_Fn(get_edge_list, &zd);
268  }
269 
270  // Do coloring of columns with Zoltan -- we can request colors for
271  // columns we don't own
272  const size_t num_local_cols = this->graph->getNodeNumCols();
273  const size_t num_global_rows = this->graph->getGlobalNumRows();
274 
275  Teuchos::Array<ZOLTAN_ID_TYPE> col_gids(num_local_cols);
276  auto gids = this->graph->getColMap()->getNodeElementList();
277 
278  if (symmetric || symmetrize)
279  for (size_t i = 0; i < num_local_cols; ++i)
280  col_gids[i] = gids[i];
281  else
282  for (size_t i = 0; i < num_local_cols; ++i)
283  col_gids[i] = gids[i] + num_global_rows;
284 
285  list_of_colors_t my_list_of_colors("ZoltanCrsColorer::list_of_colors",
286  num_local_cols);
287  list_of_colors_host = Kokkos::create_mirror_view(my_list_of_colors);
288 
289  int num_gid_entries = 1;
290  int ret = zz->Color(num_gid_entries, num_local_cols, col_gids.getRawPtr(),
291  list_of_colors_host.data());
292 
293  TEUCHOS_TEST_FOR_EXCEPTION(ret != ZOLTAN_OK, std::logic_error,
294  "Zoltan::Color returned " << ret << std::endl);
295 
296  Kokkos::deep_copy(my_list_of_colors, list_of_colors_host);
297  list_of_colors = my_list_of_colors;
298 
299  const bool dump_zoltan = coloring_params.get("Dump Zoltan Data", false);
300  if (dump_zoltan)
301  {
302  std::string zoltan_dump_file =
303  coloring_params.get("Zoltan Dump File Name", "zoltan_graph.txt");
304  zz->Generate_Files(zoltan_dump_file, 0, 0, 1, 0);
305  }
306 
307  delete zz;
308 
309  // Compute global number of colors
310  int local_num_colors = 0;
311  Kokkos::parallel_reduce("ZoltanCrsColorer::find_num_colors",
312  Kokkos::RangePolicy<execution_space>(0, num_local_cols),
313  KOKKOS_LAMBDA(const size_t i, int &lcl_max) {
314  if (my_list_of_colors[i] > lcl_max)
315  lcl_max = my_list_of_colors[i];
316  },
317  Kokkos::Max<int>(local_num_colors));
318 
319  Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, 1, &local_num_colors,
320  &num_colors);
321 }
322 
324 template <typename CrsMatrixType>
325 int
327 {
328  ZoltanData *zoltan_data = static_cast<ZoltanData *>(data);
329  *ierr = ZOLTAN_OK;
330  return zoltan_data->graph->getNodeNumRows() +
331  zoltan_data->trans_graph->getNodeNumRows();
332 }
333 
335 template <typename CrsMatrixType>
336 void
337 ZoltanCrsColorer<CrsMatrixType>::get_vertex_list(
338  void *data,
339  int sizeGID,
340  int sizeLID,
341  ZOLTAN_ID_PTR global_ids,
342  ZOLTAN_ID_PTR local_ids,
343  int wgt_dim,
344  float *obj_wgts,
345  int *ierr)
346 {
347  assert(sizeGID == 1 && sizeLID == 1);
348 
349  ZoltanData *zoltan_data = static_cast<ZoltanData *>(data);
350  *ierr = ZOLTAN_OK;
351 
352  const size_t num_local_rows = zoltan_data->graph->getNodeNumRows();
353  const size_t num_local_cols = zoltan_data->trans_graph->getNodeNumRows();
354  const size_t num_global_rows = zoltan_data->graph->getGlobalNumRows();
355  auto row_gids = zoltan_data->graph->getRowMap()->getNodeElementList();
356  auto col_gids = zoltan_data->trans_graph->getRowMap()->getNodeElementList();
357 
358  for (size_t i = 0; i < num_local_rows; ++i)
359  {
360  local_ids[i] = i;
361  global_ids[i] = row_gids[i];
362  }
363  for (size_t i = 0; i < num_local_cols; ++i)
364  {
365  local_ids[num_local_rows + i] = num_local_rows + i;
366  global_ids[num_local_rows + i] = num_global_rows + col_gids[i];
367  }
368 }
369 
371 template <typename CrsMatrixType>
372 int
373 ZoltanCrsColorer<CrsMatrixType>::get_number_of_edges(
374  void *data,
375  int sizeGID,
376  int sizeLID,
377  ZOLTAN_ID_PTR global_id,
378  ZOLTAN_ID_PTR local_id,
379  int *ierr)
380 {
381  assert(sizeGID == 1 && sizeLID == 1);
382 
383  ZoltanData *zoltan_data = static_cast<ZoltanData *>(data);
384  *ierr = ZOLTAN_OK;
385 
386  const size_t num_local_rows = zoltan_data->graph->getNodeNumRows();
387  const ZOLTAN_ID_TYPE lid = *local_id;
388  int num_edges = 0;
389 
390  if (lid < num_local_rows)
391  num_edges = zoltan_data->graph->getNumEntriesInLocalRow(lid);
392  else
393  num_edges =
394  zoltan_data->trans_graph->getNumEntriesInLocalRow(lid - num_local_rows);
395 
396  return num_edges;
397 }
398 
400 template <typename CrsMatrixType>
401 void
402 ZoltanCrsColorer<CrsMatrixType>::get_edge_list(
403  void *data,
404  int sizeGID,
405  int sizeLID,
406  ZOLTAN_ID_PTR global_id,
407  ZOLTAN_ID_PTR local_id,
408  ZOLTAN_ID_PTR nbor_global_ids,
409  int *nbor_procs,
410  int wgt_dim,
411  float *ewgts,
412  int *ierr)
413 {
414  using Teuchos::Array;
415  using Teuchos::ArrayView;
416  using Teuchos::arrayView;
417 
418  ZoltanData *zoltan_data = static_cast<ZoltanData *>(data);
419  *ierr = ZOLTAN_OK;
420 
421  const size_t num_local_rows = zoltan_data->graph->getNodeNumRows();
422  const size_t num_global_rows = zoltan_data->graph->getGlobalNumRows();
423  const ZOLTAN_ID_TYPE lid = *local_id;
424 
425  if (lid < num_local_rows)
426  {
427  const int num_nbr = zoltan_data->graph->getNumEntriesInLocalRow(lid);
428  const auto colMap = zoltan_data->graph->getColMap();
429 
430  typename CrsMatrixType::local_inds_host_view_type lcl_ids;
431  zoltan_data->graph->getLocalRowView(lid, lcl_ids);
432 
433  for (int j = 0; j < num_nbr; ++j) {
434  nbor_global_ids[j] = num_global_rows
435  + colMap->getGlobalElement(lcl_ids[j]);
436  nbor_procs[j] = zoltan_data->col_procs[lcl_ids[j]];
437  }
438  }
439  else
440  {
441  const int num_nbr =
442  zoltan_data->trans_graph->getNumEntriesInLocalRow(lid-num_local_rows);
443  const auto colMap = zoltan_data->trans_graph->getColMap();
444 
445  typename CrsMatrixType::local_inds_host_view_type lcl_ids;
446  zoltan_data->trans_graph->getLocalRowView(lid - num_local_rows, lcl_ids);
447  for (int j = 0; j < num_nbr; ++j)
448  {
449  nbor_global_ids[j] = colMap->getGlobalElement(lcl_ids[j]);
450  nbor_procs[j] = zoltan_data->trans_col_procs[lcl_ids[j]];
451  }
452  }
453 }
454 
456 template <typename CrsMatrixType>
457 int
458 ZoltanCrsColorer<CrsMatrixType>::sym_get_number_of_vertices(
459  void *data,
460  int *ierr)
461 {
462  ZoltanData *zoltan_data = static_cast<ZoltanData *>(data);
463  *ierr = ZOLTAN_OK;
464  return zoltan_data->graph->getNodeNumRows();
465 }
466 
468 template <typename CrsMatrixType>
469 void
470 ZoltanCrsColorer<CrsMatrixType>::sym_get_vertex_list(
471  void *data,
472  int sizeGID,
473  int sizeLID,
474  ZOLTAN_ID_PTR global_ids,
475  ZOLTAN_ID_PTR local_ids,
476  int wgt_dim,
477  float *obj_wgts,
478  int *ierr)
479 {
480  ZoltanData *zoltan_data = static_cast<ZoltanData *>(data);
481  *ierr = ZOLTAN_OK;
482 
483  const size_t num_local_rows = zoltan_data->graph->getNodeNumRows();
484  auto row_gids = zoltan_data->graph->getRowMap()->getNodeElementList();
485  for (size_t i = 0; i < num_local_rows; ++i)
486  {
487  local_ids[i] = i;
488  global_ids[i] = row_gids[i];
489  }
490 }
491 
493 template <typename CrsMatrixType>
494 int
495 ZoltanCrsColorer<CrsMatrixType>::sym_get_number_of_edges(
496  void *data,
497  int sizeGID,
498  int sizeLID,
499  ZOLTAN_ID_PTR global_id,
500  ZOLTAN_ID_PTR local_id,
501  int *ierr)
502 {
503  ZoltanData *zoltan_data = static_cast<ZoltanData *>(data);
504  *ierr = ZOLTAN_OK;
505 
506  const ZOLTAN_ID_TYPE lid = *local_id;
507  int num_edges = zoltan_data->graph->getNumEntriesInLocalRow(lid);
508  return num_edges;
509 }
510 
512 template <typename CrsMatrixType>
513 void
514 ZoltanCrsColorer<CrsMatrixType>::sym_get_edge_list(
515  void *data,
516  int sizeGID,
517  int sizeLID,
518  ZOLTAN_ID_PTR global_id,
519  ZOLTAN_ID_PTR local_id,
520  ZOLTAN_ID_PTR nbor_global_ids,
521  int *nbor_procs,
522  int wgt_dim,
523  float *ewgts,
524  int *ierr)
525 {
526  using Teuchos::Array;
527  using Teuchos::ArrayView;
528  using Teuchos::arrayView;
529 
530  ZoltanData *zoltan_data = static_cast<ZoltanData *>(data);
531  *ierr = ZOLTAN_OK;
532 
533  const ZOLTAN_ID_TYPE lid = *local_id;
534  const int num_nbr = zoltan_data->graph->getNumEntriesInLocalRow(lid);
535 
536  typename CrsMatrixType::local_inds_host_view_type lcl_ids;
537  zoltan_data->graph->getLocalRowView(lid, lcl_ids);
538  const auto colMap = zoltan_data->graph->getColMap();
539 
540  for (int j = 0; j < num_nbr; ++j)
541  {
542  nbor_global_ids[j] = colMap->getGlobalElement(lcl_ids[j]);
543  nbor_procs[j] = zoltan_data->col_procs[lcl_ids[j]];
544  }
545 }
546 } // namespace Zoltan2
ZoltanCrsColorer(const Teuchos::RCP< matrix_t > &matrix_)
void computeColoring(Teuchos::ParameterList &coloring_params, int &num_colors, list_of_colors_host_t &list_of_colors_host, list_of_colors_t &list_of_colors) const
Kokkos::View< int *, device_t > list_of_colors_t
matrix_t::global_ordinal_type gno_t
list_of_colors_t::HostMirror list_of_colors_host_t
Teuchos::RCP< Tpetra::CrsGraph< LO, GO, NO > > compute_transpose_graph(const Tpetra::CrsGraph< LO, GO, NO > &graph)
Created by mbenlioglu on Aug 31, 2020.