46struct ParmetisMatrixPartitioner
48 typedef typename Backend::value_type value_type;
50 using col_type = Backend::col_type;
51 using ptr_type = Backend::ptr_type;
66 : ARCCORE_ALINA_PARAMS_IMPORT_VALUE(p, shrink)
67 , ARCCORE_ALINA_PARAMS_IMPORT_VALUE(p, min_per_proc)
68 , ARCCORE_ALINA_PARAMS_IMPORT_VALUE(p, shrink_ratio)
70 p.check_params({
"shrink",
"min_per_proc",
"shrink_ratio" });
73 void get(
PropertyTree& p,
const std::string& path =
"")
const
75 ARCCORE_ALINA_PARAMS_EXPORT_VALUE(p, path, shrink);
76 ARCCORE_ALINA_PARAMS_EXPORT_VALUE(p, path, min_per_proc);
77 ARCCORE_ALINA_PARAMS_EXPORT_VALUE(p, path, shrink_ratio);
82 explicit ParmetisMatrixPartitioner(
const params& prm =
params())
86 bool is_needed(
const matrix& A)
const
92 ptrdiff_t n = A.loc_rows();
96 ptrdiff_t min_n = std::numeric_limits<ptrdiff_t>::max();
97 for (
int i = 0; i < comm.size; ++i) {
98 ptrdiff_t m = row_dom[i + 1] - row_dom[i];
100 min_n = std::min(min_n, m);
105 return (non_empty > 1) && (min_n <= prm.min_per_proc);
108 std::shared_ptr<matrix> operator()(
const matrix& A,
unsigned block_size = 1)
const
110 mpi_communicator comm = A.comm();
111 idx_t n = A.loc_rows();
112 ptrdiff_t row_beg = A.loc_col_shift();
115 int active = (n > 0);
116 int active_ranks = comm.reduceSum(active);
117 int shrink = prm.shrink ? prm.shrink_ratio : 1;
119 idx_t npart = std::max(1, active_ranks / shrink);
122 std::cout <<
"Partitioning[ParMETIS] " << active_ranks <<
" -> " << npart << std::endl;
124 std::vector<ptrdiff_t> perm(n);
125 ptrdiff_t col_beg, col_end;
128 col_beg = (comm.rank == 0) ? 0 : A.glob_rows();
129 col_end = A.glob_rows();
131 for (ptrdiff_t i = 0; i < n; ++i) {
132 perm[i] = row_beg + i;
136 if (block_size == 1) {
137 std::tie(col_beg, col_end) = partition(A, npart, perm);
140 typedef typename math::scalar_of<value_type>::type scalar;
141 using sbackend = BuiltinBackend<scalar,col_type,ptr_type>;
142 ptrdiff_t np = n / block_size;
144 DistributedMatrix<sbackend> A_pw(A.comm(),
145 pointwise_matrix(*A.local(), block_size),
146 pointwise_matrix(*A.remote(), block_size));
148 std::vector<ptrdiff_t> perm_pw(np);
150 std::tie(col_beg, col_end) = partition(A_pw, npart, perm_pw);
152 col_beg *= block_size;
153 col_end *= block_size;
155 for (ptrdiff_t ip = 0; ip < np; ++ip) {
156 ptrdiff_t i = ip * block_size;
157 ptrdiff_t j = perm_pw[ip] * block_size;
159 for (
unsigned k = 0; k < block_size; ++k)
165 return mpi_graph_perm_matrix<Backend>(comm, col_beg, col_end, perm);
169 std::tuple<ptrdiff_t, ptrdiff_t>
170 partition(
const DistributedMatrix<B>& A, idx_t npart, std::vector<ptrdiff_t>& perm)
const
172 mpi_communicator comm = A.comm();
173 idx_t n = A.loc_rows();
174 int active = (n > 0);
176 std::vector<idx_t> ptr;
177 std::vector<idx_t> col;
179 mpi_symm_graph(A, ptr, col);
187 std::vector<real_t> tpwgts(npart, 1.0 / npart);
188 std::vector<real_t> ubvec(ncon, 1.05);
189 std::vector<idx_t> part(n);
194 MPI_Comm_split(comm, active ? 0 : MPI_UNDEFINED, comm.rank, &scomm);
197 mpi_communicator sc(scomm);
198 std::vector<idx_t> vtxdist = sc.exclusive_sum(n);
201 METIS_OK == ParMETIS_V3_PartKway(&vtxdist[0], &ptr[0], &col[0], NULL, NULL, &wgtflag, &numflag, &ncon, &npart, &tpwgts[0], &ubvec[0], &options, &edgecut, &part[0], &scomm),
202 "Error in ParMETIS");
204 MPI_Comm_free(&scomm);
207 return mpi_graph_perm_index(comm, npart, part, perm);