14#include "arcane/utils/ITraceMng.h"
16#include "arcane/core/Timer.h"
17#include "arcane/core/VariableTypes.h"
18#include "arcane/core/IParallelMng.h"
19#include "arcane/core/ISerializer.h"
20#include "arcane/core/IItemFamily.h"
21#include "arcane/core/ISerializeMessage.h"
23#include "arcane/impl/GetVariablesValuesParallelOperation.h"
25#include "arccore/message_passing/ISerializeMessageList.h"
39GetVariablesValuesParallelOperation::
48IParallelMng* GetVariablesValuesParallelOperation::
51 return m_parallel_mng;
57void GetVariablesValuesParallelOperation::
58getVariableValues(VariableItemReal& variable,
59 ConstArrayView<Int64> unique_ids,
60 ConstArrayView<Int32> sub_domain_ids,
61 ArrayView<Real> values)
63 IParallelMng* pm = m_parallel_mng;
64 Timer::Phase tphase(pm->timeStats(), TP_Communication);
66 if (!pm->isParallel()) {
67 _getVariableValuesSequential(variable, unique_ids, values);
71 ItemGroup group = variable.itemGroup();
72 IItemFamily* item_family = variable.variable()->itemFamily();
75 ARCANE_FATAL(
"The variable '{0}' is not defined on a group.", variable.name());
77 Int32 nb_item = unique_ids.size();
78 if (nb_item != values.size())
79 ARCANE_FATAL(
"The arrays 'unique_ids' and 'values' don't have the same "
80 "number of elements (respectively {0} and {1}).",
81 nb_item, values.size());
83 if (nb_item != sub_domain_ids.size())
84 ARCANE_FATAL(
"The arrays 'unique_ids' and 'sub_domains_ids' don't have the same "
85 "number of elements (respectively {0} and {1}).",
86 nb_item, sub_domain_ids.size());
88 using SubDomainUniqueIdMap = std::map<Int32, Helper>;
89 SubDomainUniqueIdMap sub_domain_list;
91 for (Integer i = 0; i < nb_item; ++i) {
92 Int32 sd = sub_domain_ids[i];
93 if (sd == NULL_SUB_DOMAIN_ID)
96 Helper& h = sub_domain_list[sd];
97 h.m_unique_ids.add(unique_ids[i]);
101 UniqueArray<Int32> sub_domain_nb_to_send;
102 Int32 my_rank = pm->commRank();
103 for (
auto& [sd, helper] : sub_domain_list) {
104 Integer n = helper.m_unique_ids.size();
105 sub_domain_nb_to_send.add(my_rank);
106 sub_domain_nb_to_send.add(sd);
107 sub_domain_nb_to_send.add(n);
110 UniqueArray<Int32> total_sub_domain_nb_to_send;
111 pm->allGatherVariable(sub_domain_nb_to_send, total_sub_domain_nb_to_send);
112 UniqueArray<Ref<ISerializeMessage>> messages;
113 Ref<ISerializeMessageList> message_list(pm->createSerializeMessageListRef());
114 for (Integer i = 0, is = total_sub_domain_nb_to_send.size(); i < is; i += 3) {
115 Int32 rank_send = total_sub_domain_nb_to_send[i];
116 Int32 rank_recv = total_sub_domain_nb_to_send[i + 1];
121 if (rank_send == rank_recv)
123 Ref<ISerializeMessage> sm;
124 if (rank_recv == my_rank) {
126 sm = message_list->createAndAddMessage(MessageRank(rank_send), ePointToPointMessageType::MsgReceive);
128 else if (rank_send == my_rank) {
130 sm = message_list->createAndAddMessage(MessageRank(rank_recv), ePointToPointMessageType::MsgSend);
131 ISerializer* s = sm->serializer();
132 s->setMode(ISerializer::ModeReserve);
133 auto xiter = sub_domain_list.find(rank_recv);
134 if (xiter == sub_domain_list.end())
136 Span<const Int64> z_unique_ids = xiter->second.m_unique_ids;
137 Int64 nb = z_unique_ids.size();
139 s->reserveSpan(eBasicDataType::Int64, nb);
141 s->setMode(ISerializer::ModePut);
143 s->putSpan(z_unique_ids);
149 message_list->waitMessages(eWaitType::WaitAll);
151 UniqueArray<Int64> tmp_unique_ids;
152 UniqueArray<Int32> tmp_local_ids;
153 UniqueArray<Real> tmp_values;
155 UniqueArray<Ref<ISerializeMessage>> values_messages;
156 ItemInfoListView items_internal(item_family);
157 for (Ref<ISerializeMessage> sm : messages) {
158 Ref<ISerializeMessage> new_sm;
162 new_sm = message_list->createAndAddMessage(MessageRank(sm->destination().value()), ePointToPointMessageType::MsgReceive);
165 ISerializer* s = sm->serializer();
166 s->setMode(ISerializer::ModeGet);
167 Int64 nb = s->getInt64();
168 tmp_unique_ids.resize(nb);
169 tmp_local_ids.resize(nb);
170 tmp_values.resize(nb);
171 s->getSpan(tmp_unique_ids);
172 item_family->itemsUniqueIdToLocalId(tmp_local_ids, tmp_unique_ids);
173 for (Integer z = 0; z < nb; ++z) {
174 Item item = items_internal[tmp_local_ids[z]];
175 tmp_values[z] = variable[item];
179 new_sm = message_list->createAndAddMessage(MessageRank(sm->destination().value()), ePointToPointMessageType::MsgSend);
180 ISerializer* s2 = new_sm->serializer();
181 s2->setMode(ISerializer::ModeReserve);
183 s2->reserveSpan(eBasicDataType::Real, nb);
184 s2->allocateBuffer();
185 s2->setMode(ISerializer::ModePut);
187 s2->putSpan(tmp_values);
189 values_messages.add(new_sm);
195 message_list->waitMessages(eWaitType::WaitAll);
197 for (Ref<ISerializeMessage> sm : values_messages) {
201 ISerializer* s = sm->serializer();
202 s->setMode(ISerializer::ModeGet);
203 Int64 nb = s->getInt64();
204 tmp_values.resize(nb);
205 Int32 sender = sm->destination().value();
206 s->getSpan(tmp_values);
208 Span<const Int32> indexes = sub_domain_list[sender].m_indexes;
209 for (Int64 z = 0; z < nb; ++z)
210 values[indexes[z]] = tmp_values[z];
217 Helper h(sub_domain_list[my_rank]);
218 Span<const Int32> indexes(h.m_indexes.constSpan());
219 Int64 nb = h.m_unique_ids.largeSize();
220 tmp_local_ids.resize(nb);
221 item_family->itemsUniqueIdToLocalId(tmp_local_ids, h.m_unique_ids);
222 for (Int64 z = 0; z < nb; ++z) {
223 Item item = items_internal[tmp_local_ids[z]];
224 values[indexes[z]] = variable[item];
229 values_messages.clear();
235 Integer nb_values = values.size();
237 ref_values.fill(0.0);
238 getVariableValues(variable,unique_ids,ref_values);
239 bool has_error =
false;
240 for( Integer i=0; i<nb_values; ++i ){
241 if (!math::isEqual(ref_values[i],values[i])){
242 trace->pinfo() <<
" Incorrect values ref=" << ref_values[i] <<
" v=" << values[i];
247 trace->fatal() << func_id <<
" incorrect values";
255void GetVariablesValuesParallelOperation::
263 _getVariableValuesSequential(variable, unique_ids, values);
270 ARCANE_FATAL(
"The variable '{0}' is not defined on a group.", variable.
name());
273 if (size != values.
size())
274 ARCANE_FATAL(
"The arrays 'unique_ids' and 'values' don't have the same "
275 "number of elements (respectively {0} and {1}).",
276 size, values.
size());
280 while (nb_proc != 0 && nb_phase < 32) {
286 trace->
info() <<
" NB PHASE=" << nb_phase;
289 _getVariableValues(variable, unique_ids, values);
293 for (
Integer i = 0; i < nb_phase; ++i) {
294 Integer first = (i * size) / nb_phase;
295 Integer last = ((i + 1) * size) / nb_phase;
296 if ((i + 1) == nb_phase)
300 trace->
debug() <<
"GetVariableValue: first=" << first <<
" last=" << last <<
" n=" << n
304 _getVariableValues(variable, local_unique_ids, local_values);
306 if (nb_done != size) {
307 trace->
fatal() <<
"MpiParallelMng::getVariableValue() Internal error in size: "
308 <<
" size=" << size <<
" done=" << nb_done;
316template <
class Type>
void GetVariablesValuesParallelOperation::
330 if (unique_ids.
empty()) {
331 dummy_unique_ids.
resize(1);
333 dummy_unique_ids[0] = NULL_ITEM_ID;
334 unique_ids = dummy_unique_ids.
view();
335 values = dummy_values.
view();
351 Int64UniqueArray all_unique_ids;
353 Integer all_size = all_unique_ids.size();
354 Int32UniqueArray all_local_ids(all_size);
357 ConstArrayView<Type> variable_a(variable.asArray());
358 UniqueArray<Type> all_values(all_size);
360 msg->
debug() <<
"MpiParallelMng::_getVariableValues(): size=" << all_size
361 <<
" values_size=" <<
sizeof(
Type) * all_size;
365 Type max_value = std::numeric_limits<Type>::max();
366 ItemInfoListView internal_items(item_family);
368 for (Integer i = 0; i < all_size; ++i) {
369 Integer lid = all_local_ids[i];
370 if (lid == NULL_ITEM_ID)
371 all_values[i] = max_value;
373 all_values[i] = (internal_items[lid].isOwn()) ? variable_a[lid] : max_value;
377 pm->
reduce(Parallel::ReduceMin, all_values);
386template <
class Type>
void GetVariablesValuesParallelOperation::
387_getVariableValuesSequential(ItemVariableScalarRefT<Type>& variable,
388 Int64ConstArrayView unique_ids,
389 ArrayView<Type> values)
391 ItemGroup group = variable.itemGroup();
393 ARCANE_FATAL(
"The variable '{0}' is not defined on a group.", variable.name());
395 IItemFamily* family = group.itemFamily();
396 Int32 size = unique_ids.size();
397 if (size != values.size())
398 ARCANE_FATAL(
"The arrays 'unique_ids' and 'values' don't have the same "
399 "number of elements (respectively {0} and {1}).",
400 size, values.size());
403 UniqueArray<Int32> local_ids(size);
404 family->itemsUniqueIdToLocalId(local_ids, unique_ids);
405 ConstArrayView<Type> variable_a(variable.asArray());
406 for (Integer i = 0; i < size; ++i)
407 values[i] = variable_a[local_ids[i]];
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
Modifiable view of an array of type T.
constexpr const_pointer data() const noexcept
Pointer to the start of the view.
constexpr Integer size() const noexcept
Returns the size of the array.
void resize(Int64 s)
Changes the number of elements in the array to s.
ArrayView< T > view() const
Mutable view of this array.
constexpr const_pointer data() const noexcept
Pointer to the allocated memory.
constexpr Integer size() const noexcept
Number of elements in the array.
constexpr bool empty() const noexcept
true if the array is empty (size()==0)
Interface of an entity family.
virtual void itemsUniqueIdToLocalId(Int32ArrayView local_ids, Int64ConstArrayView unique_ids, bool do_fatal=true) const =0
Converts an array of unique numbers to local numbers.
Interface of the parallelism manager for a subdomain.
virtual ITraceMng * traceMng() const =0
Trace manager.
virtual ITimeStats * timeStats() const =0
Associated statistics manager (can be null).
virtual void allGatherVariable(ConstArrayView< char > send_buf, Array< char > &recv_buf)=0
Performs an all-gather operation across all processors.
virtual Int32 commSize() const =0
Number of instances in the communicator.
virtual void scatterVariable(ConstArrayView< char > send_buf, ArrayView< char > recv_buf, Integer root)=0
Scatters an array across multiple processors.
virtual bool isParallel() const =0
Returns true if the execution is parallel.
virtual char reduce(eReduceType rt, char v)=0
Performs a reduction of type rt on the real v and returns the value.
virtual TraceMessage fatal()=0
Stream for a fatal error message.
virtual TraceMessage info()=0
Stream for an information message.
virtual TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium)=0
Stream for a debug message.
IItemFamily * itemFamily() const
Entity family to which this group belongs (0 for the null group).
bool null() const
true means the group is the null group
Scalar variable on a mesh entity type.
Positions the phase of the currently executing action.
1D data vector with value semantics (STL style).
String name() const
Variable name.
ItemVariableScalarRefT< Real > VariableItemReal
Real type quantity.
Declarations of types and methods used by message exchange mechanisms.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Int32 Integer
Type representing an integer.
ConstArrayView< Int64 > Int64ConstArrayView
C equivalent of a 1D array of 64-bit integers.
UniqueArray< Real > RealUniqueArray
Dynamic 1D array of reals.
ArrayView< Real > RealArrayView
C equivalent of a 1D array of reals.
std::int32_t Int32
Signed integer type of 32 bits.