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

Simplify chunked octree traversals #84

Merged
merged 22 commits into from
Nov 27, 2024
Merged
Changes from 1 commit
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
4be1065
Explicitly define struct ctors for compatibility with emplace_back
victorreijgwart Nov 8, 2024
1f365fb
Refactor TfTransformer to return by value, signal failure using optional
victorreijgwart Nov 8, 2024
ab59bd9
Use ChunkedNdtreeNodeRef to simplify chunked map accessors
victorreijgwart Nov 9, 2024
0b1a86f
Minor code cleanup
victorreijgwart Nov 10, 2024
af7ecc4
Simplify integrator code by using new ChunkedNdtree API features
victorreijgwart Sep 25, 2024
129f95b
Add QueryAccelerator for chunked wavelet octrees
victorreijgwart Nov 11, 2024
4f85fd8
Correctly handle constness in chunked octree node ptrs/refs
victorreijgwart Nov 11, 2024
bd9cfcf
Minor code cleanup
victorreijgwart Nov 11, 2024
35ec8ae
Add accelerated HashedChunkedWaveletOctree accessors to Python API
victorreijgwart Nov 11, 2024
6eade89
Improve consistency between coding using regular and chunked octrees
victorreijgwart Nov 11, 2024
d6e7f74
Simplify and improve clarity of old code
victorreijgwart Nov 12, 2024
26fba56
Add method to erase individual nodes from chunked octrees
victorreijgwart Nov 12, 2024
beb4c5c
Simplify thresholding and pruning code
victorreijgwart Nov 18, 2024
642680f
Optimize child node access by eliminating redundant lookup
victorreijgwart Nov 18, 2024
9269a3b
Code cleanup and consistency improvements to prepare PR#84
victorreijgwart Nov 21, 2024
620f161
Tidy up constructors and moves vs copies
victorreijgwart Nov 21, 2024
3de0323
Attempt to address 'maybe uninitialized' warnings from GCC >= 11
victorreijgwart Nov 21, 2024
d7a20b3
Switch from `nullptr_t` to `std::nullptr_t` type for portability
victorreijgwart Nov 21, 2024
75f4edf
Reintroduce the option to profile with Tracy
victorreijgwart Nov 22, 2024
57ad3bc
Revert "Reintroduce the option to profile with Tracy"
victorreijgwart Nov 25, 2024
9c9554d
Minor release management script improvements
victorreijgwart Nov 25, 2024
85320a0
Update changelogs
victorreijgwart Nov 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add method to erase individual nodes from chunked octrees
  • Loading branch information
