diff --git a/arcane/src/arcane/mesh/DynamicMeshIncrementalBuilder.cc b/arcane/src/arcane/mesh/DynamicMeshIncrementalBuilder.cc index af5185115..d982615bd 100644 --- a/arcane/src/arcane/mesh/DynamicMeshIncrementalBuilder.cc +++ b/arcane/src/arcane/mesh/DynamicMeshIncrementalBuilder.cc @@ -16,6 +16,7 @@ #include "arcane/utils/NotImplementedException.h" #include "arcane/utils/NotSupportedException.h" #include "arcane/utils/ITraceMng.h" +#include "arcane/utils/ValueConvert.h" #include "arcane/core/ItemTypeMng.h" #include "arcane/core/MeshUtils.h" @@ -63,6 +64,8 @@ DynamicMeshIncrementalBuilder(DynamicMesh* mesh) , m_has_amr(mesh->isAmrActivated()) , m_one_mesh_item_adder(new OneMeshItemAdder(this)) { + if (auto v = Convert::Type::tryParseFromEnvironment("ARCANE_VERBOSE_MESH_BUILDER", true)) + m_verbose = (v.value()!=0); } /*---------------------------------------------------------------------------*/ diff --git a/arcane/src/arcane/mesh/EdgeUniqueIdBuilder.cc b/arcane/src/arcane/mesh/EdgeUniqueIdBuilder.cc index 6e6dabac4..7bf89c46b 100644 --- a/arcane/src/arcane/mesh/EdgeUniqueIdBuilder.cc +++ b/arcane/src/arcane/mesh/EdgeUniqueIdBuilder.cc @@ -50,14 +50,6 @@ EdgeUniqueIdBuilder(DynamicMeshIncrementalBuilder* mesh_builder) /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ -EdgeUniqueIdBuilder:: -~EdgeUniqueIdBuilder() -{ -} - -/*---------------------------------------------------------------------------*/ -/*---------------------------------------------------------------------------*/ - /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ @@ -71,13 +63,13 @@ computeEdgesUniqueIds() info() << "Using version=" << edge_version << " to compute edges unique ids" << " mesh=" << m_mesh->name(); - if (edge_version==1) + if (edge_version == 1) _computeEdgesUniqueIdsParallel3(); - else if (edge_version==2) + else if (edge_version == 2) _computeEdgesUniqueIdsParallelV2(); - else if (edge_version==3) + else if (edge_version == 3) _computeEdgesUniqueIdsParallel64bit(); - else if (edge_version==0) + else if (edge_version == 0) info() << "No renumbering for edges"; else ARCANE_FATAL("Invalid valid version '{0}'. Valid values are 0, 1, 2 or 3"); @@ -92,7 +84,7 @@ computeEdgesUniqueIds() // edges ont été modifiés edges_map.notifyUniqueIdsChanged(); - if (m_mesh_builder->isVerbose()){ + if (m_mesh_builder->isVerbose()) { info() << "NEW EDGES_MAP after re-indexing"; edges_map.eachItem([&](Item edge) { info() << "Edge uid=" << edge.uniqueId() << " lid=" << edge.localId(); @@ -114,22 +106,26 @@ class T_CellEdgeInfo { public: - T_CellEdgeInfo(Int64 uid,Integer nb_back_edge,Integer nb_true_boundary_edge) - : m_unique_id(uid), m_nb_back_edge(nb_back_edge), m_nb_true_boundary_edge(nb_true_boundary_edge) + T_CellEdgeInfo(Int64 uid, Integer nb_back_edge, Integer nb_true_boundary_edge) + : m_unique_id(uid) + , m_nb_back_edge(nb_back_edge) + , m_nb_true_boundary_edge(nb_true_boundary_edge) { } T_CellEdgeInfo() - : m_unique_id(NULL_ITEM_ID), m_nb_back_edge(0), m_nb_true_boundary_edge(0) + : m_unique_id(NULL_ITEM_ID) + , m_nb_back_edge(0) + , m_nb_true_boundary_edge(0) { } public: bool operator<(const T_CellEdgeInfo& ci) const - { - return m_unique_idkey(); - exchanger->addSender(sd); - } - exchanger->initializeCommunicationsMessages(); - { - for( Integer i=0, ns=exchanger->nbSender(); imessageToSend(i); - Int32 rank = sm->destination().value(); - ISerializer* s = sm->serializer(); - Int64ConstArrayView infos = boundary_infos_to_send[rank]; - Integer nb_info = infos.size(); - s->setMode(ISerializer::ModeReserve); - s->reserve(DT_Int64,1); // Pour le nombre d'elements - s->reserveSpan(DT_Int64,nb_info); // Pour les elements - s->allocateBuffer(); - s->setMode(ISerializer::ModePut); - //info() << " SEND1 rank=" << rank << " nb_info=" << nb_info; - s->putInt64(nb_info); - s->putSpan(infos); - } - } - exchanger->processExchange(); - debug() << "END EXCHANGE"; -} - -template +template class ItemInfoMultiList { public: @@ -182,37 +143,165 @@ class ItemInfoMultiList class MyInfo { public: - MyInfo(const DataType& d,Integer n) : data(d), next_index(n) {} + + MyInfo(const DataType& d, Integer n) + : data(d) + , next_index(n) + {} + public: + DataType data; Integer next_index; }; public: - ItemInfoMultiList() : m_last_index(5000,true) {} + + ItemInfoMultiList() + : m_last_index(5000, true) + {} public: - void add(Int64 node_uid,const DataType& data) + void add(Int64 node_uid, const DataType& data) { Integer current_index = m_values.size(); bool is_add = false; - HashTableMapT::Data* d = m_last_index.lookupAdd(node_uid,-1,is_add); + HashTableMapT::Data* d = m_last_index.lookupAdd(node_uid, -1, is_add); - m_values.add(MyInfo(data,d->value())); + m_values.add(MyInfo(data, d->value())); d->value() = current_index; } public: + UniqueArray m_values; - HashTableMapT m_last_index; + HashTableMapT m_last_index; }; +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +class Parallel3EdgeUniqueIdBuilder +: public TraceAccessor +{ + using BoundaryInfosMap = std::unordered_map>; + + public: + + Parallel3EdgeUniqueIdBuilder(ITraceMng* tm, DynamicMeshIncrementalBuilder* mesh_builder, + Int64 max_node_uid); + + public: + + void compute(); + + private: + + DynamicMesh* m_mesh = nullptr; + DynamicMeshIncrementalBuilder* m_mesh_builder = nullptr; + IParallelMng* m_parallel_mng = nullptr; + const Int32 m_my_rank = A_NULL_RANK; + const Int32 m_nb_rank = A_NULL_RANK; + BoundaryInfosMap m_boundary_infos_to_send; + NodeUidToSubDomain m_uid_to_subdomain_converter; + std::unordered_map> m_nodes_info; + UniqueArray m_is_boundary_nodes; + bool m_is_verbose = false; + + private: + + void _exchangeData(IParallelExchanger* exchanger); + void _addEdgeBoundaryInfo(Edge edge); + void _computeEdgesUniqueId(); + void _sendInfosToOtherRanks(); +}; + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +Parallel3EdgeUniqueIdBuilder:: +Parallel3EdgeUniqueIdBuilder(ITraceMng* tm, DynamicMeshIncrementalBuilder* mesh_builder, Int64 max_node_uid) +: TraceAccessor(tm) +, m_mesh(mesh_builder->mesh()) +, m_mesh_builder(mesh_builder) +, m_parallel_mng(m_mesh->parallelMng()) +, m_my_rank(m_parallel_mng->commRank()) +, m_nb_rank(m_parallel_mng->commSize()) +, m_uid_to_subdomain_converter(max_node_uid, m_nb_rank) +, m_is_verbose(m_mesh_builder->isVerbose()) +{ +} + /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /*! - \brief Calcul les numéros uniques de chaque edge en parallèle. + * //COPIE DEPUIS GhostLayerBuilder. + * Faire une classe unique. + */ +void Parallel3EdgeUniqueIdBuilder:: +_exchangeData(IParallelExchanger* exchanger) +{ + for (const auto& [key, value] : m_boundary_infos_to_send) { + exchanger->addSender(key); + } + exchanger->initializeCommunicationsMessages(); + { + for (Integer i = 0, ns = exchanger->nbSender(); i < ns; ++i) { + ISerializeMessage* sm = exchanger->messageToSend(i); + Int32 rank = sm->destination().value(); + ISerializer* s = sm->serializer(); + ConstArrayView infos = m_boundary_infos_to_send[rank]; + Integer nb_info = infos.size(); + s->setMode(ISerializer::ModeReserve); + s->reserve(DT_Int64, 1); // Pour le nombre d'éléments + s->reserveSpan(DT_Int64, nb_info); // Pour les elements + s->allocateBuffer(); + s->setMode(ISerializer::ModePut); + //info() << " SEND1 rank=" << rank << " nb_info=" << nb_info; + s->putInt64(nb_info); + s->putSpan(infos); + } + } + exchanger->processExchange(); + debug() << "END EXCHANGE"; +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +void Parallel3EdgeUniqueIdBuilder:: +_addEdgeBoundaryInfo(Edge edge) +{ + Node first_node = edge.node(0); + Int64 first_node_uid = first_node.uniqueId(); + SharedArray v; + Int32 dest_rank = -1; + if (!m_is_boundary_nodes[first_node.localId()]) { + v = m_nodes_info[first_node_uid]; + } + else { + dest_rank = m_uid_to_subdomain_converter.uidToRank(first_node_uid); + v = m_boundary_infos_to_send[dest_rank]; + } + v.add(first_node_uid); // 0 + v.add(m_my_rank); // 1 + v.add(edge.uniqueId()); // 2 + v.add(edge.type()); // 3 + v.add(NULL_ITEM_UNIQUE_ID); // 4 : only used for debug + v.add(NULL_ITEM_UNIQUE_ID); // 5 : only used for debug + if (m_is_verbose) + info() << "Edge uid=" << edge.uniqueId() << " n0,n1=" << edge.node(0).uniqueId() << "," << edge.node(1).uniqueId() + << " n0=" << ItemPrinter(edge.node(0)) << " n1=" << ItemPrinter(edge.node(1)) << " dest_rank=" << dest_rank; + for (Node edge_node : edge.nodes()) + v.add(edge_node.uniqueId()); +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/*! + \brief Calcule les numéros uniques de chaque edge en parallèle. NEW VERSION. @@ -224,275 +313,266 @@ class ItemInfoMultiList suppose qu'une face frontière n'existe que dans une seule partie (un seul rang) ce qui n'est pas le cas pour les arêtes. On se retrouve alors avec des sous-domaines qui n'ont pas leurs arêtes renumérotées. -*/ -void EdgeUniqueIdBuilder:: -_computeEdgesUniqueIdsParallel3() +*/ +void Parallel3EdgeUniqueIdBuilder:: +compute() { - const bool is_verbose = m_mesh_builder->isVerbose(); IParallelMng* pm = m_mesh->parallelMng(); - Integer my_rank = pm->commRank(); - Integer nb_rank = pm->commSize(); Integer nb_local_edge = m_mesh_builder->oneMeshItemAdder()->nbEdge(); info() << "ComputeEdgesUniqueIdsParallel3 nb_edge=" << nb_local_edge; - //Integer nb_local_cell = m_mesh_builder->nbCell(); - //bool is_verbose = m_mesh_builder->isVerbose(); - - Int64UniqueArray edges_opposite_cell_uid(nb_local_edge); + + UniqueArray edges_opposite_cell_uid(nb_local_edge); edges_opposite_cell_uid.fill(NULL_ITEM_ID); - IntegerUniqueArray edges_opposite_cell_index(nb_local_edge); - IntegerUniqueArray edges_opposite_cell_owner(nb_local_edge); + UniqueArray edges_opposite_cell_index(nb_local_edge); + UniqueArray edges_opposite_cell_owner(nb_local_edge); // Pour vérification, s'assure que tous les éléments de ce tableau // sont valides, ce qui signifie que toutes les edges ont bien été - // renumérotés - Int64UniqueArray edges_new_uid(nb_local_edge); - edges_new_uid.fill(NULL_ITEM_ID); - - //UniqueArray edges_local_infos(m_mesh_nb_edge); + // renumérotés. + UniqueArray edges_new_uid(nb_local_edge); + edges_new_uid.fill(NULL_ITEM_UNIQUE_ID); - //Integer nb_recv_sub_domain_boundary_edge = 0; - - Int64UniqueArray edges_infos; + UniqueArray edges_infos; edges_infos.reserve(10000); - //ItemInternalMap& cells_map = m_mesh->cellsMap(); ItemInternalMap& edges_map = m_mesh->edgesMap(); ItemInternalMap& faces_map = m_mesh->facesMap(); // utilisé pour détecter le bord - ItemInternalMap& nodes_map = m_mesh->nodesMap(); - // NOTE: ce tableau n'est pas utile sur toutes les mailles. Il - // suffit qu'il contienne les mailles dont on a besoin, c'est à dire - // les notres + celles connectées à une de nos edges. - HashTableMapT cell_first_edge_uid(m_mesh_builder->oneMeshItemAdder()->nbCell()*2,true); - //OLD Int64UniqueArray cell_first_edge_uid(global_max_cell_uid+1); - //OLD cell_first_edge_uid.fill(0); + // NOTE : ce tableau n'est pas utile sur toutes les mailles. Il + // suffit qu'il contienne les mailles dont on a besoin, c'est-à-dire + // les nôtres + celles connectées à une de nos edges. + HashTableMapT cell_first_edge_uid(m_mesh_builder->oneMeshItemAdder()->nbCell() * 2, true); // Rassemble les données des autres processeurs dans recv_cells; // Pour éviter que les tableaux ne soient trop gros, on procède en plusieurs // étapes. - // Chaque sous-domaine construit sa liste de edges frontières, avec pour - // chaque edge: - // - son type - // - la liste de ses noeuds, - // - le numéro unique de sa maille - // - le propriétaire de sa maille - // - son indice dans sa maille + // Chaque sous-domaine construit sa liste des arêtes frontières, avec pour + // chaque arête : + // - son type, + // - la liste de ses noeuds, + // - le numéro unique de sa maille, + // - le propriétaire de sa maille, + // - son indice dans sa maille, // Cette liste sera ensuite envoyée à tous les sous-domaines. - ItemTypeMng* itm = m_mesh->itemTypeMng(); - // Détermine le unique id max des noeuds - Int64 my_max_node_uid = NULL_ITEM_UNIQUE_ID; - nodes_map.eachItem([&](Item item) { - Int64 node_uid = item.uniqueId(); - if (node_uid>my_max_node_uid) - my_max_node_uid = node_uid; - }); - Int64 global_max_node_uid = pm->reduce(Parallel::ReduceMax,my_max_node_uid); - debug() << "NODE_UID_INFO: MY_MAX_UID=" << my_max_node_uid - << " GLOBAL=" << global_max_node_uid; - - //TODO: choisir bonne valeur pour initialiser la table - BoundaryInfosMap boundary_infos_to_send(nb_rank,true); - NodeUidToSubDomain uid_to_subdomain_converter(global_max_node_uid,nb_rank); - - HashTableMapT > nodes_info(100000,true); IItemFamily* node_family = m_mesh->nodeFamily(); - UniqueArray is_boundary_nodes(node_family->maxLocalId(),false); + m_is_boundary_nodes.resize(node_family->maxLocalId(), false); - // Marque tous les noeuds frontieres car ce sont ceux qu'il faudra envoyer + // Marque tous les noeuds frontières, car ce sont ceux qu'il faudra envoyer + // Un noeud est considéré comme frontière s'il appartient à une face qui n'a qu'une + // maille connectée. faces_map.eachItem([&](Face face) { Integer face_nb_cell = face.nbCell(); - if (face_nb_cell==1){ - for( Int32 ilid : face.nodeIds() ) - is_boundary_nodes[ilid] = true; + if (face_nb_cell == 1) { + for (Int32 ilid : face.nodeIds()) + m_is_boundary_nodes[ilid] = true; } }); - // Détermine la liste des edges frontières - edges_map.eachItem([&](Edge edge) { - Node first_node = edge.node(0); - Int64 first_node_uid = first_node.uniqueId(); - SharedArray v; - Int32 dest_rank = -1; - if (!is_boundary_nodes[first_node.localId()]){ - v = nodes_info.lookupAdd(first_node_uid)->value(); - } - else{ - dest_rank = uid_to_subdomain_converter.uidToRank(first_node_uid); - v = boundary_infos_to_send.lookupAdd(dest_rank)->value(); - } - v.add(first_node_uid); // 0 - v.add(my_rank); // 1 - v.add(edge.uniqueId()); // 2 - v.add(edge.type()); // 3 - v.add(NULL_ITEM_UNIQUE_ID); // 4 : only used for debug - v.add(NULL_ITEM_UNIQUE_ID); // 5 : only used for debug - if (is_verbose) - info() << "Edge uid=" << edge.uniqueId() << " n0,n1=" << edge.node(0).uniqueId() << "," << edge.node(1).uniqueId() - << " n0=" << ItemPrinter(edge.node(0)) << " n1=" << ItemPrinter(edge.node(1)) << " dest_rank=" << dest_rank; - for( Node edge_node : edge.nodes() ) - v.add(edge_node.uniqueId()); - }); + // Détermine la liste des arêtes frontières. + // L'ordre de cette liste dépend de l'implémentation de la table de hashage. + // Afin d'avoir la même numérotation que la version historique (qui utilise HashTableMapT), + // on utilise une instance temporaire de cette classe pour ce calcul si + // l'implémentation utilisée est différente. C'est le cas à partir d'octobre 2024. + // A terme, il faudrait utiliser une autre version du calcul des uniqueId() des + // arêtes. + // TODO: Ce mécanisme est en test. A vérifier que cela donne ensuite + // la même numérotation. + const bool is_new_item_map_impl = ItemInternalMap::UseNewImpl; + if (is_new_item_map_impl) { + info() << "Edge: ItemInternalMap is using new implementation"; + HashTableMapT old_edges_map(5000, false); + edges_map.eachItem([&](Edge edge) { + old_edges_map.add(edge.uniqueId(), edge); + }); + old_edges_map.eachValue([&](Edge edge) { + _addEdgeBoundaryInfo(edge); + }); + } + else { + edges_map.eachItem([&](Edge edge) { + _addEdgeBoundaryInfo(edge); + }); + } - // Positionne la liste des envoies - Ref exchanger{ParallelMngUtils::createExchangerRef(pm)}; - _exchangeData(exchanger.get(),boundary_infos_to_send); + _computeEdgesUniqueId(); + _sendInfosToOtherRanks(); - { - Integer nb_receiver = exchanger->nbReceiver(); - debug() << "NB RECEIVER=" << nb_receiver; - SharedArray received_infos; - for( Integer i=0; imessageToReceive(i); - //Int32 orig_rank = sm->destSubDomain(); - ISerializer* s = sm->serializer(); - s->setMode(ISerializer::ModeGet); - Int64 nb_info = s->getInt64(); - //info() << "RECEIVE NB_INFO=" << nb_info << " from=" << orig_rank; - received_infos.resize(nb_info); - s->getSpan(received_infos); - //if ((nb_info % 3)!=0) - //fatal() << "info size can not be divided by 3"; - Integer z =0; - while(ztypeFromId(edge_type); - Integer edge_nb_node = itt->nbLocalNode(); - Int64Array& a = nodes_info.lookupAdd(node_uid)->value(); - a.addRange(Int64ConstArrayView(6+edge_nb_node,&received_infos[z])); - z += 6; - z += edge_nb_node; - //info() << "NODE UID=" << node_uid << " sender=" << sender_rank - // << " edge_uid=" << edge_uid; - //node_cell_list.add(node_uid,cell_uid,cell_owner); - //HashTableMapT::Data* v = nodes_nb_cell.lookupAdd(node_uid); - //++v->value(); - } + traceMng()->flush(); + pm->barrier(); + info() << "END OF TEST NEW EDGE COMPUTE"; +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +void Parallel3EdgeUniqueIdBuilder:: +_computeEdgesUniqueId() +{ + ItemTypeMng* itm = m_mesh->itemTypeMng(); + IParallelMng* pm = m_parallel_mng; + Ref exchanger{ ParallelMngUtils::createExchangerRef(pm) }; + _exchangeData(exchanger.get()); + + Integer nb_receiver = exchanger->nbReceiver(); + debug() << "NB RECEIVER=" << nb_receiver; + SharedArray received_infos; + for (Integer i = 0; i < nb_receiver; ++i) { + ISerializeMessage* sm = exchanger->messageToReceive(i); + //Int32 orig_rank = sm->destSubDomain(); + ISerializer* s = sm->serializer(); + s->setMode(ISerializer::ModeGet); + Int64 nb_info = s->getInt64(); + //info() << "RECEIVE NB_INFO=" << nb_info << " from=" << orig_rank; + received_infos.resize(nb_info); + s->getSpan(received_infos); + //if ((nb_info % 3)!=0) + //fatal() << "info size can not be divided by 3"; + Integer z = 0; + while (z < nb_info) { + Int64 node_uid = received_infos[z + 0]; + //Int64 sender_rank = received_infos[z+1]; + //Int64 edge_uid = received_infos[z+2]; + Int32 edge_type = (Int32)received_infos[z + 3]; + // received_infos[z+4]; + // received_infos[z+5]; + ItemTypeInfo* itt = itm->typeFromId(edge_type); + Integer edge_nb_node = itt->nbLocalNode(); + Int64Array& a = m_nodes_info[node_uid]; + a.addRange(Int64ConstArrayView(6 + edge_nb_node, &received_infos[z])); + z += 6; + z += edge_nb_node; + //info() << "NODE UID=" << node_uid << " sender=" << sender_rank + // << " edge_uid=" << edge_uid; + //node_cell_list.add(node_uid,cell_uid,cell_owner); + //HashTableMapT::Data* v = nodes_nb_cell.lookupAdd(node_uid); + //++v->value(); } - Integer my_max_edge_node = 0; - for( HashTableMapT >::Enumerator inode(nodes_info); ++inode; ){ - //Int64 key = inode.data()->key(); - Int64ConstArrayView a = *inode; - //info() << "A key=" << key << " size=" << a.size(); - Integer nb_info = a.size(); - Integer z = 0; - Integer node_nb_edge = 0; - while(ztypeFromId(edge_type); - Integer edge_nb_node = itt->nbLocalNode(); - /*info() << "NODE2 UID=" << node_uid << " sender=" << sender_rank + } + + Integer my_max_edge_node = 0; + for (const auto& [key, value] : m_nodes_info) { + //Int64 key = inode.data()->key(); + Int64ConstArrayView a = value; + //info() << "A key=" << key << " size=" << a.size(); + Integer nb_info = a.size(); + Integer z = 0; + Integer node_nb_edge = 0; + while (z < nb_info) { + ++node_nb_edge; + //Int64 node_uid = a[z+0]; + //Int64 sender_rank = a[z+1]; + //Int64 edge_uid = a[z+2]; + Int32 edge_type = (Int32)a[z + 3]; + // a[z+4]; + // a[z+5]; + ItemTypeInfo* itt = itm->typeFromId(edge_type); + Integer edge_nb_node = itt->nbLocalNode(); + /*info() << "NODE2 UID=" << node_uid << " sender=" << sender_rank << " edge_uid=" << edge_uid */ - //for( Integer y=0; yreduce(Parallel::ReduceMax,my_max_edge_node); - debug() << "GLOBAL MAX EDGE NODE=" << global_max_edge_node; - // OK, maintenant donne comme uid de la edge (node_uid * global_max_edge_node + index) - IntegerUniqueArray indexes; - boundary_infos_to_send = BoundaryInfosMap(nb_rank,true); - - for( HashTableMapT >::Enumerator inode(nodes_info); ++inode; ){ - //Int64 key = inode.data()->key(); - Int64ConstArrayView a = *inode; - //info() << "A key=" << key << " size=" << a.size(); - Integer nb_info = a.size(); - Integer z = 0; - Integer node_nb_edge = 0; - indexes.clear(); - while(ztypeFromId(edge_type); - Integer edge_nb_node = itt->nbLocalNode(); - - // Regarde si la edge est déjà dans la liste: - Integer edge_index = node_nb_edge; - Int32 edge_new_owner = sender_rank; - for( Integer y=0; yreduce(Parallel::ReduceMax, my_max_edge_node); + debug() << "GLOBAL MAX EDGE NODE=" << global_max_edge_node; + // OK, maintenant donne comme uid de la edge (node_uid * global_max_edge_node + index) + IntegerUniqueArray indexes; + m_boundary_infos_to_send.clear(); + + for (const auto& [key, value] : m_nodes_info) { + Int64ConstArrayView a = value; + Integer nb_info = a.size(); + Integer z = 0; + Integer node_nb_edge = 0; + indexes.clear(); + while (z < nb_info) { + Int64 node_uid = a[z + 0]; + Int32 sender_rank = (Int32)a[z + 1]; + Int64 edge_uid = a[z + 2]; + Int32 edge_type = (Int32)a[z + 3]; + // a[z+4]; + // a[z+5]; + ItemTypeInfo* itt = itm->typeFromId(edge_type); + Integer edge_nb_node = itt->nbLocalNode(); + + // Regarde si la edge est déjà dans la liste: + Integer edge_index = node_nb_edge; + Int32 edge_new_owner = sender_rank; + for (Integer y = 0; y < node_nb_edge; ++y) { + if (memcmp(&a[indexes[y] + 6], &a[z + 6], sizeof(Int64) * edge_nb_node) == 0) { + edge_index = y; + edge_new_owner = (Int32)a[indexes[y] + 1]; } - Int64 edge_new_uid = (node_uid * global_max_edge_node) + edge_index; - Int64Array& v = boundary_infos_to_send.lookupAdd(sender_rank)->value(); - // Indique au propriétaire de cette edge son nouvel uid - v.add(edge_uid); - v.add(edge_new_uid); - v.add(edge_new_owner); - indexes.add(z); - z += 6; - z += edge_nb_node; - /*info() << "NODE3 UID=" << node_uid << " sender=" << sender_rank - << " edge_uid=" << edge_uid - << " edge_index=" << edge_index;*/ - ++node_nb_edge; } - my_max_edge_node = math::max(node_nb_edge,my_max_edge_node); + Int64 edge_new_uid = (node_uid * global_max_edge_node) + edge_index; + Int64Array& v = m_boundary_infos_to_send[sender_rank]; + // Indique au propriétaire de cette arête son nouvel uid + v.add(edge_uid); + v.add(edge_new_uid); + v.add(edge_new_owner); + indexes.add(z); + z += 6; + z += edge_nb_node; + /* info() << "NODE3 UID=" << node_uid << " sender=" << sender_rank + << " edge_uid=" << edge_uid + << " edge_index=" << edge_index + << " edge_new_uid=" << edge_new_uid; */ + ++node_nb_edge; } + my_max_edge_node = math::max(node_nb_edge, my_max_edge_node); } - exchanger = ParallelMngUtils::createExchangerRef(pm); +} - _exchangeData(exchanger.get(),boundary_infos_to_send); - { - Integer nb_receiver = exchanger->nbReceiver(); - debug() << "NB RECEIVER=" << nb_receiver; - Int64UniqueArray received_infos; - for( Integer i=0; imessageToReceive(i); - auto orig_rank = sm->destination(); - ISerializer* s = sm->serializer(); - s->setMode(ISerializer::ModeGet); - Int64 nb_info = s->getInt64(); +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +void Parallel3EdgeUniqueIdBuilder:: +_sendInfosToOtherRanks() +{ + const bool is_verbose = m_mesh_builder->isVerbose(); + IParallelMng* pm = m_parallel_mng; + Ref exchanger = ParallelMngUtils::createExchangerRef(pm); + + _exchangeData(exchanger.get()); + + ItemInternalMap& edges_map = m_mesh->edgesMap(); + Integer nb_receiver = exchanger->nbReceiver(); + debug() << "NB RECEIVER=" << nb_receiver; + Int64UniqueArray received_infos; + for (Integer i = 0; i < nb_receiver; ++i) { + ISerializeMessage* sm = exchanger->messageToReceive(i); + auto orig_rank = sm->destination(); + ISerializer* s = sm->serializer(); + s->setMode(ISerializer::ModeGet); + Int64 nb_info = s->getInt64(); + if (is_verbose) + info() << "RECEIVE NB_INFO=" << nb_info << " from=" << orig_rank; + received_infos.resize(nb_info); + s->getSpan(received_infos); + if ((nb_info % 3) != 0) + ARCANE_FATAL("info size can not be divided by 3 x={0}", nb_info); + Int64 nb_item = nb_info / 3; + for (Int64 z = 0; z < nb_item; ++z) { + Int64 old_uid = received_infos[(z * 3)]; + Int64 new_uid = received_infos[(z * 3) + 1]; + Int32 new_owner = static_cast(received_infos[(z * 3) + 2]); + //info() << "EDGE old_uid=" << old_uid << " new_uid=" << new_uid; + impl::MutableItemBase iedge(edges_map.tryFind(old_uid)); + if (iedge.null()) + ARCANE_FATAL("Can not find own edge uid={0}", old_uid); + iedge.setUniqueId(new_uid); + iedge.setOwner(new_owner, m_my_rank); + Edge edge{ iedge }; if (is_verbose) - info() << "RECEIVE NB_INFO=" << nb_info << " from=" << orig_rank; - received_infos.resize(nb_info); - s->getSpan(received_infos); - if ((nb_info % 3)!=0) - ARCANE_FATAL("info size can not be divided by 3 x={0}",nb_info); - Int64 nb_item = nb_info / 3; - for (Int64 z=0; z(received_infos[(z * 3) + 2]); - //info() << "EDGE old_uid=" << old_uid << " new_uid=" << new_uid; - impl::MutableItemBase iedge(edges_map.tryFind(old_uid)); - if (iedge.null()) - ARCANE_FATAL("Can not find own edge uid={0}",old_uid); - iedge.setUniqueId(new_uid); - iedge.setOwner(new_owner, my_rank); - Edge edge{iedge}; - if (is_verbose) - info() << "SetEdgeOwner uid=" << new_uid << " owner=" << new_owner - << " n0,n1=" << edge.node(0).uniqueId() << "," << edge.node(1).uniqueId() - << " n0=" << ItemPrinter(edge.node(0)) << " n1=" << ItemPrinter(edge.node(1)); - } + info() << "SetEdgeOwner uid=" << new_uid << " owner=" << new_owner + << " n0,n1=" << edge.node(0).uniqueId() << "," << edge.node(1).uniqueId() + << " n0=" << ItemPrinter(edge.node(0)) << " n1=" << ItemPrinter(edge.node(1)); } } - - traceMng()->flush(); - pm->barrier(); - info() << "END OF TEST NEW EDGE COMPUTE"; } /*---------------------------------------------------------------------------*/ @@ -653,6 +733,30 @@ _computeEdgesUniqueIdsParallelV2() /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ +void EdgeUniqueIdBuilder:: +_computeEdgesUniqueIdsParallel3() +{ + IParallelMng* pm = m_mesh->parallelMng(); + ItemInternalMap& nodes_map = m_mesh->nodesMap(); + + // Détermine le maximum des uniqueId() des noeuds + Int64 my_max_node_uid = NULL_ITEM_UNIQUE_ID; + nodes_map.eachItem([&](Item item) { + Int64 node_uid = item.uniqueId(); + if (node_uid > my_max_node_uid) + my_max_node_uid = node_uid; + }); + Int64 global_max_node_uid = pm->reduce(Parallel::ReduceMax, my_max_node_uid); + debug() << "NODE_UID_INFO: MY_MAX_UID=" << my_max_node_uid + << " GLOBAL=" << global_max_node_uid; + + Parallel3EdgeUniqueIdBuilder builder(traceMng(), m_mesh_builder, global_max_node_uid); + builder.compute(); +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + void EdgeUniqueIdBuilder:: _computeEdgesUniqueIdsParallel64bit() { diff --git a/arcane/src/arcane/mesh/EdgeUniqueIdBuilder.h b/arcane/src/arcane/mesh/EdgeUniqueIdBuilder.h index 8c69ff06e..2539ff372 100644 --- a/arcane/src/arcane/mesh/EdgeUniqueIdBuilder.h +++ b/arcane/src/arcane/mesh/EdgeUniqueIdBuilder.h @@ -52,7 +52,6 @@ class EdgeUniqueIdBuilder //! Construit une instance pour le maillage \a mesh explicit EdgeUniqueIdBuilder(DynamicMeshIncrementalBuilder* mesh_builder); - ~EdgeUniqueIdBuilder() override; public: @@ -67,7 +66,6 @@ class EdgeUniqueIdBuilder void _computeEdgesUniqueIdsSequential(); void _computeEdgesUniqueIdsParallel3(); - void _exchangeData(IParallelExchanger* exchanger,BoundaryInfosMap& boundary_infos_to_send); void _computeEdgesUniqueIdsParallelV2(); void _computeEdgesUniqueIdsParallel64bit(); }; diff --git a/arcane/src/arcane/mesh/ItemInternalMap.h b/arcane/src/arcane/mesh/ItemInternalMap.h index f07090ffe..b7537c8b2 100644 --- a/arcane/src/arcane/mesh/ItemInternalMap.h +++ b/arcane/src/arcane/mesh/ItemInternalMap.h @@ -64,6 +64,8 @@ class ItemInternalMap using NewImpl = std::unordered_map; using BaseData = LegacyImpl::Data; + public: + #ifdef ARCANE_USE_NEW_IMPL_FOR_ITEMINTERNALMAP static constexpr bool UseNewImpl = 1; #else