Arcane  v3.14.10.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-2023 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-2023 */
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
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
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{
256 eMemoryRessource mem = mmvs->bufferMemoryRessource();
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) {
272 Int32ConstArrayView ranks = mmvs->variableSynchronizer()->communicatingRanks();
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()->defaultQueue();
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 if (queue)
367 queue->barrier();
368
369 // Poste les sends
370 for (Integer i = 0; i < nb_rank; ++i) {
371 Int32 rank = ranks[i];
372 MP::PointToPointMessageInfo msg_info(MP::MessageRank(rank), sync_info.message_tag, MP::eBlockingType::NonBlocking);
373 sync_info.requests.add(mpSend(mpm, buf_list->sendBuffer(i), msg_info));
374 }
375}
376
377/*---------------------------------------------------------------------------*/
378/*---------------------------------------------------------------------------*/
379
380void MeshMaterialVariableSynchronizerList::
381_endSynchronizeMultiple2(SyncInfo& sync_info)
382{
383 ConstArrayView<MeshMaterialVariable*> vars = sync_info.variables;
384 IMeshMaterialVariableSynchronizer* mmvs = sync_info.mat_synchronizer;
385 IVariableSynchronizer* var_syncer = mmvs->variableSynchronizer();
386 IParallelMng* pm = var_syncer->parallelMng();
387
388 if (!pm->isParallel())
389 return;
390 const bool use_new_version = sync_info.use_generic_version;
391 RunQueue* queue = pm->_internalApi()->defaultQueue();
392 IMeshMaterialSynchronizeBuffer* buf_list = sync_info.buf_list.get();
393
394 Int32ConstArrayView ranks = var_syncer->communicatingRanks();
395 Int32 nb_rank = ranks.size();
396 Integer nb_var = vars.size();
397
398 pm->waitAllRequests(sync_info.requests);
399
400 // Recopie les données recues dans les mailles fantomes.
401 for (Integer i = 0; i < nb_rank; ++i) {
402 ConstArrayView<MatVarIndex> ghost_matcells(mmvs->ghostItems(i));
403 Integer total_ghost = ghost_matcells.size();
404 ByteConstArrayView values(buf_list->receiveBuffer(i).smallView());
405
406 Integer offset = 0;
407 for (Integer z = 0; z < nb_var; ++z) {
408 Integer my_data_size = sync_info.data_sizes[z];
409 auto sub_view = values.subView(offset, total_ghost * my_data_size);
410 if (use_new_version) {
411 auto* ptr = reinterpret_cast<const std::byte*>(sub_view.data());
412 vars[z]->_internalApi()->copyFromBuffer(ghost_matcells, { ptr, sub_view.size() }, queue);
413 }
414 else
415 vars[z]->copyFromBuffer(ghost_matcells, sub_view);
416 offset += total_ghost * my_data_size;
417 }
418 }
419 sync_info.message_total_size += buf_list->totalSize();
420
421 // Attend que les copies soient terminées
422 if (queue)
423 queue->barrier();
424}
425
426/*---------------------------------------------------------------------------*/
427/*---------------------------------------------------------------------------*/
428
429} // End namespace Arcane::Materials
430
431/*---------------------------------------------------------------------------*/
432/*---------------------------------------------------------------------------*/
#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 ITraceMng * traceMng() const =0
Gestionnaire de traces.
virtual void waitAllRequests(ArrayView< Request > rvalues)=0
Bloque en attendant que les requêtes rvalues soient terminées.
virtual IMessagePassingMng * messagePassingMng() const =0
Gestionnaire de message de Arccore associé
virtual IParallelMngInternal * _internalApi()=0
API interne à Arcane.
virtual bool isParallel() const =0
Retourne true si l'exécution est parallèle.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
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é.
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.
Informations pour envoyer/recevoir un message point à point.
Exception lorsqu'une opération n'est pas supportée.
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.
eMemoryRessource
Liste des ressources mémoire disponibles.
@ Host
Alloue sur l'hôte.
ConstArrayView< Int32 > Int32ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:640
ConstArrayView< Byte > ByteConstArrayView
Equivalent C d'un tableau à une dimension de caractères.
Definition UtilsTypes.h:634
ArrayView< Byte > ByteArrayView
Equivalent C d'un tableau à une dimension de caractères.
Definition UtilsTypes.h:605
Espace de nommage contenant les types et déclarations qui gèrent le mécanisme de parallélisme par éch...
Request mpSend(IMessagePassingMng *pm, const ISerializer *values, const PointToPointMessageInfo &message)
Message d'envoi utilisant un ISerializer.
Definition Messages.cc:266
Request mpReceive(IMessagePassingMng *pm, ISerializer *values, const PointToPointMessageInfo &message)
Message de réception utilisant un ISerializer.
Definition Messages.cc:277
Int32 Integer
Type représentant un entier.