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

Reduce memory use and allocations for some connectivity descriptors

Memory use reduction occurs for 1D and 2D
- In dimension 1 node/edge/face numbers/owner/is_owned share the same
underlying arrays since node, edge and face are actually the same
- In dimension 2 edge/face numbers/owner/is_owned share the same
underlying arrays since edge and face are actually the same

On the way, ItemValue (resp. ItemArray) APIs changed: one can no more
affect a direct Array (resp. Table). One now must use the new
constructor that uses a connectivity and an Array (resp. Table). This
is always a better approach than before since it eventually consumes
one useless allocation/deallocation.
parent 5d0d902f
Branches
Tags
1 merge request!132Reduce memory use and allocations for some connectivity descriptors
This commit is part of merge request !132. Comments created here will be created in the context of that merge request.
......@@ -31,17 +31,10 @@ Connectivity<Dimension>::_buildFrom(const ConnectivityDescriptor& descriptor)
m_cell_type = cell_type;
}
{
WeakCellValue<int> cell_number(*this);
cell_number = convert_to_array(descriptor.cell_number_vector);
m_cell_number = cell_number;
}
m_cell_number = WeakCellValue<int>(*this, convert_to_array(descriptor.cell_number_vector));
{
WeakNodeValue<int> node_number(*this);
node_number = convert_to_array(descriptor.node_number_vector);
m_node_number = node_number;
}
Array node_number_array = convert_to_array(descriptor.node_number_vector);
m_node_number = WeakNodeValue<int>(*this, node_number_array);
{
WeakCellValue<int> cell_global_index(*this);
......@@ -51,11 +44,7 @@ Connectivity<Dimension>::_buildFrom(const ConnectivityDescriptor& descriptor)
m_cell_global_index = cell_global_index;
}
{
WeakCellValue<int> cell_owner(*this);
cell_owner = convert_to_array(descriptor.cell_owner_vector);
m_cell_owner = cell_owner;
}
m_cell_owner = WeakCellValue<int>(*this, convert_to_array(descriptor.cell_owner_vector));
{
const int rank = parallel::rank();
......@@ -65,15 +54,13 @@ Connectivity<Dimension>::_buildFrom(const ConnectivityDescriptor& descriptor)
m_cell_is_owned = cell_is_owned;
}
{
WeakNodeValue<int> node_owner(*this);
node_owner = convert_to_array(descriptor.node_owner_vector);
m_node_owner = node_owner;
}
Array node_owner_array = convert_to_array(descriptor.node_owner_vector);
m_node_owner = WeakNodeValue<int>{*this, node_owner_array};
Array<bool> node_is_owned_array(this->numberOfNodes());
{
const int rank = parallel::rank();
WeakNodeValue<bool> node_is_owned(*this);
WeakNodeValue<bool> node_is_owned(*this, node_is_owned_array);
parallel_for(
this->numberOfNodes(), PUGS_LAMBDA(NodeId r) { node_is_owned[r] = (m_node_owner[r] == rank); });
m_node_is_owned = node_is_owned;
......@@ -84,46 +71,14 @@ Connectivity<Dimension>::_buildFrom(const ConnectivityDescriptor& descriptor)
if constexpr (Dimension == 1) {
// faces are similar to nodes
{
WeakFaceValue<int> face_number(*this);
face_number = convert_to_array(descriptor.node_number_vector);
m_face_number = face_number;
}
{
WeakFaceValue<int> face_owner(*this);
face_owner = convert_to_array(descriptor.node_owner_vector);
m_face_owner = face_owner;
}
{
const int rank = parallel::rank();
WeakFaceValue<bool> face_is_owned(*this);
parallel_for(
this->numberOfFaces(), PUGS_LAMBDA(FaceId l) { face_is_owned[l] = (m_face_owner[l] == rank); });
m_face_is_owned = face_is_owned;
}
m_face_number = WeakFaceValue<int>(*this, node_number_array);
m_face_owner = WeakFaceValue<int>(*this, node_owner_array);
m_face_is_owned = WeakFaceValue<bool>(*this, node_is_owned_array);
// edges are similar to nodes
{
WeakEdgeValue<int> edge_number(*this);
edge_number = convert_to_array(descriptor.node_number_vector);
m_edge_number = edge_number;
}
{
WeakEdgeValue<int> edge_owner(*this);
edge_owner = convert_to_array(descriptor.node_owner_vector);
m_edge_owner = edge_owner;
}
{
const int rank = parallel::rank();
WeakEdgeValue<bool> edge_is_owned(*this);
parallel_for(
this->numberOfEdges(), PUGS_LAMBDA(EdgeId l) { edge_is_owned[l] = (m_edge_owner[l] == rank); });
m_edge_is_owned = edge_is_owned;
}
m_edge_number = WeakEdgeValue<int>(*this, node_number_array);
m_edge_owner = WeakEdgeValue<int>(*this, node_owner_array);
m_edge_is_owned = WeakEdgeValue<bool>(*this, node_is_owned_array);
} else {
m_item_to_item_matrix[itemTId(ItemType::face)][itemTId(ItemType::node)] = descriptor.face_to_node_vector;
......@@ -140,21 +95,16 @@ Connectivity<Dimension>::_buildFrom(const ConnectivityDescriptor& descriptor)
m_cell_face_is_reversed = cell_face_is_reversed;
}
{
WeakFaceValue<int> face_number(*this);
face_number = convert_to_array(descriptor.face_number_vector);
m_face_number = face_number;
}
Array face_number_array = convert_to_array(descriptor.face_number_vector);
m_face_number = WeakFaceValue<int>(*this, face_number_array);
{
WeakFaceValue<int> face_owner(*this);
face_owner = convert_to_array(descriptor.face_owner_vector);
m_face_owner = face_owner;
}
Array face_owner_array = convert_to_array(descriptor.face_owner_vector);
m_face_owner = WeakFaceValue<int>(*this, face_owner_array);
Array<bool> face_is_owned_array(this->numberOfFaces());
{
const int rank = parallel::rank();
WeakFaceValue<bool> face_is_owned(*this);
WeakFaceValue<bool> face_is_owned(*this, face_is_owned_array);
parallel_for(
this->numberOfFaces(), PUGS_LAMBDA(FaceId l) { face_is_owned[l] = (m_face_owner[l] == rank); });
m_face_is_owned = face_is_owned;
......@@ -164,25 +114,9 @@ Connectivity<Dimension>::_buildFrom(const ConnectivityDescriptor& descriptor)
if constexpr (Dimension == 2) {
// edges are similar to faces
{
WeakEdgeValue<int> edge_number(*this);
edge_number = convert_to_array(descriptor.face_number_vector);
m_edge_number = edge_number;
}
{
WeakEdgeValue<int> edge_owner(*this);
edge_owner = convert_to_array(descriptor.face_owner_vector);
m_edge_owner = edge_owner;
}
{
const int rank = parallel::rank();
WeakEdgeValue<bool> edge_is_owned(*this);
parallel_for(
this->numberOfEdges(), PUGS_LAMBDA(EdgeId l) { edge_is_owned[l] = (m_edge_owner[l] == rank); });
m_edge_is_owned = edge_is_owned;
}
m_edge_number = WeakEdgeValue<int>(*this, face_number_array);
m_edge_owner = WeakEdgeValue<int>(*this, face_owner_array);
m_edge_is_owned = WeakEdgeValue<bool>(*this, face_is_owned_array);
} else {
m_item_to_item_matrix[itemTId(ItemType::edge)][itemTId(ItemType::node)] = descriptor.edge_to_node_vector;
......@@ -202,17 +136,8 @@ Connectivity<Dimension>::_buildFrom(const ConnectivityDescriptor& descriptor)
m_face_edge_is_reversed = face_edge_is_reversed;
}
{
WeakEdgeValue<int> edge_number(*this);
edge_number = convert_to_array(descriptor.edge_number_vector);
m_edge_number = edge_number;
}
{
WeakEdgeValue<int> edge_owner(*this);
edge_owner = convert_to_array(descriptor.edge_owner_vector);
m_edge_owner = edge_owner;
}
m_edge_number = WeakEdgeValue<int>(*this, convert_to_array(descriptor.edge_number_vector));
m_edge_owner = WeakEdgeValue<int>(*this, convert_to_array(descriptor.edge_owner_vector));
{
const int rank = parallel::rank();
......
......@@ -16,8 +16,7 @@ ConnectivityDispatcher<Dimension>::_buildNewOwner()
CRSGraph connectivity_graph = m_connectivity.cellToCellGraph();
Partitioner P;
CellValue<int> cell_new_owner(m_connectivity);
cell_new_owner = P.partition(connectivity_graph);
CellValue<int> cell_new_owner(m_connectivity, P.partition(connectivity_graph));
this->_dispatchedInfo<ItemType::cell>().m_new_owner = cell_new_owner;
} else {
......
......@@ -126,28 +126,6 @@ class ItemArray
return m_values.numberOfColumns();
}
template <typename DataType2>
PUGS_INLINE ItemArray&
operator=(const Table<DataType2>& table) noexcept(NO_ASSERT)
{
// ensures that DataType is the same as source DataType2
static_assert(std::is_same_v<std::remove_const_t<DataType>, std::remove_const_t<DataType2>>,
"Cannot assign ItemArray of different type");
// ensures that const is not lost through copy
static_assert(((std::is_const_v<DataType2> and std::is_const_v<DataType>) or not std::is_const_v<DataType2>),
"Cannot assign ItemArray of const to ItemArray of non-const");
Assert((table.numberOfRows() * table.numberOfColumns() == 0) or this->isBuilt(),
"Cannot assign array of arrays to a non-built ItemArray\n");
Assert(this->numberOfItems() == table.numberOfRows(), "Cannot assign a table of a different dimensions\n");
Assert(this->sizeOfArrays() == table.numberOfColumns(), "Cannot assign a table of a different dimensions\n");
m_values = table;
return *this;
}
template <typename DataType2, typename ConnectivityPtr2>
PUGS_INLINE ItemArray&
operator=(const ItemArray<DataType2, item_type, ConnectivityPtr2>& array_per_item) noexcept
......@@ -196,6 +174,13 @@ class ItemArray
"supported");
}
PUGS_INLINE
ItemArray(const IConnectivity& connectivity, const Table<DataType>& table) noexcept(NO_ASSERT)
: m_connectivity_ptr{connectivity.shared_ptr()}, m_values{table}
{
Assert(connectivity.numberOf<item_type>() == table.numberOfRows(), "Invalid table, wrong number of rows");
}
PUGS_INLINE
~ItemArray() = default;
};
......
......@@ -117,26 +117,6 @@ class ItemValue
static_assert(std::is_same_v<IndexType, ItemId>, "ItemValue must be indexed by ItemId");
}
template <typename DataType2>
PUGS_INLINE ItemValue&
operator=(const Array<DataType2>& values) noexcept(NO_ASSERT)
{
// ensures that DataType is the same as source DataType2
static_assert(std::is_same_v<std::remove_const_t<DataType>, std::remove_const_t<DataType2>>,
"Cannot assign ItemValue of different type");
// ensures that const is not lost through copy
static_assert(((std::is_const_v<DataType2> and std::is_const_v<DataType>) or not std::is_const_v<DataType2>),
"Cannot assign ItemValue of const to ItemValue of non-const");
Assert((m_values.size() == values.size()), "Cannot assign an array of values of a different size\n");
Assert((values.size() == 0) or this->isBuilt(), "Cannot assign array of values to a non-built ItemValue\n");
m_values = values;
return *this;
}
template <typename DataType2, typename ConnectivityPtr2>
PUGS_INLINE ItemValue&
operator=(const ItemValue<DataType2, item_type, ConnectivityPtr2>& value_per_item) noexcept
......@@ -184,6 +164,13 @@ class ItemValue
"supported");
}
PUGS_INLINE
ItemValue(const IConnectivity& connectivity, const Array<DataType>& values) noexcept(NO_ASSERT)
: m_connectivity_ptr{connectivity.shared_ptr()}, m_values{values}
{
Assert((m_values.size() == connectivity.numberOf<item_type>()), "Invalid values size");
}
PUGS_INLINE
~ItemValue() = default;
};
......
......@@ -145,9 +145,7 @@ TEST_CASE("ItemArray", "[mesh]")
const Connectivity<3>& connectivity = mesh_3d->connectivity();
CellArray<size_t> cell_array{connectivity, 3};
Table<size_t> table{cell_array.numberOfItems(), cell_array.sizeOfArrays()};
Table<size_t> table{connectivity.numberOfCells(), 3};
{
size_t k = 0;
for (size_t i = 0; i < table.numberOfRows(); ++i) {
......@@ -156,7 +154,8 @@ TEST_CASE("ItemArray", "[mesh]")
}
}
}
cell_array = table;
CellArray<size_t> cell_array{connectivity, table};
auto is_same = [](const CellArray<size_t>& cell_array, const Table<size_t>& table) {
bool is_same = true;
......@@ -170,6 +169,7 @@ TEST_CASE("ItemArray", "[mesh]")
};
REQUIRE(is_same(cell_array, table));
REQUIRE(&(cell_array[CellId{0}][0]) == &(table(0, 0)));
}
}
}
......@@ -282,8 +282,7 @@ TEST_CASE("ItemArray", "[mesh]")
}
}
CellArray<int> cell_array{mesh->connectivity(), 3};
cell_array = table;
CellArray<int> cell_array{mesh->connectivity(), table};
std::ostringstream table_ost;
table_ost << table;
......@@ -351,10 +350,8 @@ TEST_CASE("ItemArray", "[mesh]")
const Connectivity<3>& connectivity = mesh_3d->connectivity();
CellArray<size_t> cell_array{connectivity, 2};
Table<size_t> values{3, connectivity.numberOfCells() + 3};
REQUIRE_THROWS_AS(cell_array = values, AssertError);
Table<size_t> values{connectivity.numberOfCells() + 3, 3};
REQUIRE_THROWS_WITH(CellArray<size_t>(connectivity, values), "Invalid table, wrong number of rows");
}
}
}
......
......@@ -121,14 +121,12 @@ TEST_CASE("ItemValue", "[mesh]")
const Connectivity<3>& connectivity = mesh_3d->connectivity();
CellValue<size_t> cell_value{connectivity};
Array<size_t> values{cell_value.numberOfItems()};
Array<size_t> values{connectivity.numberOfCells()};
for (size_t i = 0; i < values.size(); ++i) {
values[i] = i;
}
cell_value = values;
CellValue<size_t> cell_value{connectivity, values};
{
bool is_same = true;
......@@ -136,6 +134,7 @@ TEST_CASE("ItemValue", "[mesh]")
is_same &= (cell_value[i_cell] == i_cell);
}
REQUIRE(is_same);
REQUIRE(&(cell_value[CellId{0}]) == &(values[0]));
}
}
}
......@@ -227,8 +226,7 @@ TEST_CASE("ItemValue", "[mesh]")
array[i] = 2 * i + 1;
}
CellValue<int> cell_value{mesh->connectivity()};
cell_value = array;
CellValue<int> cell_value{mesh->connectivity(), array};
std::ostringstream array_ost;
array_ost << array;
......@@ -296,10 +294,8 @@ TEST_CASE("ItemValue", "[mesh]")
const Connectivity<3>& connectivity = mesh_3d->connectivity();
CellValue<size_t> cell_value{connectivity};
Array<size_t> values{3 + cell_value.numberOfItems()};
REQUIRE_THROWS_AS(cell_value = values, AssertError);
Array<size_t> values{3 + connectivity.numberOfCells()};
REQUIRE_THROWS_WITH(CellValue<size_t>(connectivity, values), "Invalid values size");
}
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment