Skip to content
Snippets Groups Projects
Commit d443cda0 authored by Stéphane Del Pino's avatar Stéphane Del Pino
Browse files

Improve Synchronizer handling

- The constructor is now private and can only be called by the
SynchronizerManager

- Building of exchange info is cleaner: checking if the lists have
been build (on-demand) is no more obtained by checking if the lists
are empty, one now use a unique pointer that is filled at
construction. This strategy is safer (for instance, a processor could
be empty which would generate a code crash in the previous
implementation).
parent be8df395
No related branches found
No related tags found
1 merge request!131Improve Synchronizer handling
...@@ -11,25 +11,27 @@ ...@@ -11,25 +11,27 @@
#include <iostream> #include <iostream>
#include <map> #include <map>
#include <memory>
#ifdef PUGS_HAS_MPI #ifdef PUGS_HAS_MPI
class Synchronizer class Synchronizer
{ {
private:
template <ItemType item_type> template <ItemType item_type>
using ExchangeItemTypeInfo = std::vector<Array<const ItemIdT<item_type>>>; using ExchangeItemTypeInfo = std::vector<Array<const ItemIdT<item_type>>>;
ExchangeItemTypeInfo<ItemType::cell> m_requested_cell_info; std::unique_ptr<ExchangeItemTypeInfo<ItemType::cell>> m_requested_cell_info;
ExchangeItemTypeInfo<ItemType::cell> m_provided_cell_info; std::unique_ptr<ExchangeItemTypeInfo<ItemType::cell>> m_provided_cell_info;
ExchangeItemTypeInfo<ItemType::face> m_requested_face_info; std::unique_ptr<ExchangeItemTypeInfo<ItemType::face>> m_requested_face_info;
ExchangeItemTypeInfo<ItemType::face> m_provided_face_info; std::unique_ptr<ExchangeItemTypeInfo<ItemType::face>> m_provided_face_info;
ExchangeItemTypeInfo<ItemType::edge> m_requested_edge_info; std::unique_ptr<ExchangeItemTypeInfo<ItemType::edge>> m_requested_edge_info;
ExchangeItemTypeInfo<ItemType::edge> m_provided_edge_info; std::unique_ptr<ExchangeItemTypeInfo<ItemType::edge>> m_provided_edge_info;
ExchangeItemTypeInfo<ItemType::node> m_requested_node_info; std::unique_ptr<ExchangeItemTypeInfo<ItemType::node>> m_requested_node_info;
ExchangeItemTypeInfo<ItemType::node> m_provided_node_info; std::unique_ptr<ExchangeItemTypeInfo<ItemType::node>> m_provided_node_info;
template <ItemType item_type> template <ItemType item_type>
PUGS_INLINE constexpr auto& PUGS_INLINE constexpr auto&
...@@ -68,22 +70,24 @@ class Synchronizer ...@@ -68,22 +70,24 @@ class Synchronizer
const auto& item_owner = connectivity.template owner<item_type>(); const auto& item_owner = connectivity.template owner<item_type>();
using ItemId = ItemIdT<item_type>; using ItemId = ItemIdT<item_type>;
auto& requested_item_info = this->_getRequestedItemInfo<item_type>(); auto& p_requested_item_info = this->_getRequestedItemInfo<item_type>();
requested_item_info = [&]() { p_requested_item_info = [&]() {
std::vector<std::vector<ItemId>> requested_item_vector_info(parallel::size()); std::vector<std::vector<ItemId>> requested_item_vector_info(parallel::size());
for (ItemId item_id = 0; item_id < item_owner.numberOfItems(); ++item_id) { for (ItemId item_id = 0; item_id < item_owner.numberOfItems(); ++item_id) {
if (const size_t owner = item_owner[item_id]; owner != parallel::rank()) { if (const size_t owner = item_owner[item_id]; owner != parallel::rank()) {
requested_item_vector_info[owner].emplace_back(item_id); requested_item_vector_info[owner].emplace_back(item_id);
} }
} }
std::vector<Array<const ItemId>> requested_item_info(parallel::size()); ExchangeItemTypeInfo<item_type> requested_item_info(parallel::size());
for (size_t i_rank = 0; i_rank < parallel::size(); ++i_rank) { for (size_t i_rank = 0; i_rank < parallel::size(); ++i_rank) {
const auto& requested_item_vector = requested_item_vector_info[i_rank]; const auto& requested_item_vector = requested_item_vector_info[i_rank];
requested_item_info[i_rank] = convert_to_array(requested_item_vector); requested_item_info[i_rank] = convert_to_array(requested_item_vector);
} }
return requested_item_info; return std::make_unique<ExchangeItemTypeInfo<item_type>>(std::move(requested_item_info));
}(); }();
auto& requested_item_info = *p_requested_item_info;
Array<unsigned int> local_number_of_requested_values(parallel::size()); Array<unsigned int> local_number_of_requested_values(parallel::size());
for (size_t i_rank = 0; i_rank < parallel::size(); ++i_rank) { for (size_t i_rank = 0; i_rank < parallel::size(); ++i_rank) {
local_number_of_requested_values[i_rank] = requested_item_info[i_rank].size(); local_number_of_requested_values[i_rank] = requested_item_info[i_rank].size();
...@@ -114,9 +118,9 @@ class Synchronizer ...@@ -114,9 +118,9 @@ class Synchronizer
item_number_to_id_correspondance[item_number[item_id]] = item_id; item_number_to_id_correspondance[item_number[item_id]] = item_id;
} }
auto& provided_item_info = this->_getProvidedItemInfo<item_type>(); auto& p_provided_item_info = this->_getProvidedItemInfo<item_type>();
provided_item_info = [&]() { p_provided_item_info = [&]() {
std::vector<Array<const ItemId>> provided_item_info(parallel::size()); ExchangeItemTypeInfo<item_type> provided_item_info(parallel::size());
for (size_t i_rank = 0; i_rank < parallel::size(); ++i_rank) { for (size_t i_rank = 0; i_rank < parallel::size(); ++i_rank) {
Array<ItemId> provided_item_id_to_rank{local_number_of_values_to_send[i_rank]}; Array<ItemId> provided_item_id_to_rank{local_number_of_values_to_send[i_rank]};
const Array<int>& provided_item_number_to_rank = provided_item_number_list_by_rank[i_rank]; const Array<int>& provided_item_number_to_rank = provided_item_number_list_by_rank[i_rank];
...@@ -125,7 +129,7 @@ class Synchronizer ...@@ -125,7 +129,7 @@ class Synchronizer
} }
provided_item_info[i_rank] = provided_item_id_to_rank; provided_item_info[i_rank] = provided_item_id_to_rank;
} }
return provided_item_info; return std::make_unique<ExchangeItemTypeInfo<item_type>>(provided_item_info);
}(); }();
} }
...@@ -137,15 +141,20 @@ class Synchronizer ...@@ -137,15 +141,20 @@ class Synchronizer
using ItemId = ItemIdT<item_type>; using ItemId = ItemIdT<item_type>;
const auto& provided_item_info = this->_getProvidedItemInfo<item_type>(); const auto& p_provided_item_info = this->_getProvidedItemInfo<item_type>();
const auto& requested_item_info = this->_getRequestedItemInfo<item_type>(); const auto& p_requested_item_info = this->_getRequestedItemInfo<item_type>();
Assert(requested_item_info.size() == provided_item_info.size()); Assert(static_cast<bool>(p_provided_item_info) == static_cast<bool>(p_requested_item_info));
if (provided_item_info.size() == 0) { if (not p_provided_item_info) {
this->_buildSynchronizeInfo<ConnectivityType, item_type>(connectivity); this->_buildSynchronizeInfo<ConnectivityType, item_type>(connectivity);
} }
const auto& provided_item_info = *p_provided_item_info;
const auto& requested_item_info = *p_requested_item_info;
Assert(requested_item_info.size() == provided_item_info.size());
std::vector<Array<const DataType>> provided_data_list(parallel::size()); std::vector<Array<const DataType>> provided_data_list(parallel::size());
for (size_t i_rank = 0; i_rank < parallel::size(); ++i_rank) { for (size_t i_rank = 0; i_rank < parallel::size(); ++i_rank) {
const Array<const ItemId>& provided_item_info_to_rank = provided_item_info[i_rank]; const Array<const ItemId>& provided_item_info_to_rank = provided_item_info[i_rank];
...@@ -181,15 +190,20 @@ class Synchronizer ...@@ -181,15 +190,20 @@ class Synchronizer
using ItemId = ItemIdT<item_type>; using ItemId = ItemIdT<item_type>;
const auto& provided_item_info = this->_getProvidedItemInfo<item_type>(); const auto& p_provided_item_info = this->_getProvidedItemInfo<item_type>();
const auto& requested_item_info = this->_getRequestedItemInfo<item_type>(); const auto& p_requested_item_info = this->_getRequestedItemInfo<item_type>();
Assert(requested_item_info.size() == provided_item_info.size()); Assert(static_cast<bool>(p_provided_item_info) == static_cast<bool>(p_requested_item_info));
if (provided_item_info.size() == 0) { if (not p_provided_item_info) {
this->_buildSynchronizeInfo<ConnectivityType, item_type>(connectivity); this->_buildSynchronizeInfo<ConnectivityType, item_type>(connectivity);
} }
const auto& provided_item_info = *p_provided_item_info;
const auto& requested_item_info = *p_requested_item_info;
Assert(requested_item_info.size() == provided_item_info.size());
const size_t size_of_arrays = item_array.sizeOfArrays(); const size_t size_of_arrays = item_array.sizeOfArrays();
std::vector<Array<const DataType>> provided_data_list(parallel::size()); std::vector<Array<const DataType>> provided_data_list(parallel::size());
...@@ -286,6 +300,12 @@ class Synchronizer ...@@ -286,6 +300,12 @@ class Synchronizer
} }
} }
Synchronizer(const Synchronizer&) = delete;
Synchronizer(Synchronizer&&) = delete;
private:
friend class SynchronizerManager;
PUGS_INLINE PUGS_INLINE
Synchronizer() Synchronizer()
{ {
...@@ -308,6 +328,12 @@ class Synchronizer ...@@ -308,6 +328,12 @@ class Synchronizer
synchronize(ItemArray<DataType, item_type, ConnectivityPtr>&) synchronize(ItemArray<DataType, item_type, ConnectivityPtr>&)
{} {}
Synchronizer(const Synchronizer&) = delete;
Synchronizer(Synchronizer&&) = delete;
private:
friend class SynchronizerManager;
PUGS_INLINE PUGS_INLINE
Synchronizer() Synchronizer()
{ {
......
...@@ -45,7 +45,7 @@ SynchronizerManager::getConnectivitySynchronizer(const IConnectivity* connectivi ...@@ -45,7 +45,7 @@ SynchronizerManager::getConnectivitySynchronizer(const IConnectivity* connectivi
connectivity_synchronizer != m_connectivity_synchronizer_map.end()) { connectivity_synchronizer != m_connectivity_synchronizer_map.end()) {
return (*connectivity_synchronizer->second); return (*connectivity_synchronizer->second);
} else { } else {
std::shared_ptr synchronizer = std::make_shared<Synchronizer>(); std::shared_ptr<Synchronizer> synchronizer(new Synchronizer);
m_connectivity_synchronizer_map[connectivity] = synchronizer; m_connectivity_synchronizer_map[connectivity] = synchronizer;
return *synchronizer; return *synchronizer;
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <mesh/Connectivity.hpp> #include <mesh/Connectivity.hpp>
#include <mesh/Mesh.hpp> #include <mesh/Mesh.hpp>
#include <mesh/Synchronizer.hpp> #include <mesh/Synchronizer.hpp>
#include <mesh/SynchronizerManager.hpp>
#include <utils/pugs_config.hpp> #include <utils/pugs_config.hpp>
// clazy:excludeall=non-pod-global-static // clazy:excludeall=non-pod-global-static
...@@ -57,7 +58,7 @@ TEST_CASE("Synchronizer", "[mesh]") ...@@ -57,7 +58,7 @@ TEST_CASE("Synchronizer", "[mesh]")
REQUIRE(not is_same_item_value(node_value, node_value_ref)); REQUIRE(not is_same_item_value(node_value, node_value_ref));
} }
Synchronizer synchronizer; Synchronizer& synchronizer = SynchronizerManager::instance().getConnectivitySynchronizer(&connectivity);
synchronizer.synchronize(node_value); synchronizer.synchronize(node_value);
REQUIRE(is_same_item_value(node_value, node_value_ref)); REQUIRE(is_same_item_value(node_value, node_value_ref));
...@@ -82,7 +83,7 @@ TEST_CASE("Synchronizer", "[mesh]") ...@@ -82,7 +83,7 @@ TEST_CASE("Synchronizer", "[mesh]")
REQUIRE(not is_same_item_value(edge_value, edge_value_ref)); REQUIRE(not is_same_item_value(edge_value, edge_value_ref));
} }
Synchronizer synchronizer; Synchronizer& synchronizer = SynchronizerManager::instance().getConnectivitySynchronizer(&connectivity);
synchronizer.synchronize(edge_value); synchronizer.synchronize(edge_value);
REQUIRE(is_same_item_value(edge_value, edge_value_ref)); REQUIRE(is_same_item_value(edge_value, edge_value_ref));
...@@ -107,7 +108,7 @@ TEST_CASE("Synchronizer", "[mesh]") ...@@ -107,7 +108,7 @@ TEST_CASE("Synchronizer", "[mesh]")
REQUIRE(not is_same_item_value(face_value, face_value_ref)); REQUIRE(not is_same_item_value(face_value, face_value_ref));
} }
Synchronizer synchronizer; Synchronizer& synchronizer = SynchronizerManager::instance().getConnectivitySynchronizer(&connectivity);
synchronizer.synchronize(face_value); synchronizer.synchronize(face_value);
REQUIRE(is_same_item_value(face_value, face_value_ref)); REQUIRE(is_same_item_value(face_value, face_value_ref));
...@@ -132,7 +133,7 @@ TEST_CASE("Synchronizer", "[mesh]") ...@@ -132,7 +133,7 @@ TEST_CASE("Synchronizer", "[mesh]")
REQUIRE(not is_same_item_value(cell_value, cell_value_ref)); REQUIRE(not is_same_item_value(cell_value, cell_value_ref));
} }
Synchronizer synchronizer; Synchronizer& synchronizer = SynchronizerManager::instance().getConnectivitySynchronizer(&connectivity);
synchronizer.synchronize(cell_value); synchronizer.synchronize(cell_value);
REQUIRE(is_same_item_value(cell_value, cell_value_ref)); REQUIRE(is_same_item_value(cell_value, cell_value_ref));
...@@ -163,7 +164,7 @@ TEST_CASE("Synchronizer", "[mesh]") ...@@ -163,7 +164,7 @@ TEST_CASE("Synchronizer", "[mesh]")
REQUIRE(not is_same_item_array(cell_array, cell_array_ref)); REQUIRE(not is_same_item_array(cell_array, cell_array_ref));
} }
Synchronizer synchronizer; Synchronizer& synchronizer = SynchronizerManager::instance().getConnectivitySynchronizer(&connectivity);
synchronizer.synchronize(cell_array); synchronizer.synchronize(cell_array);
REQUIRE(is_same_item_array(cell_array, cell_array_ref)); REQUIRE(is_same_item_array(cell_array, cell_array_ref));
...@@ -196,7 +197,7 @@ TEST_CASE("Synchronizer", "[mesh]") ...@@ -196,7 +197,7 @@ TEST_CASE("Synchronizer", "[mesh]")
REQUIRE(not is_same_item_value(node_value, node_value_ref)); REQUIRE(not is_same_item_value(node_value, node_value_ref));
} }
Synchronizer synchronizer; Synchronizer& synchronizer = SynchronizerManager::instance().getConnectivitySynchronizer(&connectivity);
synchronizer.synchronize(node_value); synchronizer.synchronize(node_value);
REQUIRE(is_same_item_value(node_value, node_value_ref)); REQUIRE(is_same_item_value(node_value, node_value_ref));
...@@ -221,7 +222,7 @@ TEST_CASE("Synchronizer", "[mesh]") ...@@ -221,7 +222,7 @@ TEST_CASE("Synchronizer", "[mesh]")
REQUIRE(not is_same_item_value(edge_value, edge_value_ref)); REQUIRE(not is_same_item_value(edge_value, edge_value_ref));
} }
Synchronizer synchronizer; Synchronizer& synchronizer = SynchronizerManager::instance().getConnectivitySynchronizer(&connectivity);
synchronizer.synchronize(edge_value); synchronizer.synchronize(edge_value);
REQUIRE(is_same_item_value(edge_value, edge_value_ref)); REQUIRE(is_same_item_value(edge_value, edge_value_ref));
...@@ -246,7 +247,7 @@ TEST_CASE("Synchronizer", "[mesh]") ...@@ -246,7 +247,7 @@ TEST_CASE("Synchronizer", "[mesh]")
REQUIRE(not is_same_item_value(face_value, face_value_ref)); REQUIRE(not is_same_item_value(face_value, face_value_ref));
} }
Synchronizer synchronizer; Synchronizer& synchronizer = SynchronizerManager::instance().getConnectivitySynchronizer(&connectivity);
synchronizer.synchronize(face_value); synchronizer.synchronize(face_value);
REQUIRE(is_same_item_value(face_value, face_value_ref)); REQUIRE(is_same_item_value(face_value, face_value_ref));
...@@ -271,7 +272,7 @@ TEST_CASE("Synchronizer", "[mesh]") ...@@ -271,7 +272,7 @@ TEST_CASE("Synchronizer", "[mesh]")
REQUIRE(not is_same_item_value(cell_value, cell_value_ref)); REQUIRE(not is_same_item_value(cell_value, cell_value_ref));
} }
Synchronizer synchronizer; Synchronizer& synchronizer = SynchronizerManager::instance().getConnectivitySynchronizer(&connectivity);
synchronizer.synchronize(cell_value); synchronizer.synchronize(cell_value);
REQUIRE(is_same_item_value(cell_value, cell_value_ref)); REQUIRE(is_same_item_value(cell_value, cell_value_ref));
...@@ -302,7 +303,7 @@ TEST_CASE("Synchronizer", "[mesh]") ...@@ -302,7 +303,7 @@ TEST_CASE("Synchronizer", "[mesh]")
REQUIRE(not is_same_item_array(cell_array, cell_array_ref)); REQUIRE(not is_same_item_array(cell_array, cell_array_ref));
} }
Synchronizer synchronizer; Synchronizer& synchronizer = SynchronizerManager::instance().getConnectivitySynchronizer(&connectivity);
synchronizer.synchronize(cell_array); synchronizer.synchronize(cell_array);
REQUIRE(is_same_item_array(cell_array, cell_array_ref)); REQUIRE(is_same_item_array(cell_array, cell_array_ref));
...@@ -335,7 +336,7 @@ TEST_CASE("Synchronizer", "[mesh]") ...@@ -335,7 +336,7 @@ TEST_CASE("Synchronizer", "[mesh]")
REQUIRE(not is_same_item_value(node_value, node_value_ref)); REQUIRE(not is_same_item_value(node_value, node_value_ref));
} }
Synchronizer synchronizer; Synchronizer& synchronizer = SynchronizerManager::instance().getConnectivitySynchronizer(&connectivity);
synchronizer.synchronize(node_value); synchronizer.synchronize(node_value);
REQUIRE(is_same_item_value(node_value, node_value_ref)); REQUIRE(is_same_item_value(node_value, node_value_ref));
...@@ -360,7 +361,7 @@ TEST_CASE("Synchronizer", "[mesh]") ...@@ -360,7 +361,7 @@ TEST_CASE("Synchronizer", "[mesh]")
REQUIRE(not is_same_item_value(edge_value, edge_value_ref)); REQUIRE(not is_same_item_value(edge_value, edge_value_ref));
} }
Synchronizer synchronizer; Synchronizer& synchronizer = SynchronizerManager::instance().getConnectivitySynchronizer(&connectivity);
synchronizer.synchronize(edge_value); synchronizer.synchronize(edge_value);
REQUIRE(is_same_item_value(edge_value, edge_value_ref)); REQUIRE(is_same_item_value(edge_value, edge_value_ref));
...@@ -385,7 +386,7 @@ TEST_CASE("Synchronizer", "[mesh]") ...@@ -385,7 +386,7 @@ TEST_CASE("Synchronizer", "[mesh]")
REQUIRE(not is_same_item_value(face_value, face_value_ref)); REQUIRE(not is_same_item_value(face_value, face_value_ref));
} }
Synchronizer synchronizer; Synchronizer& synchronizer = SynchronizerManager::instance().getConnectivitySynchronizer(&connectivity);
synchronizer.synchronize(face_value); synchronizer.synchronize(face_value);
REQUIRE(is_same_item_value(face_value, face_value_ref)); REQUIRE(is_same_item_value(face_value, face_value_ref));
...@@ -410,7 +411,7 @@ TEST_CASE("Synchronizer", "[mesh]") ...@@ -410,7 +411,7 @@ TEST_CASE("Synchronizer", "[mesh]")
REQUIRE(not is_same_item_value(cell_value, cell_value_ref)); REQUIRE(not is_same_item_value(cell_value, cell_value_ref));
} }
Synchronizer synchronizer; Synchronizer& synchronizer = SynchronizerManager::instance().getConnectivitySynchronizer(&connectivity);
synchronizer.synchronize(cell_value); synchronizer.synchronize(cell_value);
REQUIRE(is_same_item_value(cell_value, cell_value_ref)); REQUIRE(is_same_item_value(cell_value, cell_value_ref));
...@@ -441,7 +442,7 @@ TEST_CASE("Synchronizer", "[mesh]") ...@@ -441,7 +442,7 @@ TEST_CASE("Synchronizer", "[mesh]")
REQUIRE(not is_same_item_array(cell_array, cell_array_ref)); REQUIRE(not is_same_item_array(cell_array, cell_array_ref));
} }
Synchronizer synchronizer; Synchronizer& synchronizer = SynchronizerManager::instance().getConnectivitySynchronizer(&connectivity);
synchronizer.synchronize(cell_array); synchronizer.synchronize(cell_array);
REQUIRE(is_same_item_array(cell_array, cell_array_ref)); REQUIRE(is_same_item_array(cell_array, cell_array_ref));
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment