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