BLI: refactor IndexMask for better performance and memory usage #104629

Merged
Jacques Lucke merged 254 commits from JacquesLucke/blender:index-mask-refactor into main 2023-05-24 18:11:47 +02:00
3 changed files with 20 additions and 32 deletions
Showing only changes of commit 0610294156 - Show all commits

View File

@ -70,11 +70,6 @@ struct IndexMaskData {
RawChunkIterator end_it;
};
struct IndexMaskSegment {
int64_t start_index;
OffsetSpan<int64_t, int16_t> indices;
};
struct ChunkSlice {
const Chunk *chunk;
RawChunkIterator begin_it;
@ -161,8 +156,7 @@ class IndexMask {
IndexMask slice(IndexRange range) const;
void foreach_segment(FunctionRef<void(const IndexMaskSegment &)> fn) const;
template<typename Fn> void foreach_span(Fn &&fn) const;
void foreach_span(FunctionRef<void(OffsetSpan<int64_t, int16_t>)> fn) const;
template<typename Fn> void foreach_range(Fn &&fn) const;
template<typename Fn> void foreach_span_or_range(Fn &&fn) const;
template<typename Fn> void foreach_index(Fn &&fn) const;
@ -597,15 +591,10 @@ template<typename Fn> inline void ChunkSlice::foreach_span(Fn &&fn) const
}
}
template<typename Fn> inline void IndexMask::foreach_span(Fn &&fn) const
{
this->foreach_segment([&](const IndexMaskSegment &segment) { fn(segment.indices); });
}
template<typename Fn> inline void IndexMask::foreach_index(Fn &&fn) const
{
this->foreach_segment([&](const IndexMaskSegment &segment) {
for (const int64_t index : segment.indices) {
this->foreach_span([&](const OffsetSpan<int64_t, int16_t> indices) {
for (const int64_t index : indices) {
fn(index);
}
});
@ -614,8 +603,7 @@ template<typename Fn> inline void IndexMask::foreach_index(Fn &&fn) const
template<typename Fn> inline void IndexMask::foreach_span_or_range(Fn &&fn) const
{
IndexRangeChecker is_index_mask;
this->foreach_segment([&, is_index_mask](const IndexMaskSegment &segment) {
const OffsetSpan<int64_t, int16_t> indices = segment.indices;
this->foreach_span([&, is_index_mask](const OffsetSpan<int64_t, int16_t> indices) {
if (is_index_mask.check(indices.base_span())) {
fn(IndexRange(indices[0], indices.size()));
}
@ -627,12 +615,12 @@ template<typename Fn> inline void IndexMask::foreach_span_or_range(Fn &&fn) cons
template<typename Fn> inline void IndexMask::foreach_range(Fn &&fn) const
{
this->foreach_segment([&](const IndexMaskSegment &segment) {
Span<int16_t> indices = segment.indices.base_span();
while (!indices.is_empty()) {
const int64_t next_range_size = unique_sorted_indices::find_size_of_next_range(indices);
fn(IndexRange(int64_t(indices[0]) + segment.indices.offset(), next_range_size));
indices = indices.drop_front(next_range_size);
this->foreach_span([&](const OffsetSpan<int64_t, int16_t> indices) {
Span<int16_t> base_indices = indices.base_span();
while (!base_indices.is_empty()) {
const int64_t next_range_size = unique_sorted_indices::find_size_of_next_range(base_indices);
fn(IndexRange(int64_t(base_indices[0]) + indices.offset(), next_range_size));
base_indices = base_indices.drop_front(next_range_size);
}
});
}

View File

@ -341,7 +341,7 @@ template<typename T> void from_index_mask(const IndexMask &mask, MutableSpan<T>
} // namespace unique_sorted_indices
void IndexMask::foreach_segment(FunctionRef<void(const IndexMaskSegment &)> fn) const
void IndexMask::foreach_span(FunctionRef<void(OffsetSpan<int64_t, int16_t>)> fn) const
{
if (data_.indices_num == 0) {
return;
@ -356,7 +356,6 @@ void IndexMask::foreach_segment(FunctionRef<void(const IndexMaskSegment &)> fn)
const int64_t final_segment_i = data_.end_it.segment_i;
const int64_t final_segments_num = data_.end_it.segment_i + 1;
int64_t counter = 0;
while (chunk_i < data_.chunks_num) {
const Chunk &chunk = data_.chunks[chunk_i];
const int64_t chunk_id = data_.chunk_ids[chunk_i];
@ -374,10 +373,9 @@ void IndexMask::foreach_segment(FunctionRef<void(const IndexMaskSegment &)> fn)
const int64_t segment_size = stored_segment_size - segment_drop_front - segment_drop_back;
const Span<int16_t> indices_span{indices_in_segment, segment_size};
const IndexMaskSegment segment{counter, {offset, indices_span}};
const OffsetSpan<int64_t, int16_t> segment{offset, indices_span};
fn(segment);
counter += segment_size;
segment_drop_front = 0;
segment_i = next_segment_i;
}

View File

@ -138,20 +138,22 @@ TEST(index_mask2, FromSize)
{
{
IndexMask mask(5);
Vector<IndexMaskSegment> segments;
mask.foreach_segment([&](const IndexMaskSegment &segment) { segments.append(segment); });
Vector<OffsetSpan<int64_t, int16_t>> segments;
mask.foreach_span(
[&](const OffsetSpan<int64_t, int16_t> segment) { segments.append(segment); });
EXPECT_EQ(segments.size(), 1);
EXPECT_EQ(segments[0].indices.size(), 5);
EXPECT_EQ(segments[0].size(), 5);
EXPECT_EQ(mask.first(), 0);
EXPECT_EQ(mask.last(), 4);
EXPECT_EQ(mask.min_array_size(), 5);
}
{
IndexMask mask(chunk_capacity);
Vector<IndexMaskSegment> segments;
mask.foreach_segment([&](const IndexMaskSegment &segment) { segments.append(segment); });
Vector<OffsetSpan<int64_t, int16_t>> segments;
mask.foreach_span(
[&](const OffsetSpan<int64_t, int16_t> segment) { segments.append(segment); });
EXPECT_EQ(segments.size(), 1);
EXPECT_EQ(segments[0].indices.size(), chunk_capacity);
EXPECT_EQ(segments[0].size(), chunk_capacity);
EXPECT_EQ(mask.first(), 0);
EXPECT_EQ(mask.last(), chunk_capacity - 1);
EXPECT_EQ(mask.min_array_size(), chunk_capacity);