Arcane  v3.14.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
GraphDistributor.h
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2024 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/* GraphDistributor.h (C) 2000-2024 */
9/* */
10/* This file provides declaration and definition of a class used to */
11/* redistribute the graph accross another set of processors. */
12/*---------------------------------------------------------------------------*/
13#ifndef ARCANE_STD_GRAPHDISTRIBUTOR_H
14#define ARCANE_STD_GRAPHDISTRIBUTOR_H
15/*---------------------------------------------------------------------------*/
16/*---------------------------------------------------------------------------*/
17
18#include "arcane/utils/CheckedConvert.h"
19
20#include "arcane/IParallelTopology.h"
21#include "arcane/ParallelMngUtils.h"
22
23#include <memory>
24
25/*---------------------------------------------------------------------------*/
26/*---------------------------------------------------------------------------*/
27
28namespace Arcane
29{
30
31/*---------------------------------------------------------------------------*/
32/*---------------------------------------------------------------------------*/
43{
44 public:
45
47 : m_pm_ini(pm)
48 , m_targetSize(-1)
49 , m_targetRank(-1)
50 , m_skip(true)
51 , m_contribute(false)
52 {
53 }
54
57 {
58 m_is_init = true;
59 m_targetRank = -1;
60 m_skip = true;
61 m_contribute = false;
62 if (!m_pm_ini)
63 return;
64
66 if (topo->isMasterMachine()) {
67 m_contribute = true;
68 }
69
70 Int32 machineRank = topo->machineRank();
71 Int32ConstArrayView targetRanks = topo->masterMachineRanks();
72
73 m_targetRank = targetRanks[machineRank];
74 m_targetSize = targetRanks.size();
75
76 if ((m_targetSize != m_pm_ini->commSize()) // Only useful if number of processes change.
77 && (allow_only_one_rank || m_targetSize > 1)) { // And if more than 1 node for parmetis
78 m_skip = false;
79 m_pm_sub = m_pm_ini->createSubParallelMngRef(targetRanks);
80 }
81 else { // All ranks have to work.
82 // Still making a new communicator for safety when using with third party library
83 m_contribute = true;
84 m_targetRank = m_pm_ini->commRank();
85 m_targetSize = m_pm_ini->commSize();
86 Int32UniqueArray keptRanks(m_targetSize);
87 for (int i = 0; i < m_targetSize; i++)
88 keptRanks[i] = i;
89 m_pm_sub = m_pm_ini->createSubParallelMngRef(keptRanks);
90 }
91
92 m_pm_ini->traceMng()->info() << "Running on " << m_targetSize << " nodes";
93 }
94
95 // Max is hard-coded to work on integers.
96 void initWithMaxRank(Int32 targetSize)
97 {
98 m_is_init = true;
99 m_targetSize = targetSize;
100 m_targetRank = -1;
101 m_skip = true;
102 m_contribute = false;
103
104 if (!m_pm_ini)
105 return;
106
107 if (m_pm_ini->commRank() < targetSize) { // At this time, no duplication
108 m_contribute = 1;
109 }
110 Int64 my_rank = m_pm_ini->commRank();
111 Int64 x = my_rank * m_targetSize;
112 m_targetRank = CheckedConvert::toInt32(x / m_pm_ini->commSize());
113
114 Int32UniqueArray keepProc(m_targetSize);
115 Int32 step = m_targetSize / m_pm_ini->commSize();
116 step = (step == 0) ? 1 : step;
117 for (int i = 0; i < m_targetSize; ++i) {
118 keepProc[i] = i * step;
119 }
120
121 m_pm_sub = m_pm_ini->createSubParallelMngRef(keepProc);
122
123 if (m_targetSize != m_pm_ini->commSize()) {
124 m_skip = false;
125 }
126 }
127
128 public:
129
130 Int32 size() const { return m_targetSize; }
131
132 bool contribute() const { return m_contribute; }
133
134 //< Do the redistribution pm -> newComm
135 template <typename DataT>
136 SharedArray<DataT> convert(ConstArrayView<DataT> in, Array<DataT>* pattern = nullptr,
137 bool is_indirection = false) const
138 {
139 if (!m_is_init)
140 ARCANE_FATAL("Missing initialisation");
141 if (m_skip) {
142 SharedArray<DataT> out(in);
143 if (pattern != NULL) {
144 Integer size = in.size();
145 if (is_indirection)
146 size -= 1;
147 pattern->resize(size, m_targetRank);
148 }
149 return out;
150 }
151 ConstArrayView<DataT> toSnd;
152
153 Int32 nInfos = 2;
154 if (is_indirection) {
155 toSnd = in.subView(0, in.size() - 1);
156 nInfos += 1; // need to store end of array
157 }
158 else {
159 toSnd = in;
160 }
161
162 Int32 commSize = m_pm_ini->commSize();
163 UniqueArray<Int32> sndCnt(nInfos * commSize, -1);
164 UniqueArray<Parallel::Request> req;
165 UniqueArray<Int32> n_wanted(nInfos);
166 n_wanted[0] = m_targetRank;
167 n_wanted[1] = toSnd.size();
168 if (is_indirection)
169 n_wanted[2] = static_cast<Int32>(in[in.size() - 1]);
170
171 m_pm_ini->allGather(n_wanted, sndCnt);
172
173 UniqueArray<Int32> sndNbr(commSize, 0);
174 UniqueArray<Int32> rcvNbr(commSize, 0);
175 UniqueArray<Int32> sndDsp(commSize, 0);
176 UniqueArray<Int32> rcvDsp(commSize, 0);
177
178 sndNbr[m_targetRank] = toSnd.size();
179
180 if (pattern != NULL) {
181 pattern->resize(0);
182 }
183
184 Int32 myRank = m_pm_ini->commRank();
185 Int32 begin = 0;
186 for (int i = 0; i < commSize; ++i) {
187 if (sndCnt[nInfos * i] == myRank) { // We have to receive this message
188 rcvNbr[i] = sndCnt[nInfos * i + 1];
189 rcvDsp[i] = begin;
190 begin += rcvNbr[i];
191
192 if (pattern != NULL)
193 pattern->addRange(i, rcvNbr[i]);
194 }
195 }
196 if (contribute() && is_indirection)
197 begin += 1; // Trick: add one to mark end of array
198 SharedArray<DataT> out(begin, -1);
199
200 m_pm_ini->allToAllVariable(toSnd, sndNbr, sndDsp, out, rcvNbr, rcvDsp);
201
202 if (contribute() && is_indirection) { // We have to update offsets
203 DataT offset = 0;
204 DataT* my_iter = out.data();
205 for (int i = 0; i < commSize; ++i) {
206 if (sndCnt[nInfos * i] == myRank) { // We have to receive this message
207 Int32 nRecv = sndCnt[nInfos * i + 1];
208 DataT* my_end(my_iter + nRecv);
209 for (; my_iter != my_end; ++my_iter)
210 (*my_iter) += offset;
211 offset += sndCnt[nInfos * i + 2];
212 }
213 }
214 out[out.size() - 1] = offset;
215 }
216
217 return out;
218 }
219
220 //< Do the backward redistribution newComm -> pm
221 template <typename DataT>
222 SharedArray<DataT> convertBack(ConstArrayView<DataT> in, Int32 nRecv) const
223 {
224 if (!m_is_init)
225 ARCANE_FATAL("Missing initialisation");
226 if (m_skip) {
227 SharedArray<DataT> out(in);
228 return out;
229 }
230
231 Int32 nInfos = 2;
232 Int32 commSize = m_pm_ini->commSize();
233 UniqueArray<Int32> sndCnt(nInfos * commSize, -1);
234 UniqueArray<Parallel::Request> req;
235 UniqueArray<Int32> n_wanted(nInfos);
236 n_wanted[0] = m_targetRank;
237 n_wanted[1] = nRecv;
238
239 m_pm_ini->allGather(n_wanted, sndCnt);
240
241 UniqueArray<Int32> sndNbr(commSize, 0);
242 UniqueArray<Int32> rcvNbr(commSize, 0);
243 UniqueArray<Int32> sndDsp(commSize, 0);
244 UniqueArray<Int32> rcvDsp(commSize, 0);
245
246 rcvNbr[m_targetRank] = nRecv;
247
248 Int32 myRank = m_pm_ini->commRank();
249 Int32 begin = 0;
250 for (int i = 0; i < commSize; ++i) {
251 if (sndCnt[nInfos * i] == myRank) { // We have to receive this message
252 sndNbr[i] = sndCnt[nInfos * i + 1];
253 sndDsp[i] = begin;
254 begin += sndNbr[i];
255 }
256 }
257 SharedArray<DataT> out(nRecv, -1);
258
259 m_pm_ini->allToAllVariable(in, sndNbr, sndDsp, out, rcvNbr, rcvDsp);
260
261 return out;
262 }
263
264 IParallelMng* subParallelMng() const
265 {
266 IParallelMng* pm = m_pm_sub.get();
267 if (pm)
268 return pm;
269 return m_pm_ini->sequentialParallelMng();
270 }
271
272 public:
273
274 ARCANE_DEPRECATED_REASON("Y2024: This method is internal to Arcane. Use subParallelMng()->communicator() instead")
275 MPI_Comm getCommunicator() const
276 {
277 if (!m_pm_sub)
278 return MPI_COMM_NULL;
279 Parallel::Communicator comm = m_pm_sub->communicator();
280 return (MPI_Comm)comm;
281 }
282
283 ARCANE_DEPRECATED_REASON("Y2024: This method is internal to Arcane. Use subParallelMng() instead")
284 IParallelMng* parallelManager() const
285 {
286 return m_pm_sub.get();
287 }
288
289 private:
290
291 IParallelMng* m_pm_ini = nullptr;
292 Ref<IParallelMng> m_pm_sub;
293 Int32 m_targetSize = -1; // Taille du sous-communicateur
294 Int32 m_targetRank = -1; // Rang dans le sous-communicateur
295 bool m_skip = false; // Pas de redistribution
296 bool m_contribute = false;
297 bool m_is_init = false;
298};
299
300/*---------------------------------------------------------------------------*/
301/*---------------------------------------------------------------------------*/
302
303} // End namespace Arcane
304
305/*---------------------------------------------------------------------------*/
306/*---------------------------------------------------------------------------*/
307
308
309#endif
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Redistribute graph data to another "communicator".
void initWithOneRankPerNode(bool allow_only_one_rank)
Automatic distribution : one partitioning process per node.
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual ITraceMng * traceMng() const =0
Gestionnaire de traces.
virtual Int32 commRank() const =0
Rang de cette instance dans le communicateur.
virtual IParallelMng * sequentialParallelMng()=0
Retourne un gestionnaire de parallélisme séquentiel.
virtual Int32 commSize() const =0
Nombre d'instance dans le communicateur.
virtual void allGather(ConstArrayView< char > send_buf, ArrayView< char > recv_buf)=0
Effectue un regroupement sur tous les processeurs. Il s'agit d'une opération collective....
virtual Ref< IParallelMng > createSubParallelMngRef(Int32ConstArrayView kept_ranks)=0
Créé un nouveau gestionnaire de parallélisme pour un sous-ensemble des rangs.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
Vue constante d'un tableau de type T.
TraceMessage info() const
Flot pour un message d'information.
Vecteur 1D de données avec sémantique par valeur (style STL).
Int32 toInt32(Int64 v)
Converti un Int64 en un Int32.
Ref< IParallelTopology > createTopologyRef(IParallelMng *pm)
Créé une instance contenant les infos sur la topologie des rangs de ce gestionnnaire.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:515
Int32 Integer
Type représentant un entier.