Open3D (C++ API)  0.11.0
HashmapCPU.h
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - Open3D: www.open3d.org -
3 // ----------------------------------------------------------------------------
4 // The MIT License (MIT)
5 //
6 // Copyright (c) 2018 www.open3d.org
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
14 //
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
17 //
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 // IN THE SOFTWARE.
25 // ----------------------------------------------------------------------------
26 
27 #pragma once
28 
29 #include <unordered_map>
30 
33 
34 namespace open3d {
35 namespace core {
36 template <typename Hash, typename KeyEq>
37 class CPUHashmap : public DeviceHashmap<Hash, KeyEq> {
38 public:
39  ~CPUHashmap();
40 
41  CPUHashmap(size_t init_buckets,
42  size_t init_capacity,
43  size_t dsize_key,
44  size_t dsize_value,
45  const Device& device);
46 
47  void Rehash(size_t buckets) override;
48 
49  void Insert(const void* input_keys,
50  const void* input_values,
51  iterator_t* output_iterators,
52  bool* output_masks,
53  size_t count) override;
54 
55  void Activate(const void* input_keys,
56  iterator_t* output_iterators,
57  bool* output_masks,
58  size_t count) override;
59 
60  void Find(const void* input_keys,
61  iterator_t* output_iterators,
62  bool* output_masks,
63  size_t count) override;
64 
65  void Erase(const void* input_keys,
66  bool* output_masks,
67  size_t count) override;
68 
69  size_t GetIterators(iterator_t* output_iterators) override;
70 
71  void UnpackIterators(const iterator_t* input_iterators,
72  const bool* input_masks,
73  void* output_keys,
74  void* output_values,
75  size_t count) override;
76 
77  void AssignIterators(iterator_t* input_iterators,
78  const bool* input_masks,
79  const void* input_values,
80  size_t count) override;
81 
82  std::vector<size_t> BucketSizes() const override;
83  float LoadFactor() const override;
84 
85  size_t Size() const override;
86 
87 private:
88  std::shared_ptr<std::unordered_map<void*, void*, Hash, KeyEq>> impl_;
89 
90  // Valid kv_pairs.
91  std::vector<iterator_t> kv_pairs_;
92 };
93 
94 template <typename Hash, typename KeyEq>
96  size_t init_capacity,
97  size_t dsize_key,
98  size_t dsize_value,
99  const Device& device)
100  : DeviceHashmap<Hash, KeyEq>(
101  init_buckets,
102  init_capacity,
103  dsize_key,
105  dsize_value,
106  device) {
107  impl_ = std::make_shared<std::unordered_map<void*, void*, Hash, KeyEq>>(
108  init_buckets, Hash(dsize_key), KeyEq(dsize_key));
109 }
110 
111 template <typename Hash, typename KeyEq>
113  for (auto kv_pair : kv_pairs_) {
114  MemoryManager::Free(kv_pair.first, this->device_);
115  MemoryManager::Free(kv_pair.second, this->device_);
116  }
117  impl_->clear();
118 }
119 
120 template <typename Hash, typename KeyEq>
122  return impl_->size();
123 }
124 
125 template <typename Hash, typename KeyEq>
126 void CPUHashmap<Hash, KeyEq>::Insert(const void* input_keys,
127  const void* input_values,
128  iterator_t* output_iterators,
129  bool* output_masks,
130  size_t count) {
131  for (size_t i = 0; i < count; ++i) {
132  const uint8_t* src_key =
133  static_cast<const uint8_t*>(input_keys) + this->dsize_key_ * i;
134  const uint8_t* src_value = static_cast<const uint8_t*>(input_values) +
135  this->dsize_value_ * i;
136 
137  // Manually copy before insert.
138  uint8_t* dst_key = static_cast<uint8_t*>(
140  uint8_t* dst_value = static_cast<uint8_t*>(
142 
143  MemoryManager::Memcpy(dst_key, this->device_, src_key, this->device_,
144  this->dsize_key_);
145  MemoryManager::Memcpy(dst_value, this->device_, src_value,
146  this->device_, this->dsize_value_);
147 
148  // Try insertion.
149  auto res = impl_->insert({dst_key, dst_value});
150 
151  // Handle memory.
152  if (res.second) {
153  output_iterators[i] = iterator_t(dst_key, dst_value);
154  output_masks[i] = true;
155  } else {
156  MemoryManager::Free(dst_key, this->device_);
157  MemoryManager::Free(dst_value, this->device_);
158  output_iterators[i] = iterator_t();
159  output_masks[i] = false;
160  }
161  }
162  this->capacity_ = impl_->size();
163  this->bucket_count_ = impl_->bucket_count();
164 }
165 
166 template <typename Hash, typename KeyEq>
167 void CPUHashmap<Hash, KeyEq>::Activate(const void* input_keys,
168  iterator_t* output_iterators,
169  bool* output_masks,
170  size_t count) {
171  for (size_t i = 0; i < count; ++i) {
172  const uint8_t* src_key =
173  static_cast<const uint8_t*>(input_keys) + this->dsize_key_ * i;
174 
175  // Manually copy before insert
176  uint8_t* dst_key = static_cast<uint8_t*>(
178  uint8_t* dummy_value = static_cast<uint8_t*>(
180  memset(dummy_value, 0, this->dsize_value_);
181 
182  MemoryManager::Memcpy(dst_key, this->device_, src_key, this->device_,
183  this->dsize_key_);
184 
185  // Try insertion.
186  auto res = impl_->insert({dst_key, dummy_value});
187 
188  // Handle memory.
189  if (res.second) {
190  output_iterators[i] = iterator_t(dst_key, dummy_value);
191  output_masks[i] = true;
192  } else {
193  MemoryManager::Free(dst_key, this->device_);
194  MemoryManager::Free(dummy_value, this->device_);
195  output_iterators[i] = iterator_t();
196  output_masks[i] = false;
197  }
198  }
199  this->capacity_ = impl_->size();
200  this->bucket_count_ = impl_->bucket_count();
201 }
202 
203 template <typename Hash, typename KeyEq>
204 void CPUHashmap<Hash, KeyEq>::Find(const void* input_keys,
205  iterator_t* output_iterators,
206  bool* output_masks,
207  size_t count) {
208  for (size_t i = 0; i < count; ++i) {
209  uint8_t* key = const_cast<uint8_t*>(
210  static_cast<const uint8_t*>(input_keys) + this->dsize_key_ * i);
211 
212  auto iter = impl_->find(key);
213  if (iter == impl_->end()) {
214  output_iterators[i] = iterator_t();
215  output_masks[i] = false;
216  } else {
217  output_iterators[i] = iterator_t(iter->first, iter->second);
218  output_masks[i] = true;
219  }
220  }
221 }
222 
223 template <typename Hash, typename KeyEq>
224 void CPUHashmap<Hash, KeyEq>::Erase(const void* input_keys,
225  bool* output_masks,
226  size_t count) {
227  for (size_t i = 0; i < count; ++i) {
228  uint8_t* key = const_cast<uint8_t*>(
229  static_cast<const uint8_t*>(input_keys) + this->dsize_key_ * i);
230 
231  size_t erased = impl_->erase(key);
232  output_masks[i] = erased > 0;
233  }
234 }
235 
236 template <typename Hash, typename KeyEq>
238  size_t count = impl_->size();
239 
240  size_t i = 0;
241  for (auto iter = impl_->begin(); iter != impl_->end(); ++iter, ++i) {
242  output_iterators[i] = iterator_t(iter->first, iter->second);
243  }
244 
245  return count;
246 }
247 
248 void UnpackIteratorsStep(const iterator_t* input_iterators,
249  const bool* input_masks,
250  void* output_keys,
251  void* output_values,
252  const Device& device,
253  size_t dsize_key,
254  size_t dsize_value,
255  size_t tid) {
256  // Valid queries.
257  if (input_masks == nullptr || input_masks[tid]) {
258  if (output_keys != nullptr) {
259  uint8_t* dst_key_ptr =
260  static_cast<uint8_t*>(output_keys) + dsize_key * tid;
261  uint8_t* src_key_ptr =
262  static_cast<uint8_t*>(input_iterators[tid].first);
263  MemoryManager::Memcpy(dst_key_ptr, device, src_key_ptr, device,
264  dsize_key);
265  }
266 
267  if (output_values != nullptr) {
268  uint8_t* dst_value_ptr =
269  static_cast<uint8_t*>(output_values) + dsize_value * tid;
270  uint8_t* src_value_ptr =
271  static_cast<uint8_t*>(input_iterators[tid].second);
272  MemoryManager::Memcpy(dst_value_ptr, device, src_value_ptr, device,
273  dsize_value);
274  }
275  }
276 }
277 
278 template <typename Hash, typename KeyEq>
280  const bool* input_masks,
281  void* output_keys,
282  void* output_values,
283  size_t iterator_count) {
284  for (size_t i = 0; i < iterator_count; ++i) {
285  UnpackIteratorsStep(input_iterators, input_masks, output_keys,
286  output_values, this->device_, this->dsize_key_,
287  this->dsize_value_, i);
288  }
289 }
290 
291 void AssignIteratorsStep(iterator_t* input_iterators,
292  const bool* input_masks,
293  const void* input_values,
294  const Device& device,
295  size_t dsize_value,
296  size_t tid) {
297  // Valid queries.
298  if (input_masks == nullptr || input_masks[tid]) {
299  const uint8_t* src_value_ptr =
300  static_cast<const uint8_t*>(input_values) + dsize_value * tid;
301  uint8_t* dst_value_ptr =
302  static_cast<uint8_t*>(input_iterators[tid].second);
303  MemoryManager::Memcpy(dst_value_ptr, device, src_value_ptr, device,
304  dsize_value);
305  }
306 }
307 
308 template <typename Hash, typename KeyEq>
310  const bool* input_masks,
311  const void* input_values,
312  size_t iterator_count) {
313  for (size_t i = 0; i < iterator_count; ++i) {
314  AssignIteratorsStep(input_iterators, input_masks, input_values,
315  this->device_, this->dsize_value_, i);
316  }
317 }
318 
319 template <typename Hash, typename KeyEq>
320 void CPUHashmap<Hash, KeyEq>::Rehash(size_t buckets) {
321  impl_->rehash(buckets);
322 }
323 
324 template <typename Hash, typename KeyEq>
325 std::vector<size_t> CPUHashmap<Hash, KeyEq>::BucketSizes() const {
326  size_t bucket_count = impl_->bucket_count();
327  std::vector<size_t> ret;
328  for (size_t i = 0; i < bucket_count; ++i) {
329  ret.push_back(impl_->bucket_size(i));
330  }
331  return ret;
332 }
333 
334 template <typename Hash, typename KeyEq>
336  return impl_->load_factor();
337 }
338 
339 } // namespace core
340 } // namespace open3d
void * first
Definition: Traits.h:56
~CPUHashmap()
Definition: HashmapCPU.h:112
static void Memcpy(void *dst_ptr, const Device &dst_device, const void *src_ptr, const Device &src_device, size_t num_bytes)
Definition: MemoryManager.cpp:48
size_t GetIterators(iterator_t *output_iterators) override
Parallel collect all iterators in the hash table.
Definition: HashmapCPU.h:237
void Insert(const void *input_keys, const void *input_values, iterator_t *output_iterators, bool *output_masks, size_t count) override
Parallel insert contiguous arrays of keys and values.
Definition: HashmapCPU.h:126
CPUHashmap(size_t init_buckets, size_t init_capacity, size_t dsize_key, size_t dsize_value, const Device &device)
Definition: HashmapCPU.h:95
void UnpackIteratorsStep(const iterator_t *input_iterators, const bool *input_masks, void *output_keys, void *output_values, const Device &device, size_t dsize_key, size_t dsize_value, size_t tid)
Definition: HashmapCPU.h:248
static void Free(void *ptr, const Device &device)
Definition: MemoryManager.cpp:44
void AssignIteratorsStep(iterator_t *input_iterators, const bool *input_masks, const void *input_values, const Device &device, size_t dsize_value, size_t tid)
Definition: HashmapCPU.h:291
void Erase(const void *input_keys, bool *output_masks, size_t count) override
Parallel erase a contiguous array of keys.
Definition: HashmapCPU.h:224
size_t bucket_count_
Definition: DeviceHashmap.h:172
static void * Malloc(size_t byte_size, const Device &device)
Definition: MemoryManager.cpp:40
float LoadFactor() const override
Return size / bucket_count.
Definition: HashmapCPU.h:335
Base class: shared interface.
Definition: DeviceHashmap.h:91
void UnpackIterators(const iterator_t *input_iterators, const bool *input_masks, void *output_keys, void *output_values, size_t count) override
Parallel unpack iterators to contiguous arrays of keys and/or values.
Definition: HashmapCPU.h:279
size_t capacity_
Definition: DeviceHashmap.h:173
void AssignIterators(iterator_t *input_iterators, const bool *input_masks, const void *input_values, size_t count) override
Parallel assign iterators in-place with associated values.
Definition: HashmapCPU.h:309
Definition: Device.h:39
Definition: Traits.h:51
int count
Definition: FilePCD.cpp:61
size_t Size() const override
Definition: HashmapCPU.h:121
Device device_
Definition: DeviceHashmap.h:176
std::vector< size_t > BucketSizes() const override
Definition: HashmapCPU.h:325
Definition: PinholeCameraIntrinsic.cpp:35
Definition: HashmapCPU.h:37
void * second
Definition: Traits.h:57
size_t dsize_key_
Definition: DeviceHashmap.h:174
void Rehash(size_t buckets) override
Definition: HashmapCPU.h:320
void Activate(const void *input_keys, iterator_t *output_iterators, bool *output_masks, size_t count) override
Definition: HashmapCPU.h:167
size_t dsize_value_
Definition: DeviceHashmap.h:175
void Find(const void *input_keys, iterator_t *output_iterators, bool *output_masks, size_t count) override
Parallel find a contiguous array of keys.
Definition: HashmapCPU.h:204