From b79fe22fff66964c19ae073cedb698b7156b36bd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Del=20Pino?= <stephane.delpino44@gmail.com>
Date: Tue, 18 Feb 2025 19:20:01 +0100
Subject: [PATCH] Fix ref item list exchange for load balancing

---
 src/mesh/ConnectivityDispatcher.cpp | 248 ++++++++++++++--------------
 1 file changed, 123 insertions(+), 125 deletions(-)

diff --git a/src/mesh/ConnectivityDispatcher.cpp b/src/mesh/ConnectivityDispatcher.cpp
index 45e5ebd8a..d78d400e2 100644
--- a/src/mesh/ConnectivityDispatcher.cpp
+++ b/src/mesh/ConnectivityDispatcher.cpp
@@ -590,151 +590,149 @@ ConnectivityDispatcher<Dimension>::_buildItemReferenceList()
   }();
 
   if (number_of_item_list_sender > 0) {
-    if (number_of_item_list_sender < parallel::size()) {
-      const size_t sender_rank = [&]() {
-        size_t i_rank = 0;
-        for (; i_rank < parallel::size(); ++i_rank) {
-          if (number_of_item_ref_list_per_proc[i_rank] > 0) {
-            break;
-          }
-        }
-        return i_rank;
-      }();
-
-      Assert(number_of_item_list_sender < parallel::size());
-
-      // sending is boundary property
-      Array<RefItemListBase::Type> ref_item_list_type{number_of_item_ref_list_per_proc[sender_rank]};
-      if (parallel::rank() == sender_rank) {
-        for (size_t i_item_ref_list = 0; i_item_ref_list < m_connectivity.template numberOfRefItemList<item_type>();
-             ++i_item_ref_list) {
-          auto item_ref_list                  = m_connectivity.template refItemList<item_type>(i_item_ref_list);
-          ref_item_list_type[i_item_ref_list] = item_ref_list.type();
+    const size_t sender_rank = [&]() {
+      size_t i_rank = 0;
+      for (; i_rank < parallel::size(); ++i_rank) {
+        if (number_of_item_ref_list_per_proc[i_rank] > 0) {
+          break;
         }
       }
-      parallel::broadcast(ref_item_list_type, sender_rank);
-
-      // sending references tags
-      Array<RefId::TagNumberType> ref_tag_list{number_of_item_ref_list_per_proc[sender_rank]};
-      if (parallel::rank() == sender_rank) {
-        for (size_t i_item_ref_list = 0; i_item_ref_list < m_connectivity.template numberOfRefItemList<item_type>();
-             ++i_item_ref_list) {
-          auto item_ref_list            = m_connectivity.template refItemList<item_type>(i_item_ref_list);
-          ref_tag_list[i_item_ref_list] = item_ref_list.refId().tagNumber();
-        }
+      return i_rank;
+    }();
+
+    Assert(number_of_item_list_sender < parallel::size());
+
+    // sending is boundary property
+    Array<RefItemListBase::Type> ref_item_list_type{number_of_item_ref_list_per_proc[sender_rank]};
+    if (parallel::rank() == sender_rank) {
+      for (size_t i_item_ref_list = 0; i_item_ref_list < m_connectivity.template numberOfRefItemList<item_type>();
+           ++i_item_ref_list) {
+        auto item_ref_list                  = m_connectivity.template refItemList<item_type>(i_item_ref_list);
+        ref_item_list_type[i_item_ref_list] = item_ref_list.type();
       }
-      parallel::broadcast(ref_tag_list, sender_rank);
-
-      // sending references name size
-      Array<size_t> ref_name_size_list{number_of_item_ref_list_per_proc[sender_rank]};
-      if (parallel::rank() == sender_rank) {
-        for (size_t i_item_ref_list = 0; i_item_ref_list < m_connectivity.template numberOfRefItemList<item_type>();
-             ++i_item_ref_list) {
-          auto item_ref_list                  = m_connectivity.template refItemList<item_type>(i_item_ref_list);
-          ref_name_size_list[i_item_ref_list] = item_ref_list.refId().tagName().size();
-        }
+    }
+    parallel::broadcast(ref_item_list_type, sender_rank);
+
+    // sending references tags
+    Array<RefId::TagNumberType> ref_tag_list{number_of_item_ref_list_per_proc[sender_rank]};
+    if (parallel::rank() == sender_rank) {
+      for (size_t i_item_ref_list = 0; i_item_ref_list < m_connectivity.template numberOfRefItemList<item_type>();
+           ++i_item_ref_list) {
+        auto item_ref_list            = m_connectivity.template refItemList<item_type>(i_item_ref_list);
+        ref_tag_list[i_item_ref_list] = item_ref_list.refId().tagNumber();
       }
-      parallel::broadcast(ref_name_size_list, sender_rank);
-
-      // sending references name size
-      Array<RefId::TagNameType::value_type> ref_name_cat{sum(ref_name_size_list)};
-      if (parallel::rank() == sender_rank) {
-        size_t i_char = 0;
-        for (size_t i_item_ref_list = 0; i_item_ref_list < m_connectivity.template numberOfRefItemList<item_type>();
-             ++i_item_ref_list) {
-          auto item_ref_list = m_connectivity.template refItemList<item_type>(i_item_ref_list);
-          for (auto c : item_ref_list.refId().tagName()) {
-            ref_name_cat[i_char++] = c;
-          }
-        }
+    }
+    parallel::broadcast(ref_tag_list, sender_rank);
+
+    // sending references name size
+    Array<size_t> ref_name_size_list{number_of_item_ref_list_per_proc[sender_rank]};
+    if (parallel::rank() == sender_rank) {
+      for (size_t i_item_ref_list = 0; i_item_ref_list < m_connectivity.template numberOfRefItemList<item_type>();
+           ++i_item_ref_list) {
+        auto item_ref_list                  = m_connectivity.template refItemList<item_type>(i_item_ref_list);
+        ref_name_size_list[i_item_ref_list] = item_ref_list.refId().tagName().size();
       }
-      parallel::broadcast(ref_name_cat, sender_rank);
-
-      std::vector<RefId> ref_id_list = [&]() {
-        std::vector<RefId> mutable_ref_id_list;
-        mutable_ref_id_list.reserve(ref_name_size_list.size());
-        size_t begining = 0;
-        for (size_t i_ref = 0; i_ref < ref_name_size_list.size(); ++i_ref) {
-          const size_t size = ref_name_size_list[i_ref];
-          mutable_ref_id_list.emplace_back(ref_tag_list[i_ref], std::string{&(ref_name_cat[begining]), size});
-          begining += size;
+    }
+    parallel::broadcast(ref_name_size_list, sender_rank);
+
+    // sending references name size
+    Array<RefId::TagNameType::value_type> ref_name_cat{sum(ref_name_size_list)};
+    if (parallel::rank() == sender_rank) {
+      size_t i_char = 0;
+      for (size_t i_item_ref_list = 0; i_item_ref_list < m_connectivity.template numberOfRefItemList<item_type>();
+           ++i_item_ref_list) {
+        auto item_ref_list = m_connectivity.template refItemList<item_type>(i_item_ref_list);
+        for (auto c : item_ref_list.refId().tagName()) {
+          ref_name_cat[i_char++] = c;
         }
-        return mutable_ref_id_list;
-      }();
-
-      using block_type            = int32_t;
-      constexpr size_t block_size = sizeof(block_type);
-      const size_t nb_block       = ref_id_list.size() / block_size + (ref_id_list.size() % block_size != 0);
-      for (size_t i_block = 0; i_block < nb_block; ++i_block) {
-        ItemValue<block_type, item_type> item_references(m_connectivity);
-        item_references.fill(0);
-
-        if (m_connectivity.template numberOfRefItemList<item_type>() > 0) {
-          const size_t max_i_ref = std::min(ref_id_list.size(), block_size * (i_block + 1));
-          for (size_t i_ref = block_size * i_block, i = 0; i_ref < max_i_ref; ++i_ref, ++i) {
-            block_type ref_bit{1 << i};
-            auto item_ref_list = m_connectivity.template refItemList<item_type>(i_ref);
-
-            const auto& item_list = item_ref_list.list();
-            for (size_t i_item = 0; i_item < item_list.size(); ++i_item) {
-              const ItemId& item_id = item_list[i_item];
-              item_references[item_id] |= ref_bit;
-            }
+      }
+    }
+    parallel::broadcast(ref_name_cat, sender_rank);
+
+    std::vector<RefId> ref_id_list = [&]() {
+      std::vector<RefId> mutable_ref_id_list;
+      mutable_ref_id_list.reserve(ref_name_size_list.size());
+      size_t begining = 0;
+      for (size_t i_ref = 0; i_ref < ref_name_size_list.size(); ++i_ref) {
+        const size_t size = ref_name_size_list[i_ref];
+        mutable_ref_id_list.emplace_back(ref_tag_list[i_ref], std::string{&(ref_name_cat[begining]), size});
+        begining += size;
+      }
+      return mutable_ref_id_list;
+    }();
+
+    using block_type            = int32_t;
+    constexpr size_t block_size = sizeof(block_type);
+    const size_t nb_block       = ref_id_list.size() / block_size + (ref_id_list.size() % block_size != 0);
+    for (size_t i_block = 0; i_block < nb_block; ++i_block) {
+      ItemValue<block_type, item_type> item_references(m_connectivity);
+      item_references.fill(0);
+
+      if (m_connectivity.template numberOfRefItemList<item_type>() > 0) {
+        const size_t max_i_ref = std::min(ref_id_list.size(), block_size * (i_block + 1));
+        for (size_t i_ref = block_size * i_block, i = 0; i_ref < max_i_ref; ++i_ref, ++i) {
+          block_type ref_bit{1 << i};
+          auto item_ref_list = m_connectivity.template refItemList<item_type>(i_ref);
+
+          const auto& item_list = item_ref_list.list();
+          for (size_t i_item = 0; i_item < item_list.size(); ++i_item) {
+            const ItemId& item_id = item_list[i_item];
+            item_references[item_id] |= ref_bit;
           }
         }
+      }
 
-        const auto& nb_item_to_send_by_proc = this->_dispatchedInfo<item_type>().m_list_to_send_size_by_proc;
+      const auto& nb_item_to_send_by_proc = this->_dispatchedInfo<item_type>().m_list_to_send_size_by_proc;
 
-        const auto& send_item_id_by_proc = this->_dispatchedInfo<item_type>().m_list_to_send_by_proc;
+      const auto& send_item_id_by_proc = this->_dispatchedInfo<item_type>().m_list_to_send_by_proc;
 
-        std::vector<Array<const block_type>> send_item_refs_by_proc(parallel::size());
+      std::vector<Array<const block_type>> send_item_refs_by_proc(parallel::size());
 
-        for (size_t i_rank = 0; i_rank < parallel::size(); ++i_rank) {
-          Array<block_type> send_item_refs(nb_item_to_send_by_proc[i_rank]);
-          const Array<const ItemId> send_item_id = send_item_id_by_proc[i_rank];
-          parallel_for(
-            send_item_id.size(), PUGS_LAMBDA(size_t l) {
-              const ItemId& item_id = send_item_id[l];
-              send_item_refs[l]     = item_references[item_id];
-            });
-          send_item_refs_by_proc[i_rank] = send_item_refs;
-        }
+      for (size_t i_rank = 0; i_rank < parallel::size(); ++i_rank) {
+        Array<block_type> send_item_refs(nb_item_to_send_by_proc[i_rank]);
+        const Array<const ItemId> send_item_id = send_item_id_by_proc[i_rank];
+        parallel_for(
+          send_item_id.size(), PUGS_LAMBDA(size_t l) {
+            const ItemId& item_id = send_item_id[l];
+            send_item_refs[l]     = item_references[item_id];
+          });
+        send_item_refs_by_proc[i_rank] = send_item_refs;
+      }
 
-        std::vector<Array<block_type>> recv_item_refs_by_proc(parallel::size());
-        for (size_t i_rank = 0; i_rank < parallel::size(); ++i_rank) {
-          recv_item_refs_by_proc[i_rank] =
-            Array<block_type>(this->_dispatchedInfo<item_type>().m_list_to_recv_size_by_proc[i_rank]);
-        }
-        parallel::exchange(send_item_refs_by_proc, recv_item_refs_by_proc);
-
-        const auto& recv_item_id_correspondance_by_proc =
-          this->_dispatchedInfo<item_type>().m_recv_id_correspondance_by_proc;
-        std::vector<block_type> item_refs(m_new_descriptor.template itemNumberVector<item_type>().size());
-        for (size_t i_rank = 0; i_rank < parallel::size(); ++i_rank) {
-          for (size_t r = 0; r < recv_item_refs_by_proc[i_rank].size(); ++r) {
-            const ItemId& item_id = recv_item_id_correspondance_by_proc[i_rank][r];
-            item_refs[item_id]    = recv_item_refs_by_proc[i_rank][r];
-          }
+      std::vector<Array<block_type>> recv_item_refs_by_proc(parallel::size());
+      for (size_t i_rank = 0; i_rank < parallel::size(); ++i_rank) {
+        recv_item_refs_by_proc[i_rank] =
+          Array<block_type>(this->_dispatchedInfo<item_type>().m_list_to_recv_size_by_proc[i_rank]);
+      }
+      parallel::exchange(send_item_refs_by_proc, recv_item_refs_by_proc);
+
+      const auto& recv_item_id_correspondance_by_proc =
+        this->_dispatchedInfo<item_type>().m_recv_id_correspondance_by_proc;
+      std::vector<block_type> item_refs(m_new_descriptor.template itemNumberVector<item_type>().size());
+      for (size_t i_rank = 0; i_rank < parallel::size(); ++i_rank) {
+        for (size_t r = 0; r < recv_item_refs_by_proc[i_rank].size(); ++r) {
+          const ItemId& item_id = recv_item_id_correspondance_by_proc[i_rank][r];
+          item_refs[item_id]    = recv_item_refs_by_proc[i_rank][r];
         }
+      }
 
-        const size_t max_i_ref = std::min(ref_id_list.size(), block_size * (i_block + 1));
-        for (size_t i_ref = block_size * i_block, i = 0; i_ref < max_i_ref; ++i_ref, ++i) {
-          block_type ref_bit{1 << i};
+      const size_t max_i_ref = std::min(ref_id_list.size(), block_size * (i_block + 1));
+      for (size_t i_ref = block_size * i_block, i = 0; i_ref < max_i_ref; ++i_ref, ++i) {
+        block_type ref_bit{1 << i};
 
-          std::vector<ItemId> item_id_vector;
+        std::vector<ItemId> item_id_vector;
 
-          for (uint32_t i_item = 0; i_item < item_refs.size(); ++i_item) {
-            const ItemId item_id{i_item};
-            if (item_refs[item_id] & ref_bit) {
-              item_id_vector.push_back(item_id);
-            }
+        for (uint32_t i_item = 0; i_item < item_refs.size(); ++i_item) {
+          const ItemId item_id{i_item};
+          if (item_refs[item_id] & ref_bit) {
+            item_id_vector.push_back(item_id);
           }
+        }
 
-          Array<const ItemId> item_id_array = convert_to_array(item_id_vector);
+        Array<const ItemId> item_id_array = convert_to_array(item_id_vector);
 
-          RefItemListBase::Type type = ref_item_list_type[i_ref];
-          m_new_descriptor.addRefItemList(RefItemList<item_type>(ref_id_list[i_ref], item_id_array, type));
-        }
+        RefItemListBase::Type type = ref_item_list_type[i_ref];
+        m_new_descriptor.addRefItemList(RefItemList<item_type>(ref_id_list[i_ref], item_id_array, type));
       }
     }
   }
-- 
GitLab