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/EdgeFamily.h"
34#include "arcane/mesh/DynamicMesh.h"
36#include <unordered_set>
71class ItemsOwnerBuilderImpl
91 ItemOwnerInfo() =
default;
117 explicit ItemsOwnerBuilderImpl(
IMesh*
mesh);
121 void computeFacesOwner();
122 void computeEdgesOwner();
123 void computeNodesOwner();
128 Int32 m_verbose_level = 0;
176 return pm->send(
ByteConstArrayView(messageSize(values),
reinterpret_cast<const Byte*
>(fsi_base)), rank,
false);
189 return ItemOwnerInfo(INT64_MAX, INT64_MAX, INT64_MAX, INT32_MAX, INT32_MAX);
203ItemsOwnerBuilderImpl::
209 ARCANE_FATAL(
"Mesh is not an instance of 'DynamicMesh'");
212 m_verbose_level = v.value();
218void ItemsOwnerBuilderImpl::
221 m_items_owner_info.clear();
226 FaceFamily& face_family = m_mesh->trueFaceFamily();
228 info() <<
"** BEGIN ComputeFacesOwner nb_face=" << faces_map.
count();
245 info() <<
"ItemsOwnerBuilder: NB_FACE_TO_TRANSFER=" << faces_to_add.
size();
246 const Int32 verbose_level = m_verbose_level;
248 FaceInfoListView faces(&face_family);
249 for (Int32 lid : faces_to_add) {
250 Face face(faces[lid]);
253 if (verbose_level >= 2)
254 info() <<
"ADD lid=" << lid <<
" uid=" << face_uid <<
" cell_uid=" << cell.uniqueId() <<
" owner=" << cell.owner();
255 m_items_owner_info.add(ItemOwnerInfo(face_uid, face.
node(0).
uniqueId(), cell.uniqueId(), my_rank, cell.owner()));
262 _processSortedInfos(faces_map);
270void ItemsOwnerBuilderImpl::
273 m_items_owner_info.clear();
275 IParallelMng* pm = m_mesh->parallelMng();
277 ItemInternalMap& edges_map = m_mesh->edgesMap();
278 EdgeFamily& edge_family = m_mesh->trueEdgeFamily();
280 info() <<
"** BEGIN ComputeEdgesOwner nb_edge=" << edges_map.count();
285 UniqueArray<Int32> edges_to_add;
286 UniqueArray<Int64> edges_to_add_uid;
292 bool do_brute_force =
true;
293 edges_map.eachItem([&](Edge edge) {
294 Int32 nb_cell = edge.nbCell();
295 Int32 nb_cell_with_my_rank = 0;
296 for (
Cell cell : edge.cells())
297 if (cell.owner() == my_rank)
298 ++nb_cell_with_my_rank;
299 bool do_add = (nb_cell == 1 || (nb_cell != nb_cell_with_my_rank));
300 if (do_add || do_brute_force) {
301 edges_to_add.add(edge.localId());
302 edges_to_add_uid.add(edge.uniqueId());
305 edge.mutableItemBase().setOwner(my_rank, my_rank);
307 info() <<
"ItemsOwnerBuilder: NB_FACE_TO_TRANSFER=" << edges_to_add.size();
308 const Int32 verbose_level = m_verbose_level;
310 EdgeInfoListView edges(&edge_family);
311 for (
Int32 lid : edges_to_add) {
312 Edge edge(edges[lid]);
313 Int64 edge_uid = edge.uniqueId();
314 for (
Cell cell : edge.cells()) {
315 if (verbose_level >= 2)
316 info() <<
"ADD lid=" << lid <<
" uid=" << edge_uid <<
" cell_uid=" << cell.uniqueId() <<
" owner=" << cell.owner();
317 m_items_owner_info.add(
ItemOwnerInfo(edge_uid, edge.node(0).uniqueId(), cell.uniqueId(), my_rank, cell.owner()));
324 _processSortedInfos(edges_map);
326 edge_family.notifyItemsOwnerChanged();
332void ItemsOwnerBuilderImpl::
335 m_items_owner_info.clear();
337 IParallelMng* pm = m_mesh->parallelMng();
338 const Int32 my_rank = pm->commRank();
339 ItemInternalMap& faces_map = m_mesh->facesMap();
340 ItemInternalMap& nodes_map = m_mesh->nodesMap();
341 NodeFamily& node_family = m_mesh->trueNodeFamily();
343 info() <<
"** BEGIN ComputeNodesOwner nb_node=" << nodes_map.count();
346 nodes_map.eachItem([&](Node node) {
347 node.mutableItemBase().setOwner(my_rank, my_rank);
360 const Int32 verbose_level = m_verbose_level;
363 std::unordered_set<Int32> done_nodes;
365 FaceInfoListView faces(m_mesh->faceFamily());
366 UniqueArray<Int32> nodes_to_add;
367 faces_map.eachItem([&](Face face) {
368 Int32 face_nb_cell = face.nbCell();
369 if (face_nb_cell == 2)
371 for (Node node : face.nodes()) {
372 Int32 node_id = node.localId();
373 if (done_nodes.find(node_id) == done_nodes.end()) {
374 nodes_to_add.add(node_id);
375 done_nodes.insert(node_id);
376 node.mutableItemBase().setOwner(A_NULL_RANK, my_rank);
381 info() <<
"ItemsOwnerBuilder: NB_NODE_TO_ADD=" << nodes_to_add.size();
382 NodeInfoListView nodes(&node_family);
383 for (
Int32 lid : nodes_to_add) {
384 Node node(nodes[lid]);
385 Int64 node_uid = node.uniqueId();
386 for (
Cell cell : node.cells()) {
387 if (verbose_level >= 2)
388 info() <<
"ADD lid=" << lid <<
" uid=" << node_uid <<
" cell_uid=" << cell.uniqueId() <<
" owner=" << cell.owner();
389 m_items_owner_info.add(
ItemOwnerInfo(node_uid, node_uid, cell.uniqueId(), my_rank, cell.owner()));
396 _processSortedInfos(nodes_map);
398 node_family.notifyItemsOwnerChanged();
411 const Int32 verbose_level = m_verbose_level;
413 items_sorter.setNeedIndexAndRank(
false);
415 items_sorter.
sort(m_items_owner_info);
417 m_items_owner_info = items_sorter.
keys();
418 info() <<
"END_ALL_ITEM_OWNER_SORTER time=" << (
Real)(sort_end_time - sort_begin_time);
419 if (verbose_level >= 2)
421 info() <<
"Sorted first_node_uid=" << x.m_first_node_uid <<
" item_uid="
422 << x.m_item_uid <<
" cell_uid=" << x.m_cell_uid <<
" owner=" << x.m_cell_owner;
429void ItemsOwnerBuilderImpl::
436 Int32 nb_sorted = items_owner_info.
size();
437 info() <<
"NbSorted=" << nb_sorted;
438 const bool is_last_rank = ((my_rank + 1) == nb_rank);
439 const bool is_first_rank = (my_rank == 0);
440 const Int32 verbose_level = m_verbose_level;
450 if (nb_sorted > 0 && !is_last_rank) {
451 Int32 send_index = nb_sorted;
452 Int64 last_uid = items_owner_info[nb_sorted - 1].m_item_uid;
453 for (
Int32 i = (nb_sorted - 1); i >= 0; --i) {
454 const ItemOwnerInfo& x = items_owner_info[i];
455 if (x.m_item_uid != last_uid) {
460 info() <<
"SendIndext=" << send_index <<
" nb_sorted=" << nb_sorted;
461 for (Int32 i = send_index; i < nb_sorted; ++i) {
462 const ItemOwnerInfo& x = items_owner_info[i];
463 items_owner_info_send_to_next.
add(x);
464 if (verbose_level >= 2)
465 info() <<
"AddSendToNext item_uid=" << x.m_item_uid <<
" owner=" << x.m_cell_owner
466 <<
" from_rank=" << x.m_item_sender_rank <<
" index=" << i;
469 Int32 nb_send_to_next = items_owner_info_send_to_next.
size();
470 info() <<
"NbSendToNext=" << nb_send_to_next;
472 Int32 nb_to_receive_from_previous = 0;
473 SmallArray<Parallel::Request> requests;
476 requests.add(pm->send(ConstArrayView<Int32>(1, &nb_send_to_next), my_rank + 1,
false));
478 requests.add(pm->
recv(ArrayView<Int32>(1, &nb_to_receive_from_previous), my_rank - 1,
false));
484 UniqueArray<ItemOwnerInfo> items_owner_info_received_from_previous(nb_to_receive_from_previous);
486 requests.add(ItemOwnerInfoSortTraits::send(pm, my_rank + 1, items_owner_info_send_to_next));
488 requests.add(ItemOwnerInfoSortTraits::recv(pm, my_rank - 1, items_owner_info_received_from_previous));
492 m_items_owner_info.resize(nb_sorted - nb_send_to_next);
493 items_owner_info = m_items_owner_info.view();
494 nb_sorted = items_owner_info.
size();
495 info() <<
"NbRemaining=" << nb_sorted;
497 Int64 current_item_uid = NULL_ITEM_UNIQUE_ID;
498 Int32 current_item_owner = A_NULL_RANK;
508 impl::HashTableMap2<Int32, UniqueArray<Int64>> resend_items_owner_info_map;
509 for (
Int32 index = 0; index < (nb_sorted + nb_to_receive_from_previous); ++index) {
513 if (index < nb_to_receive_from_previous)
514 first_ioi = &items_owner_info_received_from_previous[index];
516 first_ioi = &items_owner_info[index - nb_to_receive_from_previous];
517 Int64 item_uid = first_ioi->m_item_uid;
520 if (item_uid != current_item_uid) {
521 current_item_uid = item_uid;
522 current_item_owner = first_ioi->m_cell_owner;
523 if (verbose_level >= 2)
524 info() <<
"SetOwner from sorted index=" << index <<
" item_uid=" << current_item_uid <<
" new_owner=" << current_item_owner;
526 Int32 orig_sender = first_ioi->m_item_sender_rank;
527 UniqueArray<Int64>& send_array = resend_items_owner_info_map[orig_sender];
528 send_array.add(current_item_uid);
529 send_array.add(current_item_owner);
530 if (verbose_level >= 2)
531 info() <<
"SEND i=" << index <<
" rank=" << orig_sender <<
" item_uid=" << current_item_uid <<
" new_owner=" << current_item_owner;
535 info() <<
"NbResendRanks=" << resend_items_owner_info_map.size();
536 for (
const auto& [key, value] : resend_items_owner_info_map) {
537 if (verbose_level >= 1)
538 info() <<
"RESEND_INFO to_rank=" << key <<
" nb=" << value.size();
539 exchanger->addSender(key);
541 exchanger->initializeCommunicationsMessages();
544 for (
const auto& [key, value] : resend_items_owner_info_map) {
545 ISerializeMessage* sm = exchanger->messageToSend(index);
547 ISerializer* s = sm->serializer();
548 s->setMode(ISerializer::ModeReserve);
549 s->reserveArray(value);
555 exchanger->processExchange();
556 UniqueArray<Int64> receive_info;
558 for (
Integer i = 0, ns = exchanger->nbReceiver(); i < ns; ++i) {
559 ISerializeMessage* sm = exchanger->messageToReceive(i);
560 ISerializer* s = sm->serializer();
562 s->getArray(receive_info);
563 Int32 receive_size = receive_info.size();
564 if (verbose_level >= 1)
565 info() <<
"RECEIVE_INFO size=" << receive_size <<
" rank2=" << sm->destination();
567 if ((receive_size % 2) != 0)
568 ARCANE_FATAL(
"Size '{0}' is not a multiple of 2", receive_size);
569 Int32 buf_size = receive_size / 2;
570 for (
Int32 z = 0; z < buf_size; ++z) {
571 Int64 item_uid = receive_info[z * 2];
573 impl::ItemBase x = items_map.
findItem(item_uid);
574 if (verbose_level >= 2)
575 info() <<
"SetOwner uid=" << item_uid <<
" new_owner=" << item_owner;
576 x.toMutable().setOwner(item_owner, my_rank);
588ItemsOwnerBuilder(IMesh* mesh)
589: m_p(std::make_unique<ItemsOwnerBuilderImpl>(mesh))
602void ItemsOwnerBuilder::
605 m_p->computeFacesOwner();
611void ItemsOwnerBuilder::
614 m_p->computeEdgesOwner();
620void ItemsOwnerBuilder::
623 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.
@ Cell
Le maillage est AMR par maille.
std::int32_t Int32
Type entier signé sur 32 bits.