Blender V5.0
atomic_disjoint_set.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <algorithm>
10
13#include "BLI_map.hh"
14#include "BLI_sort.hh"
15#include "BLI_task.hh"
16
17namespace blender {
18
20{
21 threading::parallel_for(IndexRange(size), 4096, [&](const IndexRange range) {
22 for (const int i : range) {
23 items_[i].store(Item{i, 0}, relaxed);
24 }
25 });
26}
27
28static void update_first_occurrence(Map<int, int> &map, const int root, const int index)
29{
30 map.add_or_modify(
31 root,
32 [&](int *first_occurrence) { *first_occurrence = index; },
33 [&](int *first_occurrence) { *first_occurrence = std::min(index, *first_occurrence); });
34}
35
37{
38 BLI_assert(result.size() == items_.size());
39
40 const int size = result.size();
41
42 /* Find the root for element. With multi-threading, this root is not deterministic. So
43 * some postprocessing has to be done to make it deterministic. */
44 threading::EnumerableThreadSpecific<Map<int, int>> first_occurrence_by_root_per_thread;
45 threading::parallel_for(IndexRange(size), 1024, [&](const IndexRange range) {
46 Map<int, int> &first_occurrence_by_root = first_occurrence_by_root_per_thread.local();
47 for (const int i : range) {
48 const int root = this->find_root(i);
49 result[i] = root;
50 update_first_occurrence(first_occurrence_by_root, root, i);
51 }
52 });
53
54 /* Build a map that contains the first element index that has a certain root. */
55 Map<int, int> &combined_map = first_occurrence_by_root_per_thread.local();
56 for (const Map<int, int> &other_map : first_occurrence_by_root_per_thread) {
57 if (&combined_map == &other_map) {
58 continue;
59 }
60 for (const auto item : other_map.items()) {
61 update_first_occurrence(combined_map, item.key, item.value);
62 }
63 }
64
65 struct RootOccurence {
66 int root;
67 int first_occurrence;
68 };
69
70 /* Sort roots by first occurrence. This removes the non-determinism above. */
71 Vector<RootOccurence, 16> root_occurrences;
72 root_occurrences.reserve(combined_map.size());
73 for (const auto item : combined_map.items()) {
74 root_occurrences.append({item.key, item.value});
75 }
76 parallel_sort(root_occurrences.begin(),
77 root_occurrences.end(),
78 [](const RootOccurence &a, const RootOccurence &b) {
79 return a.first_occurrence < b.first_occurrence;
80 });
81
82 /* Remap original root values with deterministic values. */
83 Map<int, int> id_by_root;
84 id_by_root.reserve(root_occurrences.size());
85 for (const int i : root_occurrences.index_range()) {
86 id_by_root.add_new(root_occurrences[i].root, i);
87 }
88 threading::parallel_for(IndexRange(size), 1024, [&](const IndexRange range) {
89 for (const int i : range) {
90 result[i] = id_by_root.lookup(result[i]);
91 }
92 });
93 return id_by_root.size();
94}
95
97{
99 items_.index_range(),
100 1024,
101 0,
102 [&](const IndexRange range, int count) {
103 for (const int i : range) {
104 if (this->is_root(i)) {
105 count++;
106 }
107 }
108 return count;
109 },
110 [](const int a, const int b) { return a + b; });
111}
112
113} // namespace blender
#define BLI_assert(a)
Definition BLI_assert.h:46
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
int calc_reduced_ids(MutableSpan< int > result) const
const Value & lookup(const Key &key) const
Definition BLI_map.hh:545
void add_new(const Key &key, const Value &value)
Definition BLI_map.hh:265
int64_t size() const
Definition BLI_map.hh:976
void reserve(int64_t n)
Definition BLI_map.hh:1028
auto add_or_modify(const Key &key, const CreateValueF &create_value, const ModifyValueF &modify_value) -> decltype(create_value(nullptr))
Definition BLI_map.hh:481
int64_t size() const
void append(const T &value)
IndexRange index_range() const
void reserve(const int64_t min_capacity)
int count
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:93
Value parallel_reduce(IndexRange range, int64_t grain_size, const Value &identity, const Function &function, const Reduction &reduction)
Definition BLI_task.hh:151
static void update_first_occurrence(Map< int, int > &map, const int root, const int index)
void parallel_sort(RandomAccessIterator begin, RandomAccessIterator end)
Definition BLI_sort.hh:23
i
Definition text_draw.cc:230