Arcane  v3.16.0.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
MeshMaterialVariableSynchronizer.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/* MeshMaterialVariableSynchronizer.cc (C) 2000-2024 */
9/* */
10/* Synchroniseur de variables matériaux. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/materials/internal/MeshMaterialVariableSynchronizer.h"
15
16#include "arcane/utils/PlatformUtils.h"
18#include "arcane/utils/ValueConvert.h"
19
20#include "arcane/core/IMesh.h"
21#include "arcane/core/IVariableSynchronizer.h"
22#include "arcane/core/ItemGroup.h"
23#include "arcane/core/IParallelMng.h"
24#include "arcane/core/IItemFamily.h"
25#include "arcane/core/internal/IParallelMngInternal.h"
26
27#include "arcane/materials/IMeshMaterialMng.h"
28#include "arcane/materials/MatItemEnumerator.h"
29#include "arcane/materials/IMeshMaterialSynchronizeBuffer.h"
30#include "arcane/core/materials/internal/IMeshMaterialMngInternal.h"
31
32#include "arcane/accelerator/core/RunQueue.h"
33#include "arcane/accelerator/Scan.h"
34
35/*---------------------------------------------------------------------------*/
36/*---------------------------------------------------------------------------*/
37
38namespace Arcane::Materials
39{
40
41/*---------------------------------------------------------------------------*/
42/*---------------------------------------------------------------------------*/
43
44MeshMaterialVariableSynchronizer::
45MeshMaterialVariableSynchronizer(IMeshMaterialMng* material_mng,
46 IVariableSynchronizer* var_syncer,
47 MatVarSpace space)
48: TraceAccessor(material_mng->traceMng())
49, m_material_mng(material_mng)
50, m_variable_synchronizer(var_syncer)
51, m_timestamp(-1)
52, m_var_space(space)
53{
54 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_MATERIALSYNCHRONIZER_ACCELERATOR_MODE", true))
55 m_use_accelerator_mode = v.value();
56 _initialize();
57}
58
59/*---------------------------------------------------------------------------*/
60/*---------------------------------------------------------------------------*/
61
62/*---------------------------------------------------------------------------*/
63/*---------------------------------------------------------------------------*/
64
65IVariableSynchronizer* MeshMaterialVariableSynchronizer::
66variableSynchronizer()
67{
68 return m_variable_synchronizer;
69}
70
71/*---------------------------------------------------------------------------*/
72/*---------------------------------------------------------------------------*/
73
74ConstArrayView<MatVarIndex> MeshMaterialVariableSynchronizer::
75sharedItems(Int32 index)
76{
77 return m_shared_items[index];
78}
79
80/*---------------------------------------------------------------------------*/
81/*---------------------------------------------------------------------------*/
82
83ConstArrayView<MatVarIndex> MeshMaterialVariableSynchronizer::
84ghostItems(Int32 index)
85{
86 return m_ghost_items[index];
87}
88
89/*---------------------------------------------------------------------------*/
90/*---------------------------------------------------------------------------*/
95void MeshMaterialVariableSynchronizer::
96_fillCells(Array<MatVarIndex>& items, AllEnvCellVectorView view, RunQueue& queue)
97{
98 items.clear();
99
100 // NOTE: il est possible d'optimiser en regardant les milieux qui n'ont
101 // qu'un seul matériau car dans ce cas la valeur milieu et la valeur
102 // matériau est la même. De la même manière, s'il n'y a qu'un milieu
103 // alors la valeur globale et milieu est la même. Dans ces cas, il n'est
104 // pas nécessaire d'ajouter la deuxième MatCell dans la liste.
105 // So on fait cette optimisation, il faudra alors modifier la sérialisation
106 // correspondante pour les variables
107 if (view.size() == 0)
108 return;
109
110 bool use_accelerator = queue.isAcceleratorPolicy();
111 if (m_use_accelerator_mode == 1)
112 use_accelerator = true;
113 if (m_use_accelerator_mode == 0)
114 use_accelerator = false;
115
116 if (use_accelerator)
117 _fillCellsAccelerator(items, view, queue);
118 else
119 _fillCellsSequential(items, view);
120}
121
122/*---------------------------------------------------------------------------*/
123/*---------------------------------------------------------------------------*/
128void MeshMaterialVariableSynchronizer::
129_fillCellsSequential(Array<MatVarIndex>& items, AllEnvCellVectorView view)
130{
131 bool has_mat = m_var_space == MatVarSpace::MaterialAndEnvironment;
132
133 ENUMERATE_ALLENVCELL (iallenvcell, view) {
134 AllEnvCell all_env_cell = *iallenvcell;
135 for (EnvCell env_cell : all_env_cell.subEnvItems()) {
136 items.add(env_cell._varIndex());
137 if (has_mat) {
138 for (MatCell mat_cell : env_cell.subMatItems()) {
139 items.add(mat_cell._varIndex());
140 }
141 }
142 }
143 // A priori ajouter cette information n'est pas nécessaire car il
144 // est possible de récupérer l'info de la variable globale.
145 items.add(MatVarIndex(0, view.localId(iallenvcell.index())));
146 }
147}
148
149/*---------------------------------------------------------------------------*/
150/*---------------------------------------------------------------------------*/
155void MeshMaterialVariableSynchronizer::
156_fillCellsAccelerator(Array<MatVarIndex>& items, AllEnvCellVectorView view, RunQueue& queue)
157{
158 bool has_mat = m_var_space == MatVarSpace::MaterialAndEnvironment;
159 // Fais un Scan pour connaitre l'index de chaque élément et le nombre total
160 // La tableau a (nb_item+1) éléments et la dernière valeur contiendra le
161 // nombre total d'éléments de la liste
162 Int32 nb_item = view.size();
163 UniqueArray<Int32> indexes(queue.allocationOptions());
164 indexes.resize(nb_item + 1);
165
166 Accelerator::GenericScanner scanner(queue);
167 Accelerator::ScannerSumOperator<Int32> op;
168 Span<Int32> out_indexes = indexes;
169 auto getter = [=] ARCCORE_HOST_DEVICE(Int32 index) -> Int32 {
170 if (index == nb_item)
171 return 0;
172 AllEnvCell all_env_cell = view[index];
173 Int32 n = 0;
174 for (EnvCell env_cell : all_env_cell.subEnvItems()) {
175 ++n;
176 if (has_mat)
177 n += env_cell.nbSubItem();
178 }
179 ++n;
180 return n;
181 };
182
183 {
184 // Tableau pour conserver la somme finale
185 NumArray<Int32, MDDim1> host_total_storage(1, eMemoryRessource::HostPinned);
186 SmallSpan<Int32> in_host_total_storage(host_total_storage);
187
188 auto setter = [=] ARCCORE_HOST_DEVICE(Int32 index, Int32 value) {
189 out_indexes[index] = value;
190 if (index == nb_item)
191 in_host_total_storage[0] = value;
192 };
193 scanner.applyWithIndexExclusive(nb_item + 1, 0, getter, setter, op);
194 Int32 total = host_total_storage[0]; //indexes[nb_item];
195 items.resize(total);
196 }
197
198 {
199 auto command = makeCommand(queue);
200 Span<const Int32> in_indexes = indexes;
201 Span<MatVarIndex> out_mat_var_indexes = items;
202 command << RUNCOMMAND_LOOP1(iter, nb_item)
203 {
204 auto [index] = iter();
205 AllEnvCell all_env_cell = view[index];
206 Int32 pos = in_indexes[index];
207 for (EnvCell env_cell : all_env_cell.subEnvItems()) {
208 out_mat_var_indexes[pos] = env_cell._varIndex();
209 ++pos;
210 if (has_mat) {
211 for (MatCell mat_cell : env_cell.subMatItems()) {
212 out_mat_var_indexes[pos] = mat_cell._varIndex();
213 ++pos;
214 }
215 }
216 }
217 // A priori ajouter cette information n'est pas nécessaire car il
218 // est possible de récupérer l'info de la variable globale.
219 out_mat_var_indexes[pos] = MatVarIndex(0, view.localId(index));
220 };
221 }
222}
223
224/*---------------------------------------------------------------------------*/
225/*---------------------------------------------------------------------------*/
226
227void MeshMaterialVariableSynchronizer::
228checkRecompute()
229{
230 Int64 ts = m_material_mng->timestamp();
231 if (m_timestamp != ts)
232 recompute();
233 m_timestamp = ts;
234}
235
236/*---------------------------------------------------------------------------*/
237/*---------------------------------------------------------------------------*/
238
239void MeshMaterialVariableSynchronizer::
240recompute()
241{
242 IVariableSynchronizer* var_syncer = m_variable_synchronizer;
243
244 // Calcul des informations de synchronisation pour les mailles matériaux.
245 // NOTE: Cette version nécessite que les matériaux soient correctement
246 // synchronisés entre les sous-domaines.
247
248 IItemFamily* family = var_syncer->itemGroup().itemFamily();
249 IParallelMng* pm = var_syncer->parallelMng();
250 if (!pm->isParallel())
251 return;
252 ItemGroup all_items = family->allItems();
253
254 Int32ConstArrayView ranks = var_syncer->communicatingRanks();
255 Integer nb_rank = ranks.size();
256
257 m_common_buffer->setNbRank(nb_rank);
258
259 m_shared_items.resize(nb_rank);
260 m_ghost_items.resize(nb_rank);
261
262 RunQueue queue = m_material_mng->_internalApi()->runQueue();
263
264 {
265 // Ces tableaux doivent être accessibles sur l'accélérateur
266 // TODO: à terme, n'utiliser un seul tableau pour les envois
267 // et un seul pour les réceptions.
269 for (Int32 i = 0; i < nb_rank; ++i) {
270 m_shared_items[i] = UniqueArray<MatVarIndex>(a);
271 m_ghost_items[i] = UniqueArray<MatVarIndex>(a);
272 }
273 }
274
275 // NOTE: les appels à _fillCells() sont indépendants. On pourrait
276 // donc les rendre asynchrones.
277 for (Integer i = 0; i < nb_rank; ++i) {
278
279 {
280 Int32ConstArrayView shared_ids = var_syncer->sharedItems(i);
281 CellVectorView shared_cells(family->view(shared_ids));
282 AllEnvCellVectorView view = m_material_mng->view(shared_cells);
283 Array<MatVarIndex>& items = m_shared_items[i];
284 _fillCells(items, view, queue);
285 info(4) << "SIZE SHARED FOR rank=" << ranks[i] << " n=" << items.size();
286 }
287
288 {
289 Int32ConstArrayView ghost_ids = var_syncer->ghostItems(i);
290 CellVectorView ghost_cells(family->view(ghost_ids));
291 AllEnvCellVectorView view = m_material_mng->view(ghost_cells);
292 Array<MatVarIndex>& items = m_ghost_items[i];
293 _fillCells(items, view, queue);
294 info(4) << "SIZE GHOST FOR rank=" << ranks[i] << " n=" << items.size();
295 }
296 }
297}
298
299/*---------------------------------------------------------------------------*/
300/*---------------------------------------------------------------------------*/
301
302void MeshMaterialVariableSynchronizer::
303_initialize()
304{
305 IParallelMng* pm = m_variable_synchronizer->parallelMng();
306 if (pm->_internalApi()->isAcceleratorAware()) {
307 m_buffer_memory_ressource = eMemoryRessource::Device;
308 info() << "MeshMaterialVariableSynchronizer: Using device memory for buffer";
309 }
310 m_common_buffer = impl::makeOneBufferMeshMaterialSynchronizeBufferRef(m_buffer_memory_ressource);
311}
312
313/*---------------------------------------------------------------------------*/
314/*---------------------------------------------------------------------------*/
315
316} // End namespace Arcane::Materials
317
318/*---------------------------------------------------------------------------*/
319/*---------------------------------------------------------------------------*/
Fonctions de gestion mémoire et des allocateurs.
#define RUNCOMMAND_LOOP1(iter_name, x1,...)
Boucle sur accélérateur avec arguments supplémentaires pour les réductions.
Integer size() const
Nombre d'éléments du vecteur.
Algorithmes de scan exclusif ou inclusif sur accélérateurs.
File d'exécution pour un accélérateur.
MemoryAllocationOptions allocationOptions() const
Options d'allocation associée à cette file.
Definition RunQueue.cc:340
bool isAcceleratorPolicy() const
Indique si l'instance est associée à un accélérateur.
Definition RunQueue.cc:331
Tableau d'items de types quelconques.
void clear()
Supprime les éléments du tableau.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
Vue constante d'un tableau de type T.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
Interface d'une famille d'entités.
Definition IItemFamily.h:84
virtual ItemGroup allItems() const =0
Groupe de toutes les entités.
virtual ItemVectorView view(Int32ConstArrayView local_ids)=0
Vue sur les entités.
virtual bool isAcceleratorAware() const =0
Indique si l'implémentation gère les accélérateurs.
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual IParallelMngInternal * _internalApi()=0
API interne à Arcane.
virtual bool isParallel() const =0
Retourne true si l'exécution est parallèle.
Interface d'un service de synchronisation de variable.
virtual Int32ConstArrayView ghostItems(Int32 index)=0
Liste des ids locaux des entités fantômes avec un sous-domaine.
virtual Int32ConstArrayView communicatingRanks()=0
Rangs des sous-domaines avec lesquels on communique.
virtual const ItemGroup & itemGroup()=0
Groupe d'entité servant à la synchronisation.
virtual IParallelMng * parallelMng()=0
Gestionnaire parallèle associé
virtual Int32ConstArrayView sharedItems(Int32 index)=0
Liste des ids locaux des entités partagées avec un sous-domaine.
Groupe d'entités de maillage.
Definition ItemGroup.h:49
IItemFamily * itemFamily() const
Famille d'entité à laquelle appartient ce groupe (0 pour le group nul)
Definition ItemGroup.h:123
Vue sur une liste de mailles avec infos sur les milieux.
constexpr __host__ __device__ Integer size() const
Nombre d'éléments.
Maille arcane avec info matériaux et milieux.
__host__ __device__ CellEnvCellEnumerator subEnvItems() const
Enumérateur sur les mailles milieux de cette maille.
Maille arcane d'un milieu.
Interface du gestionnaire des matériaux et des milieux d'un maillage.
Représente un matériau d'une maille multi-matériau.
Représente un index sur les variables matériaux et milieux.
void _fillCellsAccelerator(Array< MatVarIndex > &items, AllEnvCellVectorView view, RunQueue &queue)
Remplit items avec la liste de tous les MatVarIndex des mailles de view.
void _fillCells(Array< MatVarIndex > &items, AllEnvCellVectorView view, RunQueue &queue)
Remplit items avec la liste de tous les MatVarIndex des mailles de view.
void recompute() override
Recalcule les infos de synchronisation.
void _fillCellsSequential(Array< MatVarIndex > &items, AllEnvCellVectorView view)
Remplit items avec la liste de tous les MatVarIndex des mailles de view.
Options pour configurer les allocations.
Tableaux multi-dimensionnels pour les types numériques accessibles sur accélérateurs.
Vue d'un tableau d'éléments de type T.
Definition Span.h:673
Vue d'un tableau d'éléments de type T.
Definition Span.h:513
TraceMessage info() const
Flot pour un message d'information.
Vecteur 1D de données avec sémantique par valeur (style STL).
#define ENUMERATE_ALLENVCELL(iname,...)
Macro pour itérer sur toutes les mailles AllEnvCell d'un groupe.
ItemVectorViewT< Cell > CellVectorView
Vue sur un vecteur de mailles.
Definition ItemTypes.h:304
RunCommand makeCommand(const RunQueue &run_queue)
Créé une commande associée à la file run_queue.
Active toujours les traces dans les parties Arcane concernant les matériaux.
MatVarSpace
Espace de définition d'une variable matériau.
@ MaterialAndEnvironment
Variable ayant des valeurs sur les milieux et matériaux.
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:569
std::int32_t Int32
Type entier signé sur 32 bits.