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
12namespace Zoltan2
13{
14
15// Implementation of CrsColorer<> using Zoltan partial distance-2 coloring.
16// This is distributed-parallel, but not shared.
17template <typename CrsMatrixType>
19{
20public:
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
49private:
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
185template <typename CrsMatrixType>
186void
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
324template <typename CrsMatrixType>
325int
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
335template <typename CrsMatrixType>
336void
337ZoltanCrsColorer<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
371template <typename CrsMatrixType>
372int
373ZoltanCrsColorer<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
400template <typename CrsMatrixType>
401void
402ZoltanCrsColorer<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
456template <typename CrsMatrixType>
457int
458ZoltanCrsColorer<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
468template <typename CrsMatrixType>
469void
470ZoltanCrsColorer<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
493template <typename CrsMatrixType>
494int
495ZoltanCrsColorer<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
512template <typename CrsMatrixType>
513void
514ZoltanCrsColorer<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.