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