victorreijgwart committed Nov 20, 2024
commit 26fba562873d522ea960513311fce5dfbba5e774
Original file line number Diff line number Diff line change
@@ -28,7 +28,7 @@ class ChunkedNdtree {
explicit ChunkedNdtree(HeightType max_height);
~ChunkedNdtree() = default;

bool empty() const { return root_chunk_.empty(); }
bool empty() const { return getRootNode().empty(); }
size_t size() const;
void clear() { root_chunk_.clear(); }
void prune();
Original file line number Diff line number Diff line change
@@ -37,6 +37,8 @@ class ChunkedNdtreeNodePtr {
const NodeRef* operator->() const { return node_.operator->(); }

private:
// TODO(victorr): Benchmark version that uses chunk_=nullptr instead of
// std::optional to mark invalid states
std::optional<NodeRef> node_;
};

@@ -74,9 +76,12 @@ class ChunkedNdtreeNodeRef {
bool hasNonzeroData(FloatingPoint threshold) const;
auto& data() const;

typename ChunkType::BitRef hasAtLeastOneChild() const;
auto hasAtLeastOneChild() const; // Returns a BitRef or bool, depending on
// whether the ChunkType is const-qualified

bool hasChild(NdtreeIndexRelativeChild child_index) const;
// TODO(victorr): Add tests for this method
void eraseChild(NdtreeIndexRelativeChild child_index) const;

NodePtr getChild(NdtreeIndexRelativeChild child_index) const;
template <typename... DefaultArgs>
@@ -85,7 +90,9 @@ class ChunkedNdtreeNodeRef {

private:
ChunkType& chunk_;
// TODO(victorr): Benchmark with int8_t
const IndexElement relative_node_depth_ = 0;
// TODO(victorr): Benchmark with uint32_t
const LinearIndex level_traversal_distance_ = 0u;

LinearIndex computeRelativeNodeIndex() const;
Original file line number Diff line number Diff line change
@@ -15,7 +15,8 @@ bool ChunkedNdtreeChunk<DataT, dim, height>::empty() const {
template <typename DataT, int dim, int height>
void ChunkedNdtreeChunk<DataT, dim, height>::clear() {
deleteChildrenArray();
std::fill(node_data_.begin(), node_data_.end(), DataT{});
node_data_.fill({});
node_has_at_least_one_child_.reset();
}

template <typename DataT, int dim, int height>
Original file line number Diff line number Diff line change
@@ -101,8 +101,7 @@ auto& ChunkedNdtreeNodeRef<ChunkType>::data() const {
}

template <typename ChunkType>
typename ChunkType::BitRef ChunkedNdtreeNodeRef<ChunkType>::hasAtLeastOneChild()
const {
auto ChunkedNdtreeNodeRef<ChunkType>::hasAtLeastOneChild() const {
return chunk_.nodeHasAtLeastOneChild(computeRelativeNodeIndex());
}

@@ -112,14 +111,44 @@ bool ChunkedNdtreeNodeRef<ChunkType>::hasChild(
return getChild(child_index);
}

template <typename ChunkType>
void ChunkedNdtreeNodeRef<ChunkType>::eraseChild(
NdtreeIndexRelativeChild child_index) const {
if (!hasAtLeastOneChild()) {
return;
}
LinearIndex child_start_idx = computeChildLevelTraversalDistance(child_index);
LinearIndex child_end_idx = child_start_idx + 1;
for (int child_depth = relative_node_depth_ + 1;
child_depth <= ChunkType::kHeight; ++child_depth) {
for (LinearIndex level_child_idx = child_start_idx;
level_child_idx < child_end_idx; ++level_child_idx) {
if (child_depth == ChunkType::kHeight) {
chunk_.eraseChild(level_child_idx);
} else {
const LinearIndex level_offset =
tree_math::perfect_tree::num_total_nodes_fast<kDim>(child_depth);
const LinearIndex chunk_child_idx = level_offset + level_child_idx;
chunk_.nodeData(chunk_child_idx) = {};
chunk_.nodeHasAtLeastOneChild(chunk_child_idx) = false;
}
}
child_start_idx <<= kDim;
child_end_idx <<= kDim;
}
}

template <typename ChunkType>
typename ChunkedNdtreeNodeRef<ChunkType>::NodePtr
ChunkedNdtreeNodeRef<ChunkType>::getChild(
NdtreeIndexRelativeChild child_index) const {
if (!hasAtLeastOneChild()) {
return {nullptr, 0, 0u};
}
const IndexElement child_depth = relative_node_depth_ + 1;
const LinearIndex child_level_traversal_distance =
computeChildLevelTraversalDistance(child_index);
if (child_depth % ChunkType::kHeight == 0) {
if (child_depth == ChunkType::kHeight) {
auto* child_chunk = chunk_.getChild(child_level_traversal_distance);
return {child_chunk, 0, 0u};
} else {
@@ -136,7 +165,7 @@ ChunkedNdtreeNodeRef<ChunkType>::getOrAllocateChild(
const IndexElement child_depth = relative_node_depth_ + 1;
const LinearIndex child_level_traversal_distance =
computeChildLevelTraversalDistance(child_index);
if (child_depth % ChunkType::kHeight == 0) {
if (child_depth == ChunkType::kHeight) {
auto& child_chunk = chunk_.getOrAllocateChild(
child_level_traversal_distance, std::forward<DefaultArgs>(args)...);
return {child_chunk, 0, 0};
9 changes: 4 additions & 5 deletions library/cpp/test/src/core/data_structure/test_ndtree.cc
Original file line number Diff line number Diff line change
@@ -41,18 +41,17 @@ TYPED_TEST(NdtreeTest, AllocatingAndClearing) {
GeometryGenerator::getRandomNdtreeIndex<IndexType>(min_child_pos,
max_child_pos, 0, 0)
.computeParentIndex(test_height);
const bool index_is_inside_root_chunk_node =
(tree_height - random_index.height) < TypeParam::kChunkHeight;
const bool index_is_root = tree_height == random_index.height;

EXPECT_EQ(ndtree.hasNode(random_index), index_is_inside_root_chunk_node)
EXPECT_EQ(ndtree.hasNode(random_index), index_is_root)
<< random_index.toString() << " and tree height " << tree_height;
ndtree.getOrAllocateNode(random_index);
EXPECT_TRUE(ndtree.hasNode(random_index))
<< random_index.toString() << " and tree height " << tree_height;
EXPECT_EQ(ndtree.empty(), index_is_inside_root_chunk_node);
EXPECT_EQ(ndtree.empty(), index_is_root);

ndtree.clear();
EXPECT_EQ(ndtree.hasNode(random_index), index_is_inside_root_chunk_node)
EXPECT_EQ(ndtree.hasNode(random_index), index_is_root)
<< random_index.toString() << " and tree height " << tree_height;
EXPECT_TRUE(ndtree.empty());
}