Arcane  4.1.12.0
User documentation
Loading...
Searching...
No Matches
VariableParallelOperationBase.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/* VariableParallelOperationBase.cc (C) 2000-2024 */
9/* */
10/* Base class for parallel operations on variables. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/parallel/VariableParallelOperationBase.h"
15
16#include "arcane/utils/FatalErrorException.h"
17#include "arcane/utils/ScopedPtr.h"
18
19#include "arcane/core/IParallelMng.h"
20#include "arcane/core/ISerializer.h"
21#include "arcane/core/ISerializeMessage.h"
22#include "arcane/core/IParallelExchanger.h"
23#include "arcane/core/ISubDomain.h"
24#include "arcane/core/IVariable.h"
25#include "arcane/core/IItemFamily.h"
26#include "arcane/core/ItemInternal.h"
27#include "arcane/core/ItemGroup.h"
28#include "arcane/core/ParallelMngUtils.h"
29
30/*---------------------------------------------------------------------------*/
31/*---------------------------------------------------------------------------*/
32
33namespace Arcane::Parallel
34{
35
36namespace
37{
38 const Int64 SERIALIZE_MAGIC_NUMBER = 0x4cf92789;
39}
40
41/*---------------------------------------------------------------------------*/
42/*---------------------------------------------------------------------------*/
43
44VariableParallelOperationBase::
45VariableParallelOperationBase(IParallelMng* pm)
46: TraceAccessor(pm->traceMng())
47, m_parallel_mng(pm)
48, m_item_family(nullptr)
49{
50}
51
52/*---------------------------------------------------------------------------*/
53/*---------------------------------------------------------------------------*/
54
55void VariableParallelOperationBase::
56setItemFamily(IItemFamily* family)
57{
58 if (m_item_family)
59 ARCANE_FATAL("family already set");
60 m_item_family = family;
61}
62
63/*---------------------------------------------------------------------------*/
64/*---------------------------------------------------------------------------*/
65
66IItemFamily* VariableParallelOperationBase::
67itemFamily()
68{
69 return m_item_family;
70}
71
72/*---------------------------------------------------------------------------*/
73/*---------------------------------------------------------------------------*/
74
75void VariableParallelOperationBase::
76addVariable(IVariable* variable)
77{
78 if (!m_item_family)
79 ARCANE_FATAL("family not set. call setItemFamily()");
80 if (variable->itemGroup().itemFamily() != m_item_family)
81 ARCANE_FATAL("variable->itemFamily() and itemFamily() differ");
82 m_variables.add(variable);
83}
84
85/*---------------------------------------------------------------------------*/
86/*---------------------------------------------------------------------------*/
87
88void VariableParallelOperationBase::
89applyOperation(IDataOperation* operation)
90{
91 if (m_variables.empty())
92 return;
93
94#ifdef ARCANE_DEBUG
95 const bool is_debug_print = true;
96#else
97 const bool is_debug_print = false;
98#endif
99 IParallelMng* pm = m_parallel_mng;
100 Integer nb_rank = pm->commSize();
101 m_items_to_send.clear();
102 m_items_to_send.resize(nb_rank);
103 _buildItemsToSend();
104
106 m_messages.reserve(nb_rank);
107
108 auto exchanger{ ParallelMngUtils::createExchangerRef(pm) };
109
110 for (Integer i = 0; i < nb_rank; ++i)
111 if (!m_items_to_send[i].empty())
112 exchanger->addSender(i);
113
114 bool no_exchange = exchanger->initializeCommunicationsMessages();
115 if (no_exchange)
116 return;
117
118 ItemInfoListView item_list(m_item_family);
119 // Generates info for each processor to which we will send entities
120 for (Integer i = 0, is = exchanger->nbSender(); i < is; ++i) {
121 ISerializeMessage* comm = exchanger->messageToSend(i);
122 Int32 dest_sub_domain = comm->destination().value();
123 ConstArrayView<ItemLocalId> dest_items_internal = m_items_to_send[dest_sub_domain];
124
125 Integer nb_item = dest_items_internal.size();
126 debug() << "Number of items to serialize: " << nb_item << " subdomain=" << dest_sub_domain;
127
128 UniqueArray<Int32> dest_items_local_id(nb_item);
129 UniqueArray<Int64> dest_items_unique_id(nb_item);
130 for (Integer z = 0; z < nb_item; ++z) {
131 Item item = item_list[dest_items_internal[z]];
132 dest_items_local_id[z] = item.localId();
133 dest_items_unique_id[z] = item.uniqueId().asInt64();
134 }
135 ISerializer* sbuf = comm->serializer();
136
137 // Reserves memory for serialization
138 sbuf->setMode(ISerializer::ModeReserve);
139
140 // Reserves for the magic number
141 sbuf->reserveInt64(1);
142
143 // Reserves for the list of uniqueId() of transferred entities
144 sbuf->reserveInt64(1);
145 sbuf->reserveSpan(dest_items_unique_id);
146
147 // Reserves for each variable
148 for (VariableList::Enumerator i_var(m_variables); ++i_var;) {
149 IVariable* var = *i_var;
150 debug(Trace::High) << "Serialize variable (reserve)" << var->name();
151 var->serialize(sbuf, dest_items_local_id);
152 }
153
154 sbuf->allocateBuffer();
155
156 // Serializes the info
158
159 // Serializes the magic number
160 sbuf->putInt64(SERIALIZE_MAGIC_NUMBER);
161
162 // Serializes the list of uniqueId() of transferred entities
163 sbuf->putInt64(nb_item);
164 sbuf->putSpan(dest_items_unique_id);
165 for (VariableList::Enumerator i_var(m_variables); ++i_var;) {
166 IVariable* var = *i_var;
167 debug(Trace::High) << "Serialise variable (put)" << var->name();
168 var->serialize(sbuf, dest_items_local_id);
169 }
170 }
171
172 exchanger->processExchange();
173
174 {
175 debug() << "VariableParallelOperationBase::readVariables()";
176
177 UniqueArray<Int64> items_unique_id;
178 UniqueArray<Int32> items_local_id;
179
180 // Retrieves info for variables and fills them
181 for (Integer i = 0, n = exchanger->nbReceiver(); i < n; ++i) {
182 ISerializeMessage* comm = exchanger->messageToReceive(i);
183 ISerializer* sbuf = comm->serializer();
184
185 // Deserializes the variables
186 {
187 // Serializes the magic number
188 Int64 magic_number = sbuf->getInt64();
189 if (magic_number != SERIALIZE_MAGIC_NUMBER)
190 ARCANE_FATAL("Bad magic number actual={0} expected={1}. This is probably due to incoherent messaging",
191 magic_number, SERIALIZE_MAGIC_NUMBER);
192
193 // Retrieves the list of uniqueId() of transferred entities
194 Int64 nb_item = sbuf->getInt64();
195 items_unique_id.resize(nb_item);
196 sbuf->getSpan(items_unique_id);
197 items_local_id.resize(nb_item);
198 debug(Trace::High) << "Receiving " << nb_item << " items from " << comm->destination().value();
199
200 if (is_debug_print) {
201 for (Integer iz = 0; iz < nb_item; ++iz)
202 debug(Trace::Highest) << "Receiving uid=" << items_unique_id[iz];
203 }
204
205 itemFamily()->itemsUniqueIdToLocalId(items_local_id, items_unique_id);
206
207 for (VariableList::Enumerator ivar(m_variables); ++ivar;) {
208 IVariable* var = *ivar;
209 var->serialize(sbuf, items_local_id, operation);
210 }
211 }
212 }
213 }
214}
215
216/*---------------------------------------------------------------------------*/
217/*---------------------------------------------------------------------------*/
218
219} // End namespace Arcane::Parallel
220
221/*---------------------------------------------------------------------------*/
222/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
void resize(Int64 s)
Changes the number of elements in the array to s.
void reserve(Int64 new_capacity)
Reserves memory for new_capacity elements.
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
Interface of the parallelism manager for a subdomain.
virtual Int32 commSize() const =0
Number of instances in the communicator.
virtual Int64 getInt64()=0
Retrieve a size.
virtual void allocateBuffer()=0
Allocates the serializer memory.
virtual void putSpan(Span< const Real > values)
Add the array values.
virtual void getSpan(Span< Real > values)
Retrieve the array values.
virtual void reserveSpan(eBasicDataType dt, Int64 n)=0
Reserves memory for n values of dt.
virtual void setMode(eMode new_mode)=0
Sets the current mode.
virtual void putInt64(Int64 value)=0
Add the integer value.
Interface of a variable.
Definition IVariable.h:40
virtual ItemGroup itemGroup() const =0
Associated mesh group.
virtual void serialize(ISerializer *sbuffer, IDataOperation *operation=0)=0
virtual String name() const =0
Variable name.
IItemFamily * itemFamily() const
Entity family to which this group belongs (0 for the null group).
Definition ItemGroup.h:128
View of a list to obtain information about entities.
Base class for a mesh element.
Definition Item.h:84
constexpr Int32 localId() const
Local identifier of the entity in the processor subdomain.
Definition Item.h:233
ItemUniqueId uniqueId() const
Unique identifier across all domains.
Definition Item.h:239
virtual MessageRank destination() const =0
Destination rank (if isSend() is true) or sender.
virtual ISerializer * serializer()=0
Serializer.
Int32 value() const
Rank value.
Definition MessageRank.h:76
IItemFamily * itemFamily() override
Entity family on which the operation is performed.
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flow for a debug message.
1D data vector with value semantics (STL style).
Ref< IParallelExchanger > createExchangerRef(IParallelMng *pm)
Returns an interface to transfer messages between ranks.
Concurrency implementation.
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
std::int32_t Int32
Signed integer type of 32 bits.