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 UniqueArray<ptrdiff_t> loc_part_cnt(npart, 0);
254 UniqueArray<ptrdiff_t> loc_part_beg(npart, 0);
255 UniqueArray<ptrdiff_t> glo_part_cnt(npart);
256 UniqueArray<ptrdiff_t> glo_part_beg(npart + 1);
260 auto reduce_operation = Arcane::MessagePassing::eReduceType::ReduceSum;
261 mpScanExclusive(comm.messagePassingMng(), reduce_operation, loc_part_cnt, loc_part_beg);
262 Span<const ptrdiff_t> loc_part_cnt_view(loc_part_cnt);
263 Span<ptrdiff_t> glo_part_cnt_view(glo_part_cnt);
264 mpAllReduce(comm.messagePassingMng(), reduce_operation, loc_part_cnt_view, glo_part_cnt_view);
266 std::partial_sum(glo_part_cnt.begin(), glo_part_cnt.end(), glo_part_beg.begin() + 1);
268 UniqueArray<ptrdiff_t> cnt(npart, 0);
269 for (ptrdiff_t i = 0; i < n; ++i) {
271 perm[i] = glo_part_beg[p] + loc_part_beg[p] + cnt[p]++;
274 ARCCORE_ALINA_TOC(
"perm index");
275 return std::make_tuple(glo_part_beg[std::min(npart, comm.rank)],
276 glo_part_beg[std::min(npart, comm.rank + 1)]);
282template <
class Backend,
class Idx>
283std::shared_ptr<DistributedMatrix<Backend>>
284mpi_graph_perm_matrix(
AlinaCommunicator comm, ptrdiff_t col_beg, ptrdiff_t col_end,
285 const std::vector<Idx>& perm)
287 typedef typename Backend::value_type value_type;
288 using build_matrix = Backend::matrix;
290 ARCCORE_ALINA_TIC(
"perm matrix");
292 ptrdiff_t n = perm.size();
293 ptrdiff_t ncols = col_end - col_beg;
295 auto i_loc = std::make_shared<build_matrix>();
296 auto i_rem = std::make_shared<build_matrix>();
298 build_matrix& I_loc = *i_loc;
299 build_matrix& I_rem = *i_rem;
301 I_loc.set_size(n, ncols,
false);
302 I_rem.set_size(n, 0,
false);
308 for (ptrdiff_t i = begin; i < (begin + size); ++i) {
309 ptrdiff_t j = perm[i];
311 if (col_beg <= j && j < col_end) {
312 I_loc.ptr[i + 1] = 1;
313 I_rem.ptr[i + 1] = 0;
316 I_loc.ptr[i + 1] = 0;
317 I_rem.ptr[i + 1] = 1;
322 I_loc.set_nonzeros(I_loc.scan_row_sizes());
323 I_rem.set_nonzeros(I_rem.scan_row_sizes());
326 for (ptrdiff_t i = begin; i < (begin + size); ++i) {
327 ptrdiff_t j = perm[i];
329 if (col_beg <= j && j < col_end) {
330 ptrdiff_t k = I_loc.ptr[i];
331 I_loc.col[k] = j - col_beg;
332 I_loc.val[k] = math::identity<value_type>();
335 ptrdiff_t k = I_rem.ptr[i];
337 I_rem.val[k] = math::identity<value_type>();
342 ARCCORE_ALINA_TOC(
"perm matrix");
343 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)
C void mpScanExclusive(IMessagePassingMng *pm, eReduceType rt, Span< const char > send_buf, Span< char > receive_buf)
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.