Arcane  4.1.12.0
User documentation
Loading...
Searching...
No Matches
MeshMaterialVariableSynchronizerList.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/* MeshMaterialVariableSynchronizerList.cc (C) 2000-2025 */
9/* */
10/* Material variable synchronizer. */
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/FatalErrorException.h"
20
21#include "arcane/core/IParallelMng.h"
22#include "arcane/core/IVariableSynchronizer.h"
23#include "arcane/core/internal/IParallelMngInternal.h"
24#include "arcane/core/materials/IMeshMaterialMng.h"
25#include "arcane/core/materials/internal/IMeshMaterialVariableInternal.h"
26#include "arcane/core/materials/internal/IMeshMaterialMngInternal.h"
27
28#include "arcane/materials/MeshMaterialVariable.h"
29#include "arcane/materials/IMeshMaterialSynchronizeBuffer.h"
30#include "arcane/materials/IMeshMaterialVariableSynchronizer.h"
31
32#include "arcane/accelerator/core/RunQueue.h"
33
35
36/*---------------------------------------------------------------------------*/
37/*---------------------------------------------------------------------------*/
38
39namespace Arcane::Materials
40{
41namespace MP = Arccore::MessagePassing;
42
43/*---------------------------------------------------------------------------*/
44/*---------------------------------------------------------------------------*/
45
47{
48 public:
49
52 UniqueArray<Int32> data_sizes;
53 bool use_generic_version = false;
54 Int32 sync_version = 0;
55 IMeshMaterialVariableSynchronizer* mat_synchronizer = nullptr;
56 Int64 message_total_size = 0;
58 MP::MessageTag message_tag;
59};
60
61/*---------------------------------------------------------------------------*/
62/*---------------------------------------------------------------------------*/
63
65{
66 public:
67
68 explicit Impl(IMeshMaterialMng* material_mng)
69 : m_material_mng(material_mng)
70 {
71 // To use the old (pre-accelerator version) synchronization mechanism.
72 // TEMPORARY: to be removed at the end of 2023.
73 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_MATERIAL_LEGACY_SYNCHRONIZE", true))
74 m_use_generic_version = (v.value() == 0);
75 }
76
77 public:
78
79 IMeshMaterialMng* m_material_mng;
82 Int64 m_total_size = 0;
83 bool m_use_generic_version = true;
84 eMemoryRessource m_buffer_memory_ressource = eMemoryRessource::Host;
85 SyncInfo m_mat_env_sync_info;
86 SyncInfo m_env_only_sync_info;
87 bool m_is_in_sync = false;
88};
89
90/*---------------------------------------------------------------------------*/
91/*---------------------------------------------------------------------------*/
92
93MeshMaterialVariableSynchronizerList::
94MeshMaterialVariableSynchronizerList(IMeshMaterialMng* material_mng)
95: m_p(new Impl(material_mng))
96{
97}
98
99/*---------------------------------------------------------------------------*/
100/*---------------------------------------------------------------------------*/
101
102MeshMaterialVariableSynchronizerList::
103~MeshMaterialVariableSynchronizerList()
104{
105 delete m_p;
106}
107
108/*---------------------------------------------------------------------------*/
109/*---------------------------------------------------------------------------*/
110
112totalMessageSize() const
113{
114 return m_p->m_total_size;
115}
116
117/*---------------------------------------------------------------------------*/
118/*---------------------------------------------------------------------------*/
119
121apply()
122{
123 // With synchronization version 8, it is mandatory that each synchronization
124 // is blocking because there is only one shared buffer.
125 Int32 v = m_p->m_material_mng->synchronizeVariableVersion();
126 bool is_blocking = (v == 8);
127
128 _beginSynchronize(is_blocking);
129 _endSynchronize(is_blocking);
130}
131
132/*---------------------------------------------------------------------------*/
133/*---------------------------------------------------------------------------*/
134
137{
138 Int32 v = m_p->m_material_mng->synchronizeVariableVersion();
139 if (v != 7)
140 ARCANE_FATAL("beginSynchronize() is only valid for synchronize version 7 (v={0})", v);
141 _beginSynchronize(false);
142}
143
144/*---------------------------------------------------------------------------*/
145/*---------------------------------------------------------------------------*/
146
149{
150 _endSynchronize(false);
151}
152
153/*---------------------------------------------------------------------------*/
154/*---------------------------------------------------------------------------*/
155
156void MeshMaterialVariableSynchronizerList::
157_beginSynchronize(bool is_blocking)
158{
159 if (m_p->m_is_in_sync)
160 ARCANE_FATAL("Already synchronizing");
161 m_p->m_is_in_sync = true;
162
163 m_p->m_total_size = 0;
164 // TODO: modify the synchronizer to do this in a single pass
165 // of send/recv/wait.
166 IMeshMaterialMng* mm = m_p->m_material_mng;
167 m_p->m_mat_env_sync_info = SyncInfo();
168 m_p->m_env_only_sync_info = SyncInfo();
169
170 {
171 SyncInfo& sync_info = m_p->m_mat_env_sync_info;
172 _fillSyncInfo(sync_info);
173 sync_info.mat_synchronizer = mm->_internalApi()->allCellsMatEnvSynchronizer();
174 sync_info.variables = m_p->m_mat_env_vars;
175 sync_info.message_tag = MP::MessageTag(569);
176 if (!sync_info.variables.empty()) {
177 _beginSynchronizeMultiple(sync_info);
178 if (is_blocking)
179 _endSynchronizeMultiple2(sync_info);
180 }
181 }
182 {
183 SyncInfo& sync_info = m_p->m_env_only_sync_info;
184 _fillSyncInfo(sync_info);
185 sync_info.mat_synchronizer = mm->_internalApi()->allCellsEnvOnlySynchronizer();
186 sync_info.variables = m_p->m_env_only_vars;
187 sync_info.message_tag = MP::MessageTag(585);
188 if (!sync_info.variables.empty()) {
189 _beginSynchronizeMultiple(sync_info);
190 if (is_blocking)
191 _endSynchronizeMultiple2(sync_info);
192 }
193 }
194}
195
196/*---------------------------------------------------------------------------*/
197/*---------------------------------------------------------------------------*/
198
199void MeshMaterialVariableSynchronizerList::
200_endSynchronize(bool is_blocking)
201{
202 if (!m_p->m_is_in_sync)
203 ARCANE_FATAL("beginSynchronize() has to be called before endSynchronize()");
204
205 {
206 SyncInfo& sync_info = m_p->m_mat_env_sync_info;
207 if (!sync_info.variables.empty() && !is_blocking)
208 _endSynchronizeMultiple2(sync_info);
209 m_p->m_total_size += sync_info.message_total_size;
210 }
211 {
212 SyncInfo& sync_info = m_p->m_env_only_sync_info;
213 if (!sync_info.variables.empty() && !is_blocking)
214 _endSynchronizeMultiple2(sync_info);
215 m_p->m_total_size += sync_info.message_total_size;
216 }
217
218 m_p->m_is_in_sync = false;
219}
220
221/*---------------------------------------------------------------------------*/
222/*---------------------------------------------------------------------------*/
223
226{
227 MatVarSpace mvs = var->space();
229 m_p->m_mat_env_vars.add(var);
230 else if (mvs == MatVarSpace::Environment)
231 m_p->m_env_only_vars.add(var);
232 else
233 ARCANE_THROW(NotSupportedException, "Invalid space for variable name={0} space={1}",
234 var->name(), (int)mvs);
235}
236
237/*---------------------------------------------------------------------------*/
238/*---------------------------------------------------------------------------*/
239
240void MeshMaterialVariableSynchronizerList::
241_fillSyncInfo(SyncInfo& sync_info)
242{
243 sync_info.use_generic_version = m_p->m_use_generic_version;
244 sync_info.sync_version = m_p->m_material_mng->synchronizeVariableVersion();
245}
246
247/*---------------------------------------------------------------------------*/
248/*---------------------------------------------------------------------------*/
249
250void MeshMaterialVariableSynchronizerList::
251_beginSynchronizeMultiple(SyncInfo& sync_info)
252{
253 IMeshMaterialVariableSynchronizer* mmvs = sync_info.mat_synchronizer;
255 const Int32 sync_version = sync_info.sync_version;
256
257 if (sync_version == 8) {
258 // Version 8. Use the common buffer to avoid multiple allocations
259 sync_info.buf_list = mmvs->commonBuffer();
260 }
261 else if (sync_version == 7) {
262 // Version 7. Uses a single buffer, but reallocated each time.
263 sync_info.buf_list = impl::makeOneBufferMeshMaterialSynchronizeBufferRef(mem);
264 }
265 else {
266 // Version 6. Historical version with multiple buffers recreated each time.
267 sync_info.buf_list = impl::makeMultiBufferMeshMaterialSynchronizeBufferRef(mem);
268 }
269 if (sync_version < 8) {
271 Integer nb_rank = ranks.size();
272 sync_info.buf_list->setNbRank(nb_rank);
273 }
274
275 _beginSynchronizeMultiple2(sync_info);
276}
277
278/*---------------------------------------------------------------------------*/
279/*---------------------------------------------------------------------------*/
280
281void MeshMaterialVariableSynchronizerList::
282_beginSynchronizeMultiple2(SyncInfo& sync_info)
283{
284 ConstArrayView<MeshMaterialVariable*> vars = sync_info.variables;
285 IMeshMaterialSynchronizeBuffer* buf_list = sync_info.buf_list.get();
286 IMeshMaterialVariableSynchronizer* mmvs = sync_info.mat_synchronizer;
287 // Synchronization version that only sends material and environment values
288 // for shared cells.
289 // NOTE: This version requires that materials are correctly synchronized
290 // between sub-domains.
291
292 IVariableSynchronizer* var_syncer = mmvs->variableSynchronizer();
293 IParallelMng* pm = var_syncer->parallelMng();
294 IMessagePassingMng* mpm = pm->messagePassingMng();
295
296 // TODO: handle the alignment of multiple buffers.
297
298 // TODO: add a tag to ensure that the synchs are on the same variables.
299
300 if (!pm->isParallel())
301 return;
302 const bool use_new_version = sync_info.use_generic_version;
303 RunQueue queue = pm->_internalApi()->queue();
304
305 mmvs->checkRecompute();
306
307 ITraceMng* tm = pm->traceMng();
308 Integer nb_var = vars.size();
309 tm->info(4) << "MAT_SYNCHRONIZE version=" << sync_info.sync_version << " multiple n="
310 << nb_var << " is_generic?=" << use_new_version;
311
312 sync_info.data_sizes.resize(nb_var);
313 Integer all_datatype_size = 0;
314 for (Integer i = 0; i < nb_var; ++i) {
315 sync_info.data_sizes[i] = vars[i]->dataTypeSize();
316 all_datatype_size += sync_info.data_sizes[i];
317 tm->info(4) << "MAT_SYNCHRONIZE name=" << vars[i]->name()
318 << " size=" << sync_info.data_sizes[i];
319 }
320
321 Int32ConstArrayView ranks = var_syncer->communicatingRanks();
322 Int32 nb_rank = ranks.size();
323
324 // Calculate buffer sizes and reallocate if necessary
325 for (Integer i = 0; i < nb_rank; ++i) {
326 ConstArrayView<MatVarIndex> ghost_matcells(mmvs->ghostItems(i));
327 Integer total_ghost = ghost_matcells.size();
328 buf_list->setReceiveBufferSize(i, total_ghost * all_datatype_size);
329 ConstArrayView<MatVarIndex> shared_matcells(mmvs->sharedItems(i));
330 Integer total_shared = shared_matcells.size();
331 buf_list->setSendBufferSize(i, total_shared * all_datatype_size);
332 }
333 buf_list->allocate();
334
335 // Post the receives.
336 for (Integer i = 0; i < nb_rank; ++i) {
337 Int32 rank = ranks[i];
338 MP::PointToPointMessageInfo msg_info(MP::MessageRank(rank), sync_info.message_tag, MP::eBlockingType::NonBlocking);
339 sync_info.requests.add(mpReceive(mpm, buf_list->receiveBuffer(i), msg_info));
340 }
341
342 // Copy values into the buffers
343 for (Integer i = 0; i < nb_rank; ++i) {
344 ConstArrayView<MatVarIndex> shared_matcells(mmvs->sharedItems(i));
345 Integer total_shared = shared_matcells.size();
346 ByteArrayView values(buf_list->sendBuffer(i).smallView());
347 Integer offset = 0;
348 for (Integer z = 0; z < nb_var; ++z) {
349 Integer my_data_size = sync_info.data_sizes[z];
350 auto sub_view = values.subView(offset, total_shared * my_data_size);
351 if (use_new_version) {
352 auto* ptr = reinterpret_cast<std::byte*>(sub_view.data());
353 vars[z]->_internalApi()->copyToBuffer(shared_matcells, { ptr, sub_view.size() }, &queue);
354 }
355 else
356 vars[z]->copyToBuffer(shared_matcells, sub_view);
357 offset += total_shared * my_data_size;
358 }
359 }
360
361 // Wait for copies to finish
362 queue.barrier();
363
364 // Post the sends
365 for (Integer i = 0; i < nb_rank; ++i) {
366 Int32 rank = ranks[i];
367 MP::PointToPointMessageInfo msg_info(MP::MessageRank(rank), sync_info.message_tag, MP::eBlockingType::NonBlocking);
368 sync_info.requests.add(mpSend(mpm, buf_list->sendBuffer(i), msg_info));
369 }
370}
371
372/*---------------------------------------------------------------------------*/
373/*---------------------------------------------------------------------------*/
374
375void MeshMaterialVariableSynchronizerList::
376_endSynchronizeMultiple2(SyncInfo& sync_info)
377{
378 ConstArrayView<MeshMaterialVariable*> vars = sync_info.variables;
379 IMeshMaterialVariableSynchronizer* mmvs = sync_info.mat_synchronizer;
380 IVariableSynchronizer* var_syncer = mmvs->variableSynchronizer();
381 IParallelMng* pm = var_syncer->parallelMng();
382
383 if (!pm->isParallel())
384 return;
385 const bool use_new_version = sync_info.use_generic_version;
386 RunQueue queue = pm->_internalApi()->queue();
387 IMeshMaterialSynchronizeBuffer* buf_list = sync_info.buf_list.get();
388
389 Int32ConstArrayView ranks = var_syncer->communicatingRanks();
390 Int32 nb_rank = ranks.size();
391 Integer nb_var = vars.size();
392
393 pm->waitAllRequests(sync_info.requests);
394
395 // Recopy the received data into the ghost cells.
396 for (Integer i = 0; i < nb_rank; ++i) {
397 ConstArrayView<MatVarIndex> ghost_matcells(mmvs->ghostItems(i));
398 Integer total_ghost = ghost_matcells.size();
399 ByteConstArrayView values(buf_list->receiveBuffer(i).smallView());
400
401 Integer offset = 0;
402 for (Integer z = 0; z < nb_var; ++z) {
403 Integer my_data_size = sync_info.data_sizes[z];
404 auto sub_view = values.subView(offset, total_ghost * my_data_size);
405 if (use_new_version) {
406 auto* ptr = reinterpret_cast<const std::byte*>(sub_view.data());
407 vars[z]->_internalApi()->copyFromBuffer(ghost_matcells, { ptr, sub_view.size() }, &queue);
408 }
409 else
410 vars[z]->copyFromBuffer(ghost_matcells, sub_view);
411 offset += total_ghost * my_data_size;
412 }
413 }
414 sync_info.message_total_size += buf_list->totalSize();
415
416 // Wait for copies to finish
417 queue.barrier();
418}
419
420/*---------------------------------------------------------------------------*/
421/*---------------------------------------------------------------------------*/
422
423} // End namespace Arcane::Materials
424
425/*---------------------------------------------------------------------------*/
426/*---------------------------------------------------------------------------*/
#define ARCANE_THROW(exception_class,...)
Macro for throwing an exception with formatting.
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
Brief list of message exchange functions.
constexpr Integer size() const noexcept
Number of elements in the array.
Template class for converting a type.
virtual IMessagePassingMng * messagePassingMng() const =0
Associated Arccore message passing manager.
virtual Int32ConstArrayView communicatingRanks()=0
Ranks of subdomains with which communication occurs.
virtual IParallelMng * parallelMng()=0
Associated parallel manager.
Interface for the material and environment manager of a mesh.
virtual Integer synchronizeVariableVersion() const =0
Version of the implementation for synchronizing material variables.
virtual IMeshMaterialMngInternal * _internalApi() const =0
Internal API for Arcane.
virtual IVariableSynchronizer * variableSynchronizer()=0
Associated classical variable synchronizer.
virtual eMemoryRessource bufferMemoryRessource() const =0
Memory resource to use for communication buffers.
virtual Ref< IMeshMaterialSynchronizeBuffer > commonBuffer()=0
Common buffer for messages.
Int64 totalMessageSize() const
After calling apply(), contains the size of the messages sent.
void add(MeshMaterialVariable *var)
Adds the variable var to the list of variables to synchronize.
void endSynchronize()
Blocks until the ongoing synchronization is finished.
String name() const override
Name of the variable.
MatVarSpace space() const override
Variable definition space (material+environment or environment only).
Reference to an instance.
1D data vector with value semantics (STL style).
Always enables tracing in Arcane parts concerning materials.
MatVarSpace
Definition space for a material variable.
@ Environment
Variable having values only on environments.
@ MaterialAndEnvironment
Variable having values on environments and materials.
Request mpReceive(IMessagePassingMng *pm, ISerializer *values, const PointToPointMessageInfo &message)
Receive message using an ISerializer.
Definition Messages.cc:290
Request mpSend(IMessagePassingMng *pm, const ISerializer *values, const PointToPointMessageInfo &message)
Send message using an ISerializer.
Definition Messages.cc:279
ArrayView< Byte > ByteArrayView
C equivalent of a 1D array of characters.
Definition UtilsTypes.h:447
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
Arcane::eMemoryResource eMemoryRessource
Typedef for the historical Arcane version (with 2's').
ConstArrayView< Byte > ByteConstArrayView
C equivalent of a 1D array of characters.
Definition UtilsTypes.h:476
std::int32_t Int32
Signed integer type of 32 bits.
Namespace containing the types and declarations that manage the message-passing parallelism mechanism...