14#include "arcane/mesh/ItemsOwnerBuilder.h"
16#include "arcane/utils/FatalErrorException.h"
17#include "arcane/utils/PlatformUtils.h"
18#include "arcane/utils/SmallArray.h"
19#include "arcane/utils/TraceAccessor.h"
20#include "arcane/utils/HashTableMap2.h"
21#include "arcane/utils/ValueConvert.h"
23#include "arcane/core/IParallelMng.h"
24#include "arcane/core/ParallelMngUtils.h"
25#include "arcane/core/IParallelExchanger.h"
26#include "arcane/core/ISerializeMessage.h"
27#include "arcane/core/ISerializer.h"
29#include "arcane/parallel/BitonicSortT.H"
31#include "arcane/mesh/ItemInternalMap.h"
32#include "arcane/mesh/NodeFamily.h"
33#include "arcane/mesh/DynamicMesh.h"
35#include <unordered_set>
70class ItemsOwnerBuilderImpl
90 ItemOwnerInfo() =
default;
116 explicit ItemsOwnerBuilderImpl(
IMesh*
mesh);
120 void computeFacesOwner();
121 void computeNodesOwner();
126 Int32 m_verbose_level = 0;
174 return pm->send(
ByteConstArrayView(messageSize(values),
reinterpret_cast<const Byte*
>(fsi_base)), rank,
false);
187 return ItemOwnerInfo(INT64_MAX, INT64_MAX, INT64_MAX, INT32_MAX, INT32_MAX);
201ItemsOwnerBuilderImpl::
207 ARCANE_FATAL(
"Mesh is not an instance of 'DynamicMesh'");
210 m_verbose_level = v.value();
216void ItemsOwnerBuilderImpl::
219 m_items_owner_info.clear();
224 FaceFamily& face_family = m_mesh->trueFaceFamily();
226 info() <<
"** BEGIN ComputeFacesOwner nb_face=" << faces_map.
count();
243 info() <<
"ItemsOwnerBuilder: NB_FACE_TO_TRANSFER=" << faces_to_add.
size();
244 const Int32 verbose_level = m_verbose_level;
246 FaceInfoListView faces(&face_family);
247 for (Int32 lid : faces_to_add) {
248 Face face(faces[lid]);
250 for (Cell cell : face.
cells()) {
251 if (verbose_level >= 2)
252 info() <<
"ADD lid=" << lid <<
" uid=" << face_uid <<
" cell_uid=" << cell.uniqueId() <<
" owner=" << cell.owner();
253 m_items_owner_info.add(ItemOwnerInfo(face_uid, face.
node(0).
uniqueId(), cell.uniqueId(), my_rank, cell.owner()));
260 _processSortedInfos(faces_map);
268void ItemsOwnerBuilderImpl::
271 m_items_owner_info.clear();
273 IParallelMng* pm = m_mesh->parallelMng();
275 ItemInternalMap& faces_map = m_mesh->facesMap();
276 ItemInternalMap& nodes_map = m_mesh->nodesMap();
277 NodeFamily& node_family = m_mesh->trueNodeFamily();
279 info() <<
"** BEGIN ComputeNodesOwner nb_node=" << nodes_map.count();
282 nodes_map.eachItem([&](Node node) {
283 node.mutableItemBase().setOwner(my_rank, my_rank);
296 const Int32 verbose_level = m_verbose_level;
299 std::unordered_set<Int32> done_nodes;
301 FaceInfoListView faces(m_mesh->faceFamily());
302 UniqueArray<Int32> nodes_to_add;
303 faces_map.eachItem([&](Face face) {
304 Int32 face_nb_cell = face.nbCell();
305 if (face_nb_cell == 2)
307 for (Node node : face.nodes()) {
308 Int32 node_id = node.localId();
309 if (done_nodes.find(node_id) == done_nodes.end()) {
310 nodes_to_add.add(node_id);
311 done_nodes.insert(node_id);
312 node.mutableItemBase().setOwner(A_NULL_RANK, my_rank);
317 info() <<
"ItemsOwnerBuilder: NB_NODE_TO_ADD=" << nodes_to_add.size();
318 NodeInfoListView nodes(&node_family);
319 for (
Int32 lid : nodes_to_add) {
320 Node node(nodes[lid]);
321 Int64 node_uid = node.uniqueId();
322 for (Cell cell : node.cells()) {
323 if (verbose_level >= 2)
324 info() <<
"ADD lid=" << lid <<
" uid=" << node_uid <<
" cell_uid=" << cell.uniqueId() <<
" owner=" << cell.owner();
325 m_items_owner_info.add(
ItemOwnerInfo(node_uid, node_uid, cell.uniqueId(), my_rank, cell.owner()));
332 _processSortedInfos(nodes_map);
334 node_family.notifyItemsOwnerChanged();
347 const Int32 verbose_level = m_verbose_level;
349 items_sorter.setNeedIndexAndRank(
false);
351 items_sorter.
sort(m_items_owner_info);
353 m_items_owner_info = items_sorter.
keys();
354 info() <<
"END_ALL_ITEM_OWNER_SORTER time=" << (
Real)(sort_end_time - sort_begin_time);
355 if (verbose_level >= 2)
357 info() <<
"Sorted first_node_uid=" << x.m_first_node_uid <<
" item_uid="
358 << x.m_item_uid <<
" cell_uid=" << x.m_cell_uid <<
" owner=" << x.m_cell_owner;
365void ItemsOwnerBuilderImpl::
372 Int32 nb_sorted = items_owner_info.
size();
373 info() <<
"NbSorted=" << nb_sorted;
374 const bool is_last_rank = ((my_rank + 1) == nb_rank);
375 const bool is_first_rank = (my_rank == 0);
376 const Int32 verbose_level = m_verbose_level;
386 if (nb_sorted > 0 && !is_last_rank) {
387 Int32 send_index = nb_sorted;
388 Int64 last_uid = items_owner_info[nb_sorted - 1].m_item_uid;
389 for (
Int32 i = (nb_sorted - 1); i >= 0; --i) {
390 const ItemOwnerInfo& x = items_owner_info[i];
391 if (x.m_item_uid != last_uid) {
396 info() <<
"SendIndext=" << send_index <<
" nb_sorted=" << nb_sorted;
397 for (Int32 i = send_index; i < nb_sorted; ++i) {
398 const ItemOwnerInfo& x = items_owner_info[i];
399 items_owner_info_send_to_next.
add(x);
400 if (verbose_level >= 2)
401 info() <<
"AddSendToNext item_uid=" << x.m_item_uid <<
" owner=" << x.m_cell_owner
402 <<
" from_rank=" << x.m_item_sender_rank <<
" index=" << i;
405 Int32 nb_send_to_next = items_owner_info_send_to_next.
size();
406 info() <<
"NbSendToNext=" << nb_send_to_next;
408 Int32 nb_to_receive_from_previous = 0;
409 SmallArray<Parallel::Request> requests;
412 requests.add(pm->send(ConstArrayView<Int32>(1, &nb_send_to_next), my_rank + 1,
false));
414 requests.add(pm->
recv(ArrayView<Int32>(1, &nb_to_receive_from_previous), my_rank - 1,
false));
420 UniqueArray<ItemOwnerInfo> items_owner_info_received_from_previous(nb_to_receive_from_previous);
422 requests.add(ItemOwnerInfoSortTraits::send(pm, my_rank + 1, items_owner_info_send_to_next));
424 requests.add(ItemOwnerInfoSortTraits::recv(pm, my_rank - 1, items_owner_info_received_from_previous));
428 m_items_owner_info.resize(nb_sorted - nb_send_to_next);
429 items_owner_info = m_items_owner_info.view();
430 nb_sorted = items_owner_info.
size();
431 info() <<
"NbRemaining=" << nb_sorted;
433 Int64 current_item_uid = NULL_ITEM_UNIQUE_ID;
434 Int32 current_item_owner = A_NULL_RANK;
444 impl::HashTableMap2<Int32, UniqueArray<Int64>> resend_items_owner_info_map;
445 for (
Int32 index = 0; index < (nb_sorted + nb_to_receive_from_previous); ++index) {
449 if (index < nb_to_receive_from_previous)
450 first_ioi = &items_owner_info_received_from_previous[index];
452 first_ioi = &items_owner_info[index - nb_to_receive_from_previous];
453 Int64 item_uid = first_ioi->m_item_uid;
456 if (item_uid != current_item_uid) {
457 current_item_uid = item_uid;
458 current_item_owner = first_ioi->m_cell_owner;
459 if (verbose_level >= 2)
460 info() <<
"SetOwner from sorted index=" << index <<
" item_uid=" << current_item_uid <<
" new_owner=" << current_item_owner;
462 Int32 orig_sender = first_ioi->m_item_sender_rank;
463 UniqueArray<Int64>& send_array = resend_items_owner_info_map[orig_sender];
464 send_array.add(current_item_uid);
465 send_array.add(current_item_owner);
466 if (verbose_level >= 2)
467 info() <<
"SEND i=" << index <<
" rank=" << orig_sender <<
" item_uid=" << current_item_uid <<
" new_owner=" << current_item_owner;
471 info() <<
"NbResendRanks=" << resend_items_owner_info_map.size();
472 for (
const auto& [key, value] : resend_items_owner_info_map) {
473 if (verbose_level >= 1)
474 info() <<
"RESEND_INFO to_rank=" << key <<
" nb=" << value.size();
475 exchanger->addSender(key);
477 exchanger->initializeCommunicationsMessages();
480 for (
const auto& [key, value] : resend_items_owner_info_map) {
481 ISerializeMessage* sm = exchanger->messageToSend(index);
483 ISerializer* s = sm->serializer();
484 s->setMode(ISerializer::ModeReserve);
485 s->reserveArray(value);
491 exchanger->processExchange();
492 UniqueArray<Int64> receive_info;
494 for (
Integer i = 0, ns = exchanger->nbReceiver(); i < ns; ++i) {
495 ISerializeMessage* sm = exchanger->messageToReceive(i);
496 ISerializer* s = sm->serializer();
498 s->getArray(receive_info);
499 Int32 receive_size = receive_info.size();
500 if (verbose_level >= 1)
501 info() <<
"RECEIVE_INFO size=" << receive_size <<
" rank2=" << sm->destination();
503 if ((receive_size % 2) != 0)
504 ARCANE_FATAL(
"Size '{0}' is not a multiple of 2", receive_size);
505 Int32 buf_size = receive_size / 2;
506 for (
Int32 z = 0; z < buf_size; ++z) {
507 Int64 item_uid = receive_info[z * 2];
509 impl::ItemBase x = items_map.
findItem(item_uid);
510 if (verbose_level >= 2)
511 info() <<
"SetOwner uid=" << item_uid <<
" new_owner=" << item_owner;
512 x.toMutable().setOwner(item_owner, my_rank);
524ItemsOwnerBuilder(IMesh* mesh)
525: m_p(std::make_unique<ItemsOwnerBuilderImpl>(mesh))
538void ItemsOwnerBuilder::
541 m_p->computeFacesOwner();
547void ItemsOwnerBuilder::
550 m_p->computeNodesOwner();
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Integer size() const
Nombre d'éléments du vecteur.
Vue modifiable d'un tableau d'un type T.
constexpr const_pointer data() const noexcept
Pointeur sur le début de la vue.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
Vue constante d'un tableau de type T.
constexpr const_pointer data() const noexcept
Pointeur sur la mémoire allouée.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
Cell cell(Int32 i) const
i-ème maille de la face
Int32 nbCell() const
Nombre de mailles de la face (1 ou 2)
CellConnectedListViewType cells() const
Liste des mailles de la face.
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual Int32 commRank() const =0
Rang de cette instance dans le communicateur.
virtual void recv(ArrayView< char > values, Int32 rank)=0
virtual Int32 commSize() const =0
Nombre d'instance dans le communicateur.
virtual void waitAllRequests(ArrayView< Request > rvalues)=0
Bloque en attendant que les requêtes rvalues soient terminées.
@ ModePut
Le sérialiseur attend des reserve()
@ ModeGet
Le sérialiseur attend des get()
Node node(Int32 i) const
i-ème noeud de l'entité
impl::MutableItemBase mutableItemBase() const
Partie interne modifiable de l'entité.
constexpr Int32 localId() const
Identifiant local de l'entité dans le sous-domaine du processeur.
Int32 owner() const
Numéro du sous-domaine propriétaire de l'entité
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
void setOwner(Integer suid, Int32 current_sub_domain)
Positionne le numéro du sous-domaine propriétaire de l'entité.
Algorithme de tri bitonique parallèle.
ConstArrayView< KeyType > keys() const override
Après un tri, retourne la liste des éléments de ce rang.
void sort(ConstArrayView< KeyType > keys) override
Trie en parallèle les éléments de keys sur tous les rangs.
TraceAccessor(ITraceMng *m)
Construit un accesseur via le gestionnaire de trace m.
TraceMessage info() const
Flot pour un message d'information.
ITraceMng * traceMng() const
Gestionnaire de trace.
Vecteur 1D de données avec sémantique par valeur (style STL).
Implémentation d'un maillage.
IParallelMng * parallelMng() override
Gestionnaire de parallèlisme.
void notifyItemsOwnerChanged() override
Notifie que les entités propres au sous-domaine de la famille ont été modifiées.
Tableau associatif de ItemInternal.
impl::ItemBase findItem(Int64 uid) const
Retourne l'entité de numéro unique uid.
void eachItem(const Lambda &lambda)
Fonction template pour itérer sur les entités de l'instance.
Int32 count() const
Nombre d'éléments de la table.
Informations sur une entité partagée.
Int32 m_item_sender_rank
rang de celui qui a créé cette instance
Int64 m_first_node_uid
uniqueId() du premier noeud de l'entité
Int32 m_cell_owner
Propriétaire de la maille connectée à cette entité
Int64 m_item_uid
uniqueId() de l'entité
Int64 m_cell_uid
uniqueId() de la maille à laquelle l'entité appartient
void _sortInfos()
Tri les instances contenues dans m_items_owner_info replace les valeurs triées dans ce même tableau.
Integer toInteger(Real r)
Converti un Int64 en un Integer.
Int32 toInt32(Int64 v)
Converti un Int64 en un Int32.
Ref< IParallelExchanger > createExchangerRef(IParallelMng *pm)
Retourne une interface pour transférer des messages entre rangs.
ArrayView< Byte > ByteArrayView
Equivalent C d'un tableau à une dimension de caractères.
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
double Real
Type représentant un réel.
ConstArrayView< Byte > ByteConstArrayView
Equivalent C d'un tableau à une dimension de caractères.
unsigned char Byte
Type d'un octet.
std::int32_t Int32
Type entier signé sur 32 bits.