From 42fef925d50f6cf8a6c5efb04b1a6e6f12ca5626 Mon Sep 17 00:00:00 2001 From: sbstndb/sbstndbs Date: Wed, 10 Sep 2025 10:02:29 +0200 Subject: [PATCH 1/2] perf: factorise MPI calls - Previously, update_tag_subdomains in a simple for loop - Now, factorized MPI calls in the simple for loop. --- include/samurai/algorithm/update.hpp | 81 ++++++++++++++++++++++++++++ include/samurai/mr/adapt.hpp | 5 +- 2 files changed, 82 insertions(+), 4 deletions(-) diff --git a/include/samurai/algorithm/update.hpp b/include/samurai/algorithm/update.hpp index 196e8fed5..9ae5454cd 100644 --- a/include/samurai/algorithm/update.hpp +++ b/include/samurai/algorithm/update.hpp @@ -738,6 +738,87 @@ namespace samurai #endif } + template + void update_tag_subdomains([[maybe_unused]] std::size_t min_level, + [[maybe_unused]] std::size_t max_level, + [[maybe_unused]] Field& tag, + [[maybe_unused]] bool erase = false) + { +#ifdef SAMURAI_WITH_MPI + using mesh_t = typename Field::mesh_t; + using value_t = typename Field::value_type; + using mesh_id_t = typename mesh_t::mesh_id_t; + std::vector req; + + auto& mesh = tag.mesh(); + mpi::communicator world; + std::vector> to_send(mesh.mpi_neighbourhood().size()); + + std::size_t i_neigh = 0; + for (auto& neighbour : mesh.mpi_neighbourhood()) + { + for (std::size_t level = min_level; level <= max_level; ++level) + { + if (!mesh[mesh_id_t::reference][level].empty() && !neighbour.mesh[mesh_id_t::reference][level].empty()) + { + auto out_interface = intersection(mesh[mesh_id_t::reference][level], + neighbour.mesh[mesh_id_t::reference][level], + mesh.subdomain()) + .on(level); + out_interface( + [&](const auto& i, const auto& index) + { + std::copy(tag(level, i, index).begin(), tag(level, i, index).end(), std::back_inserter(to_send[i_neigh])); + }); + } + } + req.push_back(world.isend(neighbour.rank, neighbour.rank, to_send[i_neigh])); + i_neigh++; + } + + i_neigh = 0; + for (auto& neighbour : mesh.mpi_neighbourhood()) + { + std::vector to_recv; + world.recv(neighbour.rank, world.rank(), to_recv); + std::ptrdiff_t count = 0; + + for (std::size_t level = min_level; level <= max_level; ++level) + { + if (!mesh[mesh_id_t::reference][level].empty() && !neighbour.mesh[mesh_id_t::reference][level].empty()) + { + auto in_interface = intersection(mesh[mesh_id_t::reference][level], + neighbour.mesh[mesh_id_t::reference][level], + neighbour.mesh.subdomain()) + .on(level); + in_interface( + [&](const auto& i, const auto& index) + { + if (count + static_cast(i.size()) <= to_recv.size()) + { + xt::xtensor neigh_tag = xt::empty_like(tag(level, i, index)); + std::copy(to_recv.begin() + count, + to_recv.begin() + count + static_cast(i.size()), + neigh_tag.begin()); + if (erase) + { + tag(level, i, index) = neigh_tag; + } + else + { + tag(level, i, index) |= neigh_tag; + } + count += static_cast(i.size()); + } + }); + } + } + i_neigh++; + } + mpi::wait_all(req.begin(), req.end()); +#endif + } + template void update_tag_subdomains([[maybe_unused]] std::size_t level, [[maybe_unused]] Field& tag, [[maybe_unused]] bool erase = false) { diff --git a/include/samurai/mr/adapt.hpp b/include/samurai/mr/adapt.hpp index 958c14a7f..c2d1b9b85 100644 --- a/include/samurai/mr/adapt.hpp +++ b/include/samurai/mr/adapt.hpp @@ -262,10 +262,7 @@ namespace samurai m_tag[cell] = static_cast(CellFlag::keep); }); - for (std::size_t level = min_level; level <= max_level; ++level) - { - update_tag_subdomains(level, m_tag, true); - } + update_tag_subdomains(min_level, max_level, m_tag, true); times::timers.stop("mesh adaptation"); update_ghost_mr(m_fields); From 47ce2a669b7dd71771a18adeca3fe7e58f9665a7 Mon Sep 17 00:00:00 2001 From: sbstndb/sbstndbs Date: Wed, 10 Sep 2025 10:12:11 +0200 Subject: [PATCH 2/2] fix: pre-commit --- include/samurai/algorithm/update.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/samurai/algorithm/update.hpp b/include/samurai/algorithm/update.hpp index 9ae5454cd..8d32607e9 100644 --- a/include/samurai/algorithm/update.hpp +++ b/include/samurai/algorithm/update.hpp @@ -740,9 +740,9 @@ namespace samurai template void update_tag_subdomains([[maybe_unused]] std::size_t min_level, - [[maybe_unused]] std::size_t max_level, - [[maybe_unused]] Field& tag, - [[maybe_unused]] bool erase = false) + [[maybe_unused]] std::size_t max_level, + [[maybe_unused]] Field& tag, + [[maybe_unused]] bool erase = false) { #ifdef SAMURAI_WITH_MPI using mesh_t = typename Field::mesh_t;