Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce the size of Mesh, Basis & Quadrature, Direction & Size, ElementId, FixedHashMap, and combine ElementId and DirectionalId #6000

Merged
merged 10 commits into from
May 21, 2024

Conversation

nilsdeppe
Copy link
Member

Proposed changes

After looking at memory consumption, @kidder, @wthrowe and I were surprised how much these small classes ended up using. This is because we have a lot of them stored per element. Using smaller integer types greatly reduces the memory usage, and then some bit twiddling is done internally in a few classes to further reduce memory usage. This should also help by reducing memory traffic (being able to load an entire Mesh in 1 load instead of 6, etc.). The bit twiddling is just simple bitmasks so nothing too crazy.

One thing I found quite inconvenient and a bit silly is that we version tiny classes like Direction. We should instead be versioning the Domain during serialization, not all these small classes. In some cases we used more bytes during serialization for the version than the actual data. That seems unnecessary. In cases where I could, I compressed the version info into unused bits by other parts of the class. This helps, but still seems silly.

Upgrade instructions

Code review checklist

  • The code is documented and the documentation renders correctly. Run
    make doc to generate the documentation locally into BUILD_DIR/docs/html.
    Then open index.html.
  • The code follows the stylistic and code quality guidelines listed in the
    code review guide.
  • The PR lists upgrade instructions and is labeled bugfix or
    new feature if appropriate.

Further comments

@nilsdeppe nilsdeppe requested review from wthrowe and kidder May 16, 2024 03:43
* bits of a uint8_t, which is why we do the left shift. We cannot
* have more than 16 bases to fit into the 4 bits, including the
* `Uninitialized` value. The number of bits to shift is encoded in the variable
* `Spectral::detail::basis_shift`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

detail stuff should not be part of the public interface. Either make the constant non-detail or do the shift internally when using the enum instead of incorporating it into the value.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see how the detail is currently part of the interface. If you are adding or removing values from the enum class, then you need to know why it is being shifted and the limitations, as in, you've entered the realm of "details". If you are just using it, you shouldn't be casting an enum class anyway. Should I make this a \warning or preface it with If you are changing the values in this or something?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You use it in src/IO/H5/VolumeData.cpp.

friend bool operator==(const Mesh<LocalDim>& lhs, const Mesh<LocalDim>& rhs);

// - 8 bits per extent = 3 * 8 = 24 bits = 3 bytes
// This limits us to 128 extent per direction. Since FD is 2x DG, this
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where does 128 come from?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heh, probably a typo when computing 2^8. I think the limitation is 255 in practice on FD, which would be a limit of 127 on DG. Does that clarify? (If so, I'll update the comments)

// This limits us to 128 extent per direction. Since FD is 2x DG, this
// means at most 64 DG points, which is should be fine.
// - We encode the basis & quadrature as two sets of 4 bits in a uint8_t.
std::array<uint8_t, 6> bit_field_{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this would be easier to read if you had two arrays of size 3 instead of one array of size 6 with the first and second halves interpreted differently.

std::array<Spectral::Basis, Dim> bases_{};
std::array<Spectral::Quadrature, Dim> quadratures_{};
static Spectral::Basis extract_basis(uint8_t bits);
static Spectral::Quadrature extract_quadrature(uint8_t bits);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[optional] Bit of a weird asymmetry in that the combining function is in an anonymous namespace but the extracting functions are private statics. I'd make them them all anonymous.

@@ -95,6 +95,7 @@ void test_explicit_choices_per_dimension() {
test_extents_basis_and_quadrature(mesh1d, {{2}},
{{Spectral::Basis::Legendre}},
{{Spectral::Quadrature::GaussLobatto}});
return;
CHECK(mesh1d.slice_away(0) == Mesh<0>{});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix something.

side_ = side;
template <size_t VolumeDim>
uint8_t Direction<VolumeDim>::self_bits() {
return static_cast<uint8_t>(Axis::Xi) bitor static_cast<uint8_t>(Side::Self);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[optional] return self().bits(); to reduce duplication. (Or even get rid of this function entirely.)

: block_id_(element_id.block_id_),
grid_index_(element_id.grid_index_),
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
direction_(*reinterpret_cast<const uint8_t*>(&direction)),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

direction_(direction.bits())

src/NumericalAlgorithms/Spectral/Basis.hpp Outdated Show resolved Hide resolved
src/Domain/Structure/Direction.cpp Outdated Show resolved Hide resolved
src/Domain/Structure/Direction.hpp Outdated Show resolved Hide resolved
src/Domain/Structure/ElementId.hpp Outdated Show resolved Hide resolved
src/DataStructures/FixedHashMap.hpp Outdated Show resolved Hide resolved
@nilsdeppe
Copy link
Member Author

Rebased and pushed fixups. Thanks for the reviews!

Copy link
Member

@kidder kidder left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

streaming in the ASSERT is not working on the failing build...

otherwise you have my permission to squash once you have the okay from @wthrowe

Copy link
Member

@wthrowe wthrowe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Squash.

p | bit_field_;
p | extents_;
p | quadrature_and_basis_;
// p | bit_field_;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove.

@@ -274,7 +276,9 @@ bool is_isotropic(const Mesh<Dim>& mesh) {

template <size_t Dim>
bool operator==(const Mesh<Dim>& lhs, const Mesh<Dim>& rhs) {
return lhs.bit_field_ == rhs.bit_field_;
// return lhs.bit_field_ == rhs.bit_field_;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove.

This reduces the size of Mesh from 48 bytes to 6 bytes. We store the mesh quite
a few places and it ends up being around 1kB per element at 48 bytes.

Also moves various functions that needed editing into the cpp file.
This needs to be one commit because we version these tiny classes.
@nilsdeppe
Copy link
Member Author

Okay, done! I verified that the test failure is fixed locally so 🤞

@wthrowe wthrowe merged commit 6bd9cb2 into sxs-collaboration:develop May 21, 2024
21 of 22 checks passed
@nilsdeppe nilsdeppe deleted the mesh_tweaks branch August 6, 2024 21:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants