Arcane  4.1.12.0
Developer 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
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
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
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.
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.
Integer size() const
Number of elements in the vector.
Exclusive or inclusive scan algorithms on accelerators.
MemoryAllocationOptions allocationOptions() const
Allocation options associated with this queue.
Definition RunQueue.cc:340
bool isAcceleratorPolicy() const
Indicates if the instance is associated with an accelerator.
Definition RunQueue.cc:331
Base class for 1D data vectors.
void resize(Int64 s)
Changes the number of elements in the array to s.
void clear()
Removes the elements from the array.
void add(ConstReferenceType val)
Adds element val to the end of the array.
Constant view of an array of type T.
constexpr Integer size() const noexcept
Number of elements in the array.
Interface of an entity family.
Definition IItemFamily.h:83
virtual ItemGroup allItems() const =0
Group of all entities.
virtual ItemVectorView view(Int32ConstArrayView local_ids)=0
View on the entities.
virtual bool isAcceleratorAware() const =0
Indicates if the implementation handles accelerators.
Interface of the parallelism manager for a subdomain.
virtual IParallelMngInternal * _internalApi()=0
Internal Arcane API.
virtual bool isParallel() const =0
Returns true if the execution is parallel.
Interface of a variable synchronization service.
virtual Int32ConstArrayView ghostItems(Int32 index)=0
List of local IDs of ghost entities with a subdomain.
virtual Int32ConstArrayView communicatingRanks()=0
Ranks of subdomains with which communication occurs.
virtual const ItemGroup & itemGroup()=0
Entity group used for synchronization.
virtual IParallelMng * parallelMng()=0
Associated parallel manager.
virtual Int32ConstArrayView sharedItems(Int32 index)=0
List of local IDs of entities shared with a subdomain.
Mesh entity group.
Definition ItemGroup.h:51
IItemFamily * itemFamily() const
Entity family to which this group belongs (0 for the null group).
Definition ItemGroup.h:128
View over a list of cells with environment information.
constexpr __host__ __device__ Integer size() const
Number of elements.
Arcane cell with material and environment information.
__host__ __device__ CellEnvCellEnumerator subEnvItems() const
Enumerator over the environment cells of this cell.
Arcane cell of an environment.
Interface for the material and environment manager of a mesh.
Represents a material in a multi-material cell.
Represents an index on material and environment variables.
void _fillCellsAccelerator(Array< MatVarIndex > &items, AllEnvCellVectorView view, RunQueue &queue)
Fills items with the list of all MatVarIndex from the cells of view.
void _fillCells(Array< MatVarIndex > &items, AllEnvCellVectorView view, RunQueue &queue)
Fills items with the list of all MatVarIndex from the cells of view.
void recompute() override
Recalculates synchronization information.
void _fillCellsSequential(Array< MatVarIndex > &items, AllEnvCellVectorView view)
Fills items with the list of all MatVarIndex from the cells of view.
Multi-dimensional arrays for numerical types accessible on accelerators.
View of an array of elements of type T.
Definition Span.h:805
View of an array of elements of type T.
Definition Span.h:635
TraceMessage info() const
Flow for an information message.
1D data vector with value semantics (STL style).
#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.
@ MaterialAndEnvironment
Variable having values on environments and materials.
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
ConstArrayView< Int32 > Int32ConstArrayView
C equivalent of a 1D array of 32-bit integers.
Definition UtilsTypes.h:482
std::int32_t Int32
Signed integer type of 32 bits.