12#ifndef ARCCORE_ALINA_MATRIXPARTITIONUTILS_H
13#define ARCCORE_ALINA_MATRIXPARTITIONUTILS_H
26#include "arccore/alina/BackendInterface.h"
27#include "arccore/alina/DistributedMatrix.h"
40namespace Arcane::Alina
46template <
class Backend,
class Ptr,
class Col>
void
48 std::vector<Ptr>& ptr, std::vector<Col>& col)
50 using build_matrix = Backend::matrix;
52 ARCCORE_ALINA_TIC(
"symm graph");
54 build_matrix& A_loc = *A.local();
55 build_matrix& A_rem = *A.remote();
57 ptrdiff_t n = A_loc.nbRow();
58 ptrdiff_t row_beg = A.loc_col_shift();
60 auto T = transpose(A);
62 build_matrix& T_loc = *T->local();
63 build_matrix& T_rem = *T->remote();
69 for (ptrdiff_t i = begin; i < (begin + size); ++i) {
70 using Alina::detail::sort_row;
72 ptrdiff_t A_loc_beg = A_loc.ptr[i];
73 ptrdiff_t A_loc_end = A_loc.ptr[i + 1];
75 ptrdiff_t A_rem_beg = A_rem.ptr[i];
76 ptrdiff_t A_rem_end = A_rem.ptr[i + 1];
78 ptrdiff_t T_loc_beg = T_loc.ptr[i];
79 ptrdiff_t T_loc_end = T_loc.ptr[i + 1];
81 ptrdiff_t T_rem_beg = T_rem.ptr[i];
82 ptrdiff_t T_rem_end = T_rem.ptr[i + 1];
84 sort_row(A_loc.col + A_loc_beg, A_loc.val + A_loc_beg, A_loc_end - A_loc_beg);
85 sort_row(A_rem.col + A_rem_beg, A_rem.val + A_rem_beg, A_rem_end - A_rem_beg);
87 sort_row(T_loc.col + T_loc_beg, T_loc.val + T_loc_beg, T_loc_end - T_loc_beg);
88 sort_row(T_rem.col + T_rem_beg, T_rem.val + T_rem_beg, T_rem_end - T_rem_beg);
92 for (ptrdiff_t ja = A_loc_beg, jt = T_loc_beg; ja < A_loc_end || jt < T_loc_end;) {
94 if (ja == A_loc_end) {
98 else if (jt == T_loc_end) {
103 ptrdiff_t ca = A_loc.col[ja];
104 ptrdiff_t ct = T_loc.col[jt];
124 for (ptrdiff_t ja = A_rem_beg, jt = T_rem_beg; ja < A_rem_end || jt < T_rem_end;) {
125 if (ja == A_rem_end) {
128 else if (jt == T_rem_end) {
132 ptrdiff_t ca = A_rem.col[ja];
133 ptrdiff_t ct = T_rem.col[jt];
149 ptr[i + 1] = row_width;
153 std::partial_sum(ptr.begin(), ptr.end(), ptr.begin());
155 col.resize(ptr.back());
160 for (ptrdiff_t i = begin; i < (begin + size); ++i) {
161 ptrdiff_t A_loc_beg = A_loc.ptr[i];
162 ptrdiff_t A_loc_end = A_loc.ptr[i + 1];
164 ptrdiff_t A_rem_beg = A_rem.ptr[i];
165 ptrdiff_t A_rem_end = A_rem.ptr[i + 1];
167 ptrdiff_t T_loc_beg = T_loc.ptr[i];
168 ptrdiff_t T_loc_end = T_loc.ptr[i + 1];
170 ptrdiff_t T_rem_beg = T_rem.ptr[i];
171 ptrdiff_t T_rem_end = T_rem.ptr[i + 1];
175 for (ptrdiff_t ja = A_loc_beg, jt = T_loc_beg; ja < A_loc_end || jt < T_loc_end;) {
177 if (ja == A_loc_end) {
181 else if (jt == T_loc_end) {
186 ptrdiff_t ca = A_loc.col[ja];
187 ptrdiff_t ct = T_loc.col[jt];
204 col[head++] = c + row_beg;
207 for (ptrdiff_t ja = A_rem_beg, jt = T_rem_beg; ja < A_rem_end || jt < T_rem_end;) {
208 if (ja == A_rem_end) {
209 col[head] = T_rem.col[jt];
212 else if (jt == T_rem_end) {
213 col[head] = A_rem.col[ja];
217 ptrdiff_t ca = A_rem.col[ja];
218 ptrdiff_t ct = T_rem.col[jt];
239 ARCCORE_ALINA_TOC(
"symm graph");
245template <
class Idx> std::tuple<ptrdiff_t, ptrdiff_t>
246mpi_graph_perm_index(
AlinaCommunicator comm,
int npart,
const std::vector<Idx>& part,
247 std::vector<ptrdiff_t>& perm)
249 ARCCORE_ALINA_TIC(
"perm index");
250 ptrdiff_t n = part.size();
253 std::vector<ptrdiff_t> loc_part_cnt(npart, 0);
254 std::vector<ptrdiff_t> loc_part_beg(npart, 0);
255 std::vector<ptrdiff_t> glo_part_cnt(npart);
256 std::vector<ptrdiff_t> glo_part_beg(npart + 1);
260 MPI_Datatype ptr_datatype = MPI_LONG_LONG;
261 MPI_Exscan(loc_part_cnt.data(), loc_part_beg.data(), npart, ptr_datatype, MPI_SUM, comm.mpiCommunicator());
263 Span<const ptrdiff_t> loc_part_cnt_view(loc_part_cnt.data(), npart);
264 Span<ptrdiff_t> glo_part_cnt_view(glo_part_cnt.data(), npart);
265 glo_part_cnt_view.copy(loc_part_cnt_view);
266 mpAllReduce(comm.messagePassingMng(), Arcane::MessagePassing::eReduceType::ReduceSum, glo_part_cnt_view);
268 std::partial_sum(glo_part_cnt.begin(), glo_part_cnt.end(), glo_part_beg.begin() + 1);
270 std::vector<ptrdiff_t> cnt(npart, 0);
271 for (ptrdiff_t i = 0; i < n; ++i) {
273 perm[i] = glo_part_beg[p] + loc_part_beg[p] + cnt[p]++;
276 ARCCORE_ALINA_TOC(
"perm index");
277 return std::make_tuple(
278 glo_part_beg[std::min(npart, comm.rank)],
279 glo_part_beg[std::min(npart, comm.rank + 1)]);
285template <
class Backend,
class Idx>
286std::shared_ptr<DistributedMatrix<Backend>>
287mpi_graph_perm_matrix(
AlinaCommunicator comm, ptrdiff_t col_beg, ptrdiff_t col_end,
288 const std::vector<Idx>& perm)
290 typedef typename Backend::value_type value_type;
291 using build_matrix = Backend::matrix;
293 ARCCORE_ALINA_TIC(
"perm matrix");
295 ptrdiff_t n = perm.size();
296 ptrdiff_t ncols = col_end - col_beg;
298 auto i_loc = std::make_shared<build_matrix>();
299 auto i_rem = std::make_shared<build_matrix>();
301 build_matrix& I_loc = *i_loc;
302 build_matrix& I_rem = *i_rem;
304 I_loc.set_size(n, ncols,
false);
305 I_rem.set_size(n, 0,
false);
311 for (ptrdiff_t i = begin; i < (begin + size); ++i) {
312 ptrdiff_t j = perm[i];
314 if (col_beg <= j && j < col_end) {
315 I_loc.ptr[i + 1] = 1;
316 I_rem.ptr[i + 1] = 0;
319 I_loc.ptr[i + 1] = 0;
320 I_rem.ptr[i + 1] = 1;
325 I_loc.set_nonzeros(I_loc.scan_row_sizes());
326 I_rem.set_nonzeros(I_rem.scan_row_sizes());
329 for (ptrdiff_t i = begin; i < (begin + size); ++i) {
330 ptrdiff_t j = perm[i];
332 if (col_beg <= j && j < col_end) {
333 ptrdiff_t k = I_loc.ptr[i];
334 I_loc.col[k] = j - col_beg;
335 I_loc.val[k] = math::identity<value_type>();
338 ptrdiff_t k = I_rem.ptr[i];
340 I_rem.val[k] = math::identity<value_type>();
345 ARCCORE_ALINA_TOC(
"perm matrix");
346 return std::make_shared<DistributedMatrix<Backend>>(comm, i_loc, i_rem);
Brief list of message exchange functions.
Distributed Matrix using message passing.
C char mpAllReduce(IMessagePassingMng *pm, eReduceType rt, char v)
void arccoreParallelFor(const ComplexForLoopRanges< RankValue, IndexType_ > &loop_ranges, const ForLoopRunInfo &run_info, const LambdaType &lambda_function, const ReducerArgs &... reducer_args)
Applies the lambda function lambda_function concurrently over the iteration interval given by loop_ra...
std::int32_t Int32
Signed integer type of 32 bits.
Convenience wrapper around MPI_Comm.