Arcane  v3.14.10.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-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
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()->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 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.
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.