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;
255void GetVariablesValuesParallelOperation:: {
…}
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 envoyant une exception FatalErrorException.
Vue modifiable d'un tableau d'un type T.
constexpr const_pointer data() const noexcept
Pointeur sur le début de la vue.
constexpr Integer size() const noexcept
Retourne la taille du tableau.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
ArrayView< T > view() const
Vue mutable sur ce tableau.
constexpr const_pointer data() const noexcept
Pointeur sur la mémoire allouée.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
constexpr bool empty() const noexcept
true si le tableau est vide (size()==0)
Interface d'une famille d'entités.
virtual void itemsUniqueIdToLocalId(Int32ArrayView local_ids, Int64ConstArrayView unique_ids, bool do_fatal=true) const =0
Converti un tableau de numéros uniques en numéros locaux.
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual ITraceMng * traceMng() const =0
Gestionnaire de traces.
virtual ITimeStats * timeStats() const =0
Gestionnaire de statistiques associé (peut être nul)
virtual void allGatherVariable(ConstArrayView< char > send_buf, Array< char > &recv_buf)=0
Effectue un regroupement sur tous les processeurs.
virtual Int32 commSize() const =0
Nombre d'instance dans le communicateur.
virtual void scatterVariable(ConstArrayView< char > send_buf, ArrayView< char > recv_buf, Integer root)=0
Scinde un tableau sur plusieurs processeurs.
virtual bool isParallel() const =0
Retourne true si l'exécution est parallèle.
virtual char reduce(eReduceType rt, char v)=0
Effectue la réduction de type rt sur le réel v et retourne la valeur.
Interface du gestionnaire de traces.
virtual TraceMessage fatal()=0
Flot pour un message d'erreur fatale.
virtual TraceMessage info()=0
Flot pour un message d'information.
virtual TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium)=0
Flot pour un message de debug.
Groupe d'entités de maillage.
IItemFamily * itemFamily() const
Famille d'entité à laquelle appartient ce groupe (0 pour le group nul)
bool null() const
true is le groupe est le groupe nul
Variable scalaire sur un type d'entité du maillage.
Positionne la phase de l'action en cours d'exécution.
Vecteur 1D de données avec sémantique par valeur (style STL).
String name() const
Nom de la variable.
ItemVariableScalarRefT< Real > VariableItemReal
Grandeur de type réel.
Déclarations des types et méthodes utilisés par les mécanismes d'échange de messages.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
Int32 Integer
Type représentant un entier.
ConstArrayView< Int64 > Int64ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 64 bits.
UniqueArray< Real > RealUniqueArray
Tableau dynamique à une dimension de réels.
ArrayView< Real > RealArrayView
Equivalent C d'un tableau à une dimension de réels.
std::int32_t Int32
Type entier signé sur 32 bits.