Arcane  v4.1.0.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
MeshMaterialVariableSynchronizerList.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2025 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/* MeshMaterialVariableSynchronizerList.cc (C) 2000-2025 */
9/* */
10/* Synchroniseur de variables matériaux. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/materials/MeshMaterialVariableSynchronizerList.h"
15
16#include "arcane/utils/ITraceMng.h"
17#include "arcane/utils/NotSupportedException.h"
18#include "arcane/utils/ValueConvert.h"
19#include "arcane/utils/FatalErrorException.h"
20
21#include "arcane/core/IParallelMng.h"
22#include "arcane/core/IVariableSynchronizer.h"
23#include "arcane/core/internal/IParallelMngInternal.h"
24#include "arcane/core/materials/IMeshMaterialMng.h"
25#include "arcane/core/materials/internal/IMeshMaterialVariableInternal.h"
26#include "arcane/core/materials/internal/IMeshMaterialMngInternal.h"
27
28#include "arcane/materials/MeshMaterialVariable.h"
29#include "arcane/materials/IMeshMaterialSynchronizeBuffer.h"
30#include "arcane/materials/IMeshMaterialVariableSynchronizer.h"
31
32#include "arcane/accelerator/core/RunQueue.h"
33
35
36/*---------------------------------------------------------------------------*/
37/*---------------------------------------------------------------------------*/
38
39namespace Arcane::Materials
40{
41namespace MP = Arccore::MessagePassing;
42
43/*---------------------------------------------------------------------------*/
44/*---------------------------------------------------------------------------*/
45
47{
48 public:
49
52 UniqueArray<Int32> data_sizes;
53 bool use_generic_version = false;
54 Int32 sync_version = 0;
55 IMeshMaterialVariableSynchronizer* mat_synchronizer = nullptr;
56 Int64 message_total_size = 0;
58 MP::MessageTag message_tag;
59};
60
61/*---------------------------------------------------------------------------*/
62/*---------------------------------------------------------------------------*/
63
65{
66 public:
67
68 explicit Impl(IMeshMaterialMng* material_mng)
69 : m_material_mng(material_mng)
70 {
71 // Pour utiliser l'ancien (avant la version accélérateur) mécanisme de synchronisation.
72 // TEMPORAIRE: à supprimer fin 2023.
73 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_MATERIAL_LEGACY_SYNCHRONIZE", true))
74 m_use_generic_version = (v.value() == 0);
75 }
76
77 public:
78
79 IMeshMaterialMng* m_material_mng;
82 Int64 m_total_size = 0;
83 bool m_use_generic_version = true;
84 eMemoryRessource m_buffer_memory_ressource = eMemoryRessource::Host;
85 SyncInfo m_mat_env_sync_info;
86 SyncInfo m_env_only_sync_info;
87 bool m_is_in_sync = false;
88};
89
90/*---------------------------------------------------------------------------*/
91/*---------------------------------------------------------------------------*/
92
93MeshMaterialVariableSynchronizerList::
94MeshMaterialVariableSynchronizerList(IMeshMaterialMng* material_mng)
95: m_p(new Impl(material_mng))
96{
97}
98
99/*---------------------------------------------------------------------------*/
100/*---------------------------------------------------------------------------*/
101
102MeshMaterialVariableSynchronizerList::
103~MeshMaterialVariableSynchronizerList()
104{
105 delete m_p;
106}
107
108/*---------------------------------------------------------------------------*/
109/*---------------------------------------------------------------------------*/
110
112totalMessageSize() const
113{
114 return m_p->m_total_size;
115}
116
117/*---------------------------------------------------------------------------*/
118/*---------------------------------------------------------------------------*/
119
121apply()
122{
123 // Avec la version 8 des synchronisations, il faut faire obligatoirement
124 // que chaque synchronisation soit bloquante car il n'y a qu'un seul
125 // buffer partagé.
126 Int32 v = m_p->m_material_mng->synchronizeVariableVersion();
127 bool is_blocking = (v == 8);
128
129 _beginSynchronize(is_blocking);
130 _endSynchronize(is_blocking);
131}
132
133/*---------------------------------------------------------------------------*/
134/*---------------------------------------------------------------------------*/
135
138{
139 Int32 v = m_p->m_material_mng->synchronizeVariableVersion();
140 if (v != 7)
141 ARCANE_FATAL("beginSynchronize() is only valid for synchronize version 7 (v={0})", v);
142 _beginSynchronize(false);
143}
144
145/*---------------------------------------------------------------------------*/
146/*---------------------------------------------------------------------------*/
147
150{
151 _endSynchronize(false);
152}
153
154/*---------------------------------------------------------------------------*/
155/*---------------------------------------------------------------------------*/
156
157void MeshMaterialVariableSynchronizerList::
158_beginSynchronize(bool is_blocking)
159{
160 if (m_p->m_is_in_sync)
161 ARCANE_FATAL("Already synchronizing");
162 m_p->m_is_in_sync = true;
163
164 m_p->m_total_size = 0;
165 // TODO: modifier le synchroniser pour faire cela en une passe
166 // de send/recv/wait.
167 IMeshMaterialMng* mm = m_p->m_material_mng;
168 m_p->m_mat_env_sync_info = SyncInfo();
169 m_p->m_env_only_sync_info = SyncInfo();
170
171 {
172 SyncInfo& sync_info = m_p->m_mat_env_sync_info;
173 _fillSyncInfo(sync_info);
174 sync_info.mat_synchronizer = mm->_internalApi()->allCellsMatEnvSynchronizer();
175 sync_info.variables = m_p->m_mat_env_vars;
176 sync_info.message_tag = MP::MessageTag(569);
177 if (!sync_info.variables.empty()) {
178 _beginSynchronizeMultiple(sync_info);
179 if (is_blocking)
180 _endSynchronizeMultiple2(sync_info);
181 }
182 }
183 {
184 SyncInfo& sync_info = m_p->m_env_only_sync_info;
185 _fillSyncInfo(sync_info);
186 sync_info.mat_synchronizer = mm->_internalApi()->allCellsEnvOnlySynchronizer();
187 sync_info.variables = m_p->m_env_only_vars;
188 sync_info.message_tag = MP::MessageTag(585);
189 if (!sync_info.variables.empty()) {
190 _beginSynchronizeMultiple(sync_info);
191 if (is_blocking)
192 _endSynchronizeMultiple2(sync_info);
193 }
194 }
195}
196
197/*---------------------------------------------------------------------------*/
198/*---------------------------------------------------------------------------*/
199
200void MeshMaterialVariableSynchronizerList::
201_endSynchronize(bool is_blocking)
202{
203 if (!m_p->m_is_in_sync)
204 ARCANE_FATAL("beginSynchronize() has to be called before endSynchronize()");
205
206 {
207 SyncInfo& sync_info = m_p->m_mat_env_sync_info;
208 if (!sync_info.variables.empty() && !is_blocking)
209 _endSynchronizeMultiple2(sync_info);
210 m_p->m_total_size += sync_info.message_total_size;
211 }
212 {
213 SyncInfo& sync_info = m_p->m_env_only_sync_info;
214 if (!sync_info.variables.empty() && !is_blocking)
215 _endSynchronizeMultiple2(sync_info);
216 m_p->m_total_size += sync_info.message_total_size;
217 }
218
219 m_p->m_is_in_sync = false;
220}
221
222/*---------------------------------------------------------------------------*/
223/*---------------------------------------------------------------------------*/
224
227{
228 MatVarSpace mvs = var->space();
230 m_p->m_mat_env_vars.add(var);
231 else if (mvs == MatVarSpace::Environment)
232 m_p->m_env_only_vars.add(var);
233 else
234 ARCANE_THROW(NotSupportedException, "Invalid space for variable name={0} space={1}",
235 var->name(), (int)mvs);
236}
237
238/*---------------------------------------------------------------------------*/
239/*---------------------------------------------------------------------------*/
240
241void MeshMaterialVariableSynchronizerList::
242_fillSyncInfo(SyncInfo& sync_info)
243{
244 sync_info.use_generic_version = m_p->m_use_generic_version;
245 sync_info.sync_version = m_p->m_material_mng->synchronizeVariableVersion();
246}
247
248/*---------------------------------------------------------------------------*/
249/*---------------------------------------------------------------------------*/
250
251void MeshMaterialVariableSynchronizerList::
252_beginSynchronizeMultiple(SyncInfo& sync_info)
253{
254 IMeshMaterialVariableSynchronizer* mmvs = sync_info.mat_synchronizer;
256 const Int32 sync_version = sync_info.sync_version;
257
258 if (sync_version == 8) {
259 // Version 8. Utilise le buffer commun pour éviter les multiples allocations
260 sync_info.buf_list = mmvs->commonBuffer();
261 }
262 else if (sync_version == 7) {
263 // Version 7. Utilise un buffer unique, mais réalloué à chaque fois.
264 sync_info.buf_list = impl::makeOneBufferMeshMaterialSynchronizeBufferRef(mem);
265 }
266 else {
267 // Version 6. Version historique avec plusieurs buffers recréés à chaque fois.
268 sync_info.buf_list = impl::makeMultiBufferMeshMaterialSynchronizeBufferRef(mem);
269 }
270 if (sync_version < 8) {
272 Integer nb_rank = ranks.size();
273 sync_info.buf_list->setNbRank(nb_rank);
274 }
275
276 _beginSynchronizeMultiple2(sync_info);
277}
278
279/*---------------------------------------------------------------------------*/
280/*---------------------------------------------------------------------------*/
281
282void MeshMaterialVariableSynchronizerList::
283_beginSynchronizeMultiple2(SyncInfo& sync_info)
284{
285 ConstArrayView<MeshMaterialVariable*> vars = sync_info.variables;
286 IMeshMaterialSynchronizeBuffer* buf_list = sync_info.buf_list.get();
287 IMeshMaterialVariableSynchronizer* mmvs = sync_info.mat_synchronizer;
288 // Version de la synchronisation qui envoie uniquement
289 // les valeurs des matériaux et des milieux pour les mailles
290 // partagées.
291 // NOTE: Cette version nécessite que les matériaux soient correctement
292 // synchronisés entre les sous-domaines.
293
294 IVariableSynchronizer* var_syncer = mmvs->variableSynchronizer();
295 IParallelMng* pm = var_syncer->parallelMng();
296 IMessagePassingMng* mpm = pm->messagePassingMng();
297
298 // TODO: gérer l'alignement des multiples buffer.
299
300 // TODO: ajouter un tag pour garantir que les synchros sont sur les
301 // memes variables.
302
303 if (!pm->isParallel())
304 return;
305 const bool use_new_version = sync_info.use_generic_version;
306 RunQueue queue = pm->_internalApi()->queue();
307
308 mmvs->checkRecompute();
309
310 ITraceMng* tm = pm->traceMng();
311 Integer nb_var = vars.size();
312 tm->info(4) << "MAT_SYNCHRONIZE version=" << sync_info.sync_version << " multiple n="
313 << nb_var << " is_generic?=" << use_new_version;
314
315 sync_info.data_sizes.resize(nb_var);
316 Integer all_datatype_size = 0;
317 for (Integer i = 0; i < nb_var; ++i) {
318 sync_info.data_sizes[i] = vars[i]->dataTypeSize();
319 all_datatype_size += sync_info.data_sizes[i];
320 tm->info(4) << "MAT_SYNCHRONIZE name=" << vars[i]->name()
321 << " size=" << sync_info.data_sizes[i];
322 }
323
324 Int32ConstArrayView ranks = var_syncer->communicatingRanks();
325 Int32 nb_rank = ranks.size();
326
327 // Calcul la taille des buffers et réalloue si nécessaire
328 for (Integer i = 0; i < nb_rank; ++i) {
329 ConstArrayView<MatVarIndex> ghost_matcells(mmvs->ghostItems(i));
330 Integer total_ghost = ghost_matcells.size();
331 buf_list->setReceiveBufferSize(i, total_ghost * all_datatype_size);
332 ConstArrayView<MatVarIndex> shared_matcells(mmvs->sharedItems(i));
333 Integer total_shared = shared_matcells.size();
334 buf_list->setSendBufferSize(i, total_shared * all_datatype_size);
335 }
336 buf_list->allocate();
337
338 // Poste les receive.
339 for (Integer i = 0; i < nb_rank; ++i) {
340 Int32 rank = ranks[i];
341 MP::PointToPointMessageInfo msg_info(MP::MessageRank(rank), sync_info.message_tag, MP::eBlockingType::NonBlocking);
342 sync_info.requests.add(mpReceive(mpm, buf_list->receiveBuffer(i), msg_info));
343 }
344
345 // Copie les valeurs dans les buffers
346 for (Integer i = 0; i < nb_rank; ++i) {
347 ConstArrayView<MatVarIndex> shared_matcells(mmvs->sharedItems(i));
348 Integer total_shared = shared_matcells.size();
349 ByteArrayView values(buf_list->sendBuffer(i).smallView());
350 Integer offset = 0;
351 for (Integer z = 0; z < nb_var; ++z) {
352 Integer my_data_size = sync_info.data_sizes[z];
353 auto sub_view = values.subView(offset, total_shared * my_data_size);
354 if (use_new_version) {
355 auto* ptr = reinterpret_cast<std::byte*>(sub_view.data());
356 vars[z]->_internalApi()->copyToBuffer(shared_matcells, { ptr, sub_view.size() }, &queue);
357 }
358 else
359 vars[z]->copyToBuffer(shared_matcells, sub_view);
360 offset += total_shared * my_data_size;
361 }
362 }
363
364 // Attend que les copies soient terminées
365 queue.barrier();
366
367 // Poste les sends
368 for (Integer i = 0; i < nb_rank; ++i) {
369 Int32 rank = ranks[i];
370 MP::PointToPointMessageInfo msg_info(MP::MessageRank(rank), sync_info.message_tag, MP::eBlockingType::NonBlocking);
371 sync_info.requests.add(mpSend(mpm, buf_list->sendBuffer(i), msg_info));
372 }
373}
374
375/*---------------------------------------------------------------------------*/
376/*---------------------------------------------------------------------------*/
377
378void MeshMaterialVariableSynchronizerList::
379_endSynchronizeMultiple2(SyncInfo& sync_info)
380{
381 ConstArrayView<MeshMaterialVariable*> vars = sync_info.variables;
382 IMeshMaterialVariableSynchronizer* mmvs = sync_info.mat_synchronizer;
383 IVariableSynchronizer* var_syncer = mmvs->variableSynchronizer();
384 IParallelMng* pm = var_syncer->parallelMng();
385
386 if (!pm->isParallel())
387 return;
388 const bool use_new_version = sync_info.use_generic_version;
389 RunQueue queue = pm->_internalApi()->queue();
390 IMeshMaterialSynchronizeBuffer* buf_list = sync_info.buf_list.get();
391
392 Int32ConstArrayView ranks = var_syncer->communicatingRanks();
393 Int32 nb_rank = ranks.size();
394 Integer nb_var = vars.size();
395
396 pm->waitAllRequests(sync_info.requests);
397
398 // Recopie les données recues dans les mailles fantomes.
399 for (Integer i = 0; i < nb_rank; ++i) {
400 ConstArrayView<MatVarIndex> ghost_matcells(mmvs->ghostItems(i));
401 Integer total_ghost = ghost_matcells.size();
402 ByteConstArrayView values(buf_list->receiveBuffer(i).smallView());
403
404 Integer offset = 0;
405 for (Integer z = 0; z < nb_var; ++z) {
406 Integer my_data_size = sync_info.data_sizes[z];
407 auto sub_view = values.subView(offset, total_ghost * my_data_size);
408 if (use_new_version) {
409 auto* ptr = reinterpret_cast<const std::byte*>(sub_view.data());
410 vars[z]->_internalApi()->copyFromBuffer(ghost_matcells, { ptr, sub_view.size() }, &queue);
411 }
412 else
413 vars[z]->copyFromBuffer(ghost_matcells, sub_view);
414 offset += total_ghost * my_data_size;
415 }
416 }
417 sync_info.message_total_size += buf_list->totalSize();
418
419 // Attend que les copies soient terminées
420 queue.barrier();
421}
422
423/*---------------------------------------------------------------------------*/
424/*---------------------------------------------------------------------------*/
425
426} // End namespace Arcane::Materials
427
428/*---------------------------------------------------------------------------*/
429/*---------------------------------------------------------------------------*/
#define ARCANE_THROW(exception_class,...)
Macro pour envoyer une exception avec formattage.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Liste des fonctions d'échange de message.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
Classe template pour convertir un type.
virtual IMessagePassingMng * messagePassingMng() const =0
Gestionnaire de message de Arccore associé
virtual Int32ConstArrayView communicatingRanks()=0
Rangs des sous-domaines avec lesquels on communique.
virtual IParallelMng * parallelMng()=0
Gestionnaire parallèle associé
virtual IMeshMaterialVariableSynchronizer * allCellsEnvOnlySynchronizer()=0
Synchronizeur pour les variables uniquement milieux sur toutes les mailles.
virtual IMeshMaterialVariableSynchronizer * allCellsMatEnvSynchronizer()=0
Synchronizeur pour les variables matériaux et milieux sur toutes les mailles.
Interface du gestionnaire des matériaux et des milieux d'un maillage.
virtual Integer synchronizeVariableVersion() const =0
Version de l'implémentation pour la synchronisation des variables matériaux.
virtual IMeshMaterialMngInternal * _internalApi() const =0
API interne à Arcane.
Interface du synchroniseur de variables matériaux.
virtual IVariableSynchronizer * variableSynchronizer()=0
Synchroniseur des variables classiques associé.
virtual eMemoryRessource bufferMemoryRessource() const =0
Ressource mémoire à utiliser pour les buffers de communication.
virtual Ref< IMeshMaterialSynchronizeBuffer > commonBuffer()=0
Buffer commun pour les messages.
Int64 totalMessageSize() const
Après appel à apply(), contient la taille des messages envoyés.
void add(MeshMaterialVariable *var)
Ajoute la variable var à la liste des variables à synchroniser.
void endSynchronize()
Bloque tant que la synchronisation en cours n'est pas terminé.
Classe de base des variables matériaux.
String name() const override
Nom de la variable.
MatVarSpace space() const override
Espace de définition de la variable (matériau+milieu ou milieu uniquement)
Exception lorsqu'une opération n'est pas supportée.
Référence à une instance.
Vecteur 1D de données avec sémantique par valeur (style STL).
Active toujours les traces dans les parties Arcane concernant les matériaux.
MatVarSpace
Espace de définition d'une variable matériau.
@ Environment
Variable ayant des valeurs uniquement sur les milieux.
@ MaterialAndEnvironment
Variable ayant des valeurs sur les milieux et matériaux.
Request mpReceive(IMessagePassingMng *pm, ISerializer *values, const PointToPointMessageInfo &message)
Message de réception utilisant un ISerializer.
Definition Messages.cc:289
Request mpSend(IMessagePassingMng *pm, const ISerializer *values, const PointToPointMessageInfo &message)
Message d'envoi utilisant un ISerializer.
Definition Messages.cc:278
ArrayView< Byte > ByteArrayView
Equivalent C d'un tableau à une dimension de caractères.
Definition UtilsTypes.h:463
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
ConstArrayView< Int32 > Int32ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:498
Arcane::eMemoryResource eMemoryRessource
Typedef pour la version Arcane historique (avec 2's')
ConstArrayView< Byte > ByteConstArrayView
Equivalent C d'un tableau à une dimension de caractères.
Definition UtilsTypes.h:492
std::int32_t Int32
Type entier signé sur 32 bits.
Espace de nommage contenant les types et déclarations qui gèrent le mécanisme de parallélisme par éch...