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 9 additions and 10 deletions
Showing only changes of commit e734450226 - Show all commits

View File

@ -173,12 +173,10 @@ namespace unique_sorted_indices {
template<typename T> Vector<IndexRange> split_by_chunk(Span<T> indices);
template<typename T> using RangeOrSpanVariant = std::variant<IndexRange, Span<T>>;
template<typename T>
int64_t split_to_ranges_and_spans(Span<T> indices,
int64_t range_threshold,
Vector<RangeOrSpanVariant<T>> &r_parts);
Vector<std::variant<IndexRange, Span<T>>> &r_parts);
template<typename T> bool non_empty_is_range(const Span<T> indices);
template<typename T> IndexRange non_empty_as_range(const Span<T> indices);
template<typename T> int64_t find_size_of_next_range(const Span<T> indices);

View File

@ -69,10 +69,10 @@ std::ostream &operator<<(std::ostream &stream, const IndexMask &mask)
{
Array<int64_t> indices(mask.size());
mask.to_indices<int64_t>(indices);
Vector<unique_sorted_indices::RangeOrSpanVariant<int64_t>> segments;
Vector<std::variant<IndexRange, Span<int64_t>>> segments;
unique_sorted_indices::split_to_ranges_and_spans<int64_t>(indices, 16, segments);
std::cout << "(Size: " << mask.size() << " | ";
for (const unique_sorted_indices::RangeOrSpanVariant<int64_t> &segment : segments) {
for (const std::variant<IndexRange, Span<int64_t>> &segment : segments) {
if (std::holds_alternative<IndexRange>(segment)) {
const IndexRange range = std::get<IndexRange>(segment);
std::cout << range;
@ -131,7 +131,7 @@ template<typename T> Vector<IndexRange> split_by_chunk(const Span<T> indices)
template<typename T>
int64_t split_to_ranges_and_spans(const Span<T> indices,
const int64_t range_threshold,
Vector<RangeOrSpanVariant<T>> &r_parts)
Vector<std::variant<IndexRange, Span<T>>> &r_parts)
{
BLI_assert(range_threshold >= 1);
const int64_t old_parts_num = r_parts.size();
@ -187,7 +187,7 @@ IndexMask to_index_mask(const Span<T> indices, std::pmr::memory_resource &memory
std::mutex scope_mutex;
threading::parallel_for(split_ranges.index_range(), 32, [&](const IndexRange slice) {
Vector<RangeOrSpanVariant<T>> segments_in_chunks;
Vector<std::variant<IndexRange, Span<T>>> segments_in_chunks;
Vector<int64_t> segments_per_chunk_cumulative;
segments_per_chunk_cumulative.reserve(slice.size() + 1);
segments_per_chunk_cumulative.append(0);
@ -219,7 +219,7 @@ IndexMask to_index_mask(const Span<T> indices, std::pmr::memory_resource &memory
for (const int64_t segment_i :
segments_in_chunks.index_range().take_back(segments_in_chunk_num)) {
const RangeOrSpanVariant<T> &segment = segments_in_chunks[segment_i];
const std::variant<IndexRange, Span<T>> &segment = segments_in_chunks[segment_i];
if (std::holds_alternative<IndexRange>(segment)) {
/* No extra allocations necessary because static memory is used. */
}
@ -273,7 +273,8 @@ IndexMask to_index_mask(const Span<T> indices, std::pmr::memory_resource &memory
int64_t cumulative_size = 0;
for (const int64_t segment_i : IndexRange(segments_num)) {
const RangeOrSpanVariant<T> &segment = segments_in_chunks[segments_in_chunk[segment_i]];
const std::variant<IndexRange, Span<T>> &segment =
segments_in_chunks[segments_in_chunk[segment_i]];
cumulative_segment_sizes[segment_i] = int16_t(cumulative_size);
if (std::holds_alternative<IndexRange>(segment)) {

View File

@ -82,7 +82,7 @@ TEST(index_mask2, FindStartOfNextRange)
TEST(index_mask2, SplitToRangesAndSpans)
{
Array<int> data = {1, 2, 3, 4, 7, 9, 10, 13, 14, 15, 20, 21, 22, 23, 24};
Vector<unique_sorted_indices::RangeOrSpanVariant<int>> parts;
Vector<std::variant<IndexRange, Span<int>>> parts;
const int64_t parts_num = unique_sorted_indices::split_to_ranges_and_spans<int>(data, 3, parts);
EXPECT_EQ(parts_num, 4);