Open3D (C++ API)  0.20.0
Loading...
Searching...
No Matches
TBBHashBackend.h
Go to the documentation of this file.
1// ----------------------------------------------------------------------------
2// - Open3D: www.open3d.org -
3// ----------------------------------------------------------------------------
4// Copyright (c) 2018-2026 www.open3d.org
5// SPDX-License-Identifier: MIT
6// ----------------------------------------------------------------------------
7
8#pragma once
9
10#include <tbb/concurrent_unordered_map.h>
11#include <tbb/parallel_for.h>
12
13#include <limits>
14#include <unordered_map>
15
19
20namespace open3d {
21namespace core {
22template <typename Key, typename Hash, typename Eq>
24public:
25 TBBHashBackend(int64_t init_capacity,
26 int64_t key_dsize,
27 const std::vector<int64_t>& value_dsizes,
28 const Device& device);
30
31 void Reserve(int64_t capacity) override;
32
33 void Insert(const void* input_keys,
34 const std::vector<const void*>& input_values_soa,
35 buf_index_t* output_buf_indices,
36 bool* output_masks,
37 int64_t count) override;
38
39 void Find(const void* input_keys,
40 buf_index_t* output_buf_indices,
41 bool* output_masks,
42 int64_t count) override;
43
44 void Erase(const void* input_keys,
45 bool* output_masks,
46 int64_t count) override;
47
48 int64_t GetActiveIndices(buf_index_t* output_indices) override;
49
50 void Clear() override;
51
52 int64_t Size() const override;
53 int64_t GetBucketCount() const override;
54 std::vector<int64_t> BucketSizes() const override;
55 float LoadFactor() const override;
56
57 std::shared_ptr<tbb::concurrent_unordered_map<Key, buf_index_t, Hash, Eq>>
58 GetImpl() const {
59 return impl_;
60 }
61
62 void Allocate(int64_t capacity) override;
63 void Free() override {};
64
65protected:
66 std::shared_ptr<tbb::concurrent_unordered_map<Key, buf_index_t, Hash, Eq>>
68
69 std::shared_ptr<CPUHashBackendBufferAccessor> buffer_accessor_;
70};
71
72template <typename Key, typename Hash, typename Eq>
74 int64_t init_capacity,
75 int64_t key_dsize,
76 const std::vector<int64_t>& value_dsizes,
77 const Device& device)
78 : DeviceHashBackend(init_capacity, key_dsize, value_dsizes, device) {
79 Allocate(init_capacity);
80}
81
82template <typename Key, typename Hash, typename Eq>
84
85template <typename Key, typename Hash, typename Eq>
87 return impl_->size();
88}
89
90template <typename Key, typename Hash, typename Eq>
91void TBBHashBackend<Key, Hash, Eq>::Find(const void* input_keys,
92 buf_index_t* output_buf_indices,
93 bool* output_masks,
94 int64_t count) {
95 const Key* input_keys_templated = static_cast<const Key*>(input_keys);
96
97 tbb::parallel_for(
98 tbb::blocked_range<int64_t>(0, count, 64),
99 [=, &impl = impl_](const tbb::blocked_range<int64_t>& range) {
100 for (int64_t i = range.begin(); i < range.end(); ++i) {
101 const Key& key = input_keys_templated[i];
102
103 auto iter = impl->find(key);
104 bool flag = (iter != impl->end());
105 output_masks[i] = flag;
106 output_buf_indices[i] = flag ? iter->second : 0;
107 }
108 });
109}
110
111template <typename Key, typename Hash, typename Eq>
112void TBBHashBackend<Key, Hash, Eq>::Erase(const void* input_keys,
113 bool* output_masks,
114 int64_t count) {
115 const Key* input_keys_templated = static_cast<const Key*>(input_keys);
116
117 for (int64_t i = 0; i < count; ++i) {
118 const Key& key = input_keys_templated[i];
119
120 auto iter = impl_->find(key);
121 bool flag = (iter != impl_->end());
122 output_masks[i] = flag;
123 if (flag) {
124 buffer_accessor_->DeviceFree(iter->second);
125 impl_->unsafe_erase(iter);
126 }
127 }
128}
129
130template <typename Key, typename Hash, typename Eq>
132 buf_index_t* output_buf_indices) {
133 int64_t count = impl_->size();
134 int64_t i = 0;
135 for (auto iter = impl_->begin(); iter != impl_->end(); ++iter, ++i) {
136 output_buf_indices[i] = static_cast<int64_t>(iter->second);
137 }
138
139 return count;
140}
141
142template <typename Key, typename Hash, typename Eq>
144 impl_->clear();
145 this->buffer_->ResetHeap();
146}
147
148template <typename Key, typename Hash, typename Eq>
150 impl_->rehash(std::ceil(capacity / impl_->max_load_factor()));
151}
152
153template <typename Key, typename Hash, typename Eq>
155 return impl_->unsafe_bucket_count();
156}
157
158template <typename Key, typename Hash, typename Eq>
159std::vector<int64_t> TBBHashBackend<Key, Hash, Eq>::BucketSizes() const {
160 int64_t bucket_count = impl_->unsafe_bucket_count();
161 std::vector<int64_t> ret;
162 for (int64_t i = 0; i < bucket_count; ++i) {
163 ret.push_back(impl_->unsafe_bucket_size(i));
164 }
165 return ret;
166}
167
168template <typename Key, typename Hash, typename Eq>
170 return impl_->load_factor();
171}
172
173template <typename Key, typename Hash, typename Eq>
175 const void* input_keys,
176 const std::vector<const void*>& input_values_soa,
177 buf_index_t* output_buf_indices,
178 bool* output_masks,
179 int64_t count) {
180 const Key* input_keys_templated = static_cast<const Key*>(input_keys);
181
182 size_t n_values = input_values_soa.size();
183
184 tbb::parallel_for(
185 tbb::blocked_range<int64_t>(0, count, 64),
186 [&](const tbb::blocked_range<int64_t>& range) {
187 for (int64_t i = range.begin(); i < range.end(); ++i) {
188 output_buf_indices[i] = 0;
189 output_masks[i] = false;
190
191 const Key& key = input_keys_templated[i];
192
193 // Try to insert a dummy buffer index.
194 auto res = impl_->insert({key, 0});
195
196 // Lazy copy key value pair to buffer only if succeeded
197 if (res.second) {
198 buf_index_t buf_index =
199 buffer_accessor_->DeviceAllocate();
200 void* key_ptr = buffer_accessor_->GetKeyPtr(buf_index);
201
202 // Copy templated key to buffer
203 *static_cast<Key*>(key_ptr) = key;
204
205 // Copy/reset non-templated value in buffer
206 for (size_t j = 0; j < n_values; ++j) {
207 uint8_t* dst_value = static_cast<uint8_t*>(
208 buffer_accessor_->GetValuePtr(buf_index,
209 j));
210
211 const uint8_t* src_value =
212 static_cast<const uint8_t*>(
213 input_values_soa[j]) +
214 this->value_dsizes_[j] * i;
215 std::memcpy(dst_value, src_value,
216 this->value_dsizes_[j]);
217 }
218
219 // Update from dummy 0
220 res.first->second = buf_index;
221
222 // Write to return variables
223 output_buf_indices[i] = buf_index;
224 output_masks[i] = true;
225 }
226 }
227 });
228}
229
230template <typename Key, typename Hash, typename Eq>
232 this->capacity_ = capacity;
233
234 this->buffer_ = std::make_shared<HashBackendBuffer>(
235 this->capacity_, this->key_dsize_, this->value_dsizes_,
236 this->device_);
237
238 buffer_accessor_ =
239 std::make_shared<CPUHashBackendBufferAccessor>(*this->buffer_);
240
241 impl_ = std::make_shared<
242 tbb::concurrent_unordered_map<Key, buf_index_t, Hash, Eq>>(
243 capacity, Hash(), Eq());
244}
245
246} // namespace core
247} // namespace open3d
Definition DeviceHashBackend.h:20
Definition Device.h:18
Definition TBBHashBackend.h:23
void Insert(const void *input_keys, const std::vector< const void * > &input_values_soa, buf_index_t *output_buf_indices, bool *output_masks, int64_t count) override
Parallel insert contiguous arrays of keys and values.
Definition TBBHashBackend.h:174
void Find(const void *input_keys, buf_index_t *output_buf_indices, bool *output_masks, int64_t count) override
Parallel find a contiguous array of keys.
Definition TBBHashBackend.h:91
void Erase(const void *input_keys, bool *output_masks, int64_t count) override
Parallel erase a contiguous array of keys.
Definition TBBHashBackend.h:112
TBBHashBackend(int64_t init_capacity, int64_t key_dsize, const std::vector< int64_t > &value_dsizes, const Device &device)
Definition TBBHashBackend.h:73
std::shared_ptr< CPUHashBackendBufferAccessor > buffer_accessor_
Definition TBBHashBackend.h:69
std::vector< int64_t > BucketSizes() const override
Get the number of entries per bucket.
Definition TBBHashBackend.h:159
void Reserve(int64_t capacity) override
Definition TBBHashBackend.h:149
~TBBHashBackend()
Definition TBBHashBackend.h:83
std::shared_ptr< tbb::concurrent_unordered_map< Key, buf_index_t, Hash, Eq > > GetImpl() const
Definition TBBHashBackend.h:58
int64_t GetActiveIndices(buf_index_t *output_indices) override
Parallel collect all iterators in the hash table.
Definition TBBHashBackend.h:131
void Clear() override
Clear stored map without reallocating memory.
Definition TBBHashBackend.h:143
std::shared_ptr< tbb::concurrent_unordered_map< Key, buf_index_t, Hash, Eq > > impl_
Definition TBBHashBackend.h:67
int64_t GetBucketCount() const override
Get the number of buckets of the hash map.
Definition TBBHashBackend.h:154
void Free() override
Definition TBBHashBackend.h:63
void Allocate(int64_t capacity) override
Definition TBBHashBackend.h:231
int64_t Size() const override
Get the size (number of valid entries) of the hash map.
Definition TBBHashBackend.h:86
float LoadFactor() const override
Get the current load factor, defined as size / bucket count.
Definition TBBHashBackend.h:169
int count
Definition FilePCD.cpp:43
uint32_t buf_index_t
Definition HashBackendBuffer.h:49
Definition PinholeCameraIntrinsic.cpp:16