Arcane  v4.1.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
SimpleMatrixPartitioner.h
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* SimpleMatrixPartitioner.h (C) 2000-2026 */
9/* */
10/* Simple matrix partitioner merging consecutive domains together. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCCORE_ALINA_SIMPLEMATRIXPARTITIONER_H
13#define ARCCORE_ALINA_SIMPLEMATRIXPARTITIONER_H
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16/*
17 * This file is based on the work on AMGCL library (version march 2026)
18 * which can be found at https://github.com/ddemidov/amgcl.
19 *
20 * Copyright (c) 2012-2022 Denis Demidov <dennis.demidov@gmail.com>
21 * SPDX-License-Identifier: MIT
22 */
23/*---------------------------------------------------------------------------*/
24/*---------------------------------------------------------------------------*/
25
26#include <memory>
27
28#include "arccore/alina/BackendInterface.h"
29#include "arccore/alina/MessagePassingUtils.h"
30#include "arccore/alina/DistributedMatrix.h"
31#include "arccore/alina/MatrixPartitionUtils.h"
32
33/*---------------------------------------------------------------------------*/
34/*---------------------------------------------------------------------------*/
35
36namespace Arcane::Alina
37{
38
39/*---------------------------------------------------------------------------*/
40/*---------------------------------------------------------------------------*/
44template <class Backend>
45struct SimpleMatrixPartitioner
46{
47 typedef typename Backend::value_type value_type;
48 typedef DistributedMatrix<Backend> matrix;
49
50 struct params
51 {
52 bool enable = false;
53 int min_per_proc = 10000;
54 int shrink_ratio = 8;
55
56 params() = default;
57
58 params(const PropertyTree& p)
59 : ARCCORE_ALINA_PARAMS_IMPORT_VALUE(p, enable)
60 , ARCCORE_ALINA_PARAMS_IMPORT_VALUE(p, min_per_proc)
61 , ARCCORE_ALINA_PARAMS_IMPORT_VALUE(p, shrink_ratio)
62 {
63 p.check_params({ "enable", "min_per_proc", "shrink_ratio" });
64 }
65
66 void get(PropertyTree& p, const std::string& path = "") const
67 {
68 ARCCORE_ALINA_PARAMS_EXPORT_VALUE(p, path, enable);
69 ARCCORE_ALINA_PARAMS_EXPORT_VALUE(p, path, min_per_proc);
70 ARCCORE_ALINA_PARAMS_EXPORT_VALUE(p, path, shrink_ratio);
71 }
72
73 } prm;
74
75 explicit SimpleMatrixPartitioner(const params& prm = params())
76 : prm(prm)
77 {}
78
79 bool is_needed(const matrix& A) const
80 {
81 if (!prm.enable)
82 return false;
83
84 mpi_communicator comm = A.comm();
85 ptrdiff_t n = A.loc_rows();
86 std::vector<ptrdiff_t> row_dom = comm.exclusive_sum(n);
87
88 int non_empty = 0;
89 ptrdiff_t min_n = std::numeric_limits<ptrdiff_t>::max();
90 for (int i = 0; i < comm.size; ++i) {
91 ptrdiff_t m = row_dom[i + 1] - row_dom[i];
92 if (m) {
93 min_n = std::min(min_n, m);
94 ++non_empty;
95 }
96 }
97
98 return (non_empty > 1) && (min_n <= prm.min_per_proc);
99 }
100
101 std::shared_ptr<matrix> operator()(const matrix& A, unsigned /*block_size*/ = 1) const
102 {
103 mpi_communicator comm = A.comm();
104 ptrdiff_t nrows = A.loc_rows();
105
106 std::vector<ptrdiff_t> row_dom = comm.exclusive_sum(nrows);
107 std::vector<ptrdiff_t> col_dom(comm.size + 1);
108
109 for (int i = 0; i <= comm.size; ++i)
110 col_dom[i] = row_dom[std::min<int>(i * prm.shrink_ratio, comm.size)];
111
112 int old_domains = 0;
113 int new_domains = 0;
114
115 for (int i = 0; i < comm.size; ++i) {
116 if (row_dom[i + 1] > row_dom[i])
117 ++old_domains;
118 if (col_dom[i + 1] > col_dom[i])
119 ++new_domains;
120 }
121
122 if (comm.rank == 0)
123 std::cout << "Partitioning[Simple] " << old_domains << " -> " << new_domains << std::endl;
124
125 ptrdiff_t row_beg = row_dom[comm.rank];
126 ptrdiff_t col_beg = col_dom[comm.rank];
127 ptrdiff_t col_end = col_dom[comm.rank + 1];
128
129 std::vector<ptrdiff_t> perm(nrows);
130 for (ptrdiff_t i = 0; i < nrows; ++i) {
131 perm[i] = i + row_beg;
132 }
133
134 return mpi_graph_perm_matrix<Backend>(comm, col_beg, col_end, perm);
135 }
136};
137
138/*---------------------------------------------------------------------------*/
139/*---------------------------------------------------------------------------*/
140
141} // namespace Arcane::Alina
142
143/*---------------------------------------------------------------------------*/
144/*---------------------------------------------------------------------------*/
145
146#endif
Distributed Matrix using message passing.
Convenience wrapper around MPI_Comm.
std::vector< T > exclusive_sum(T n) const
Exclusive sum over mpi communicator.