Arcane  4.1.12.0
User documentation
Loading...
Searching...
No Matches
MeshMaterialVariableSynchronizer.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 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/* Material variable synchronizer. */
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/*---------------------------------------------------------------------------*/
91
92/*!
93 * \brief Fills \a items with the list of all MatVarIndex from the cells of \a view.
94 */
95void MeshMaterialVariableSynchronizer::
96_fillCells(Array<MatVarIndex>& items, AllEnvCellVectorView view, RunQueue& queue)
97{
98 items.clear();
99
100 // NOTE: It is possible to optimize by looking at elements that have
101 // only one material, because in that case the element value and the
102 // material value are the same. Similarly, if there is only one element,
103 // then the global value and the element value are the same. In these
104 // cases, it is not necessary to add the second MatCell to the list.
105 // If we implement this optimization, we will then need to modify the
106 // corresponding serialization for the 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/*!
126 * \brief Fills \a items with the list of all MatVarIndex from the cells of \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 // In principle, adding this information is not necessary because it
144 // is possible to retrieve the global variable info.
145 items.add(MatVarIndex(0, view.localId(iallenvcell.index())));
146 }
147}
148
149/*---------------------------------------------------------------------------*/
150/*---------------------------------------------------------------------------*/
151
152/*!
153 * \brief Fills \a items with the list of all MatVarIndex from the cells of \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 // Perform a Scan to know the index of each element and the total number
160 // The array has (nb_item+1) elements and the last value will contain the
161 // total number of elements in the list
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 // Array to store the final sum
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 // In principle, adding this information is not necessary because it
218 // is possible to retrieve the global variable info.
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 // Calculation of synchronization information for material cells.
245 // NOTE: This version requires that the materials are correctly
246 // synchronized between sub-domains.
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 // These arrays must be accessible on the accelerator
266 // TODO: eventually, use a single array for sends
267 // and a single one for receives.
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: The calls to _fillCells() are independent. We could
276 // therefore make them asynchronous.
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/*---------------------------------------------------------------------------*/
Memory and allocator management functions.
#define RUNCOMMAND_LOOP1(iter_name, x1,...)
1D loop on accelerator with additional arguments.
Interface for the material and environment manager of a mesh.
#define ENUMERATE_ALLENVCELL(iname,...)
Macro to iterate over all AllEnvCell cells of a group.
ItemVectorViewT< Cell > CellVectorView
View over a vector of cells.
Definition ItemTypes.h:305
RunCommand makeCommand(const RunQueue &run_queue)
Creates a command associated with the queue run_queue.
Always enables tracing in Arcane parts concerning materials.
MatVarSpace
Definition space for a material variable.
Int32 Integer
Type representing an integer.
ConstArrayView< Int32 > Int32ConstArrayView
C equivalent of a 1D array of 32-bit integers.
Definition UtilsTypes.h:482