Arcane  v3.14.10.0
Documentation utilisateur
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"
17#include "arcane/utils/MemoryUtils.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/*---------------------------------------------------------------------------*/
91/*!
92 * \brief Remplit \a items avec la liste de tous les MatVarIndex des
93 * mailles de \a view.
94 */
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/*---------------------------------------------------------------------------*/
124/*!
125 * \brief Remplit \a items avec la liste de tous les MatVarIndex des
126 * mailles de \a view.
127 */
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/*---------------------------------------------------------------------------*/
151/*!
152 * \brief Remplit \a items avec la liste de tous les MatVarIndex des
153 * mailles de \a view.
154 */
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.
268 MemoryAllocationOptions a = queue.allocationOptions();
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/*---------------------------------------------------------------------------*/
#define RUNCOMMAND_LOOP1(iter_name, x1,...)
Boucle sur accélérateur avec arguments supplémentaires pour les réductions.
MemoryAllocationOptions allocationOptions() const
Options d'allocation associée à cette file.
Definition RunQueue.cc:333
#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.
ConstArrayView< Int32 > Int32ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:640
Int32 Integer
Type représentant un entier.