warpcore 0.0.1
Hashing at the Speed of Light on modern CUDA-accelerators
counting_hash_table.cuh
Go to the documentation of this file.
1 #ifndef WARPCORE_COUNTING_HASH_TABLE_CUH
2 #define WARPCORE_COUNTING_HASH_TABLE_CUH
3 
5 
6 namespace warpcore
7 {
8 
9 /*! \brief counting hash table
10  * \tparam Key key type (\c std::uint32_t or \c std::uint64_t)
11  * \tparam Value value type
12  * \tparam EmptyKey key which represents an empty slot
13  * \tparam TombstoneKey key which represents an erased slot
14  * \tparam ProbingScheme probing scheme from \c warpcore::probing_schemes
15  * \tparam TableStorage internal storage class \c warpcore::storage::key_value
16  * \tparam TempMemoryBytes size of temporary storage (typically a few kB)
17  */
18 template<
19  class Key,
20  class Value = index_t,
27 {
30 
31  static_assert(
33  "counter type must be either int, std::uint32_t or std::uint64_t");
34 
35 public:
36  using key_type = typename base_type::key_type;
37  using value_type = typename base_type::value_type;
38  using index_type = typename base_type::index_type;
39  using status_type = typename base_type::status_type;
40 
41  /*! \brief get empty key
42  * \return empty key
43  */
45  static constexpr key_type empty_key() noexcept
46  {
47  return base_type::empty_key();
48  }
49 
50  /*! \brief get tombstone key
51  * \return tombstone key
52  */
54  static constexpr key_type tombstone_key() noexcept
55  {
56  return base_type::tombstone_key();
57  }
58 
59  /*! \brief get cooperative group size
60  * \return cooperative group size
61  */
63  static constexpr index_type cg_size() noexcept
64  {
65  return base_type::cg_size();
66  }
67 
68  /*! \brief constructor
69  * \param[in] min_capacity minimum number of slots in the hash table
70  * \param[in] seed random seed
71  * \param[in] max_count count after which to stop counting new occurrences
72  * \param[in] no_init whether to initialize the table at construction or not
73  */
79  bool no_init = false) noexcept :
82  is_copy_(false)
83  {
84  if(!no_init) init(seed);
85  }
86 
87  /*! \brief copy-constructor (shallow)
88  * \param[in] object to be copied
89  */
94  is_copy_(true)
95  {}
96 
97  /*! \brief move-constructor
98  * \param[in] object to be moved
99  */
105  {
106  o.is_copy_ = true;
107  }
108 
109  /*! \brief (re)initialize the hash table
110  * \param[in] seed random seed
111  * \param[in] stream CUDA stream in which this operation is executed in
112  */
114  void init(
115  const key_type seed,
116  const cudaStream_t stream = 0) noexcept
117  {
119 
121  {
123  }
124  }
125 
126  /*! \brief (re)initialize the hash table
127  * \param[in] stream CUDA stream in which this operation is executed in
128  */
130  void init(const cudaStream_t stream = 0) noexcept
131  {
133  }
134 
135  /*! \brief inserts a key into the hash table
136  * \param[in] key_in key to insert into the hash table
137  * \param[in] group cooperative group
138  * \param[in] probing_length maximum number of probing attempts
139  * \return status (per thread)
140  */
144  const cg::thread_block_tile<cg_size()>& group,
146  {
148 
151 
152  if(group.thread_rank() == 0 && value_ptr != nullptr)
153  {
154  // this may not exactly stop counting when max_count is reached
155  // however, this is resolved during retireval
156  if(*value_ptr < max_count_)
157  {
158  const value_type old = atomicAdd(value_ptr, 1);
159 
160  // guard wrap-around
161  if(old > *value_ptr)
162  {
167  }
168  }
169  }
170 
171  return status;
172  }
173 
174  /*! \brief insert a set of keys into the hash table
175  * \tparam StatusHandler handles status per key (see \c status_handlers)
176  * \param[in] keys_in pointer to keys to insert into the hash table
177  * \param[in] num_in number of keys to insert
178  * \param[in] stream CUDA stream in which this operation is executed in
179  * \param[in] probing_length maximum number of probing attempts
180  * \param[out] status_out status information per key
181  */
182  template<class StatusHandler = defaults::status_handler_t>
184  void insert(
185  const key_type * keys_in,
187  cudaStream_t stream = 0,
189  typename StatusHandler::base_type * status_out = nullptr) noexcept
190  {
194  }
195 
196  /*! \brief retrieves a key from the hash table
197  * \param[in] key_in key to retrieve from the hash table
198  * \param[out] value_out count of \c key_in
199  * \param[in] group cooperative group
200  * \param[in] probing_length maximum number of probing attempts
201  * \return status (per thread)
202  */
207  const cg::thread_block_tile<cg_size()>& group,
208  index_type probing_length = defaults::probing_length()) const noexcept
209  {
210  value_type out;
211 
212  const status_type status =
214 
215  if(status.has_any())
216  {
217  value_out = 0;
218  }
219  else
220  {
222  }
223 
224  return status;
225  }
226 
227  /*! \brief retrieve a set of keys from the hash table
228  * \tparam StatusHandler handles status per key (see \c status_handlers)
229  * \param[in] keys_in pointer to keys to retrieve from the hash table
230  * \param[in] num_in number of keys to retrieve
231  * \param[out] values_out corresponding counts of keys in \c key_in
232  * \param[in] stream CUDA stream in which this operation is executed in
233  * \param[in] probing_length maximum number of probing attempts
234  * \param[out] status_out status information (per key)
235  */
236  template<class StatusHandler = defaults::status_handler_t>
238  void retrieve(
239  const key_type * keys_in,
242  cudaStream_t stream = 0,
244  typename StatusHandler::base_type * status_out = nullptr) const noexcept
245  {
249  }
250 
251  /*! \brief retrieves all elements from the hash table
252  * \param[out] keys_out location to store all retrieved keys
253  * \param[out] values_out location to store all retrieved counts
254  * \param[out] num_out number of of key/value pairs retrieved
255  * \param[in] stream CUDA stream in which this operation is executed in
256  */
259  key_type * keys_out,
261  index_t& num_out,
262  cudaStream_t stream = 0) const noexcept
263  {
265  }
266 
267  /*! \brief erases a key from the hash table
268  * \param[in] key_in key to erase from the hash table
269  * \param[in] group cooperative group
270  * \param[in] probing_length maximum number of probing attempts
271  * \return status (per thread)
272  */
276  const cg::thread_block_tile<cg_size()>& group,
278  {
280  }
281 
282  /*! \brief erases a set of keys from the hash table
283  * \tparam StatusHandler handles status per key (see \c status_handlers)
284  * \param[in] keys_in pointer to keys to erase from the hash table
285  * \param[in] num_in number of keys to erase
286  * \param[in] stream CUDA stream in which this operation is executed in
287  * \param[in] probing_length maximum number of probing attempts
288  * \param[out] status_out status information (per key)
289  */
290  template<class StatusHandler = defaults::status_handler_t>
292  void erase(
293  key_type * keys_in,
295  cudaStream_t stream = 0,
297  typename StatusHandler::base_type * status_out = nullptr) noexcept
298  {
299  base_table_.template erase<StatusHandler>(
301  }
302 
303  /*! \brief applies a funtion on all key value pairs inside the table
304  * \tparam Func type of map i.e. CUDA device lambda
305  * \param[in] f map to apply
306  * \param[in] stream CUDA stream in which this operation is executed in
307  * \param[in] size of shared memory to reserve for this execution
308  */
309  template<class Func>
311  void for_each(
312  Func f,
313  cudaStream_t stream = 0,
314  index_type smem_bytes = 0) const noexcept
315  {
317  }
318 
319  /*! \brief number of key/value pairs stored inside the hash table
320  * \param stream CUDA stream in which this operation is executed in
321  * \return the number of key/value pairs inside the hash table
322  */
324  index_type size(cudaStream_t stream = 0) const noexcept
325  {
326  return base_table_.size(stream);
327  }
328 
329  /*! \brief current load factor of the hash table
330  * \param stream CUDA stream in which this operation is executed in
331  * \return load factor
332  */
334  float load_factor(cudaStream_t stream = 0) const noexcept
335  {
337  }
338 
339  /*! \brief current storage density of the hash table
340  * \param stream CUDA stream in which this operation is executed in
341  * \return storage density
342  */
344  float storage_density(cudaStream_t stream = 0) const noexcept
345  {
347  }
348 
349  /*! \brief get the capacity of the hash table
350  * \return number of slots in the hash table
351  */
353  index_type capacity() const noexcept
354  {
355  return base_table_.capacity();
356  }
357 
358  /*! \brief get the status of the hash table
359  * \param stream CUDA stream in which this operation is executed in
360  * \return the status
361  */
364  {
366  }
367 
368  /*! \brief get and reset the status of the hash table
369  * \param stream CUDA stream in which this operation is executed in
370  * \return the status
371  */
374  {
375  return base_table_.pop_status(stream);
376  }
377 
378  /*! \brief checks if \c key is equal to \c EmptyKey
379  * \return \c bool
380  */
382  static constexpr bool is_empty_key(key_type key) noexcept
383  {
384  return base_type::is_empty_key(key);
385  }
386 
387  /*! \brief checks if \c key is equal to \c TombstoneKey
388  * \return \c bool
389  */
391  static constexpr bool is_tombstone_key(key_type key) noexcept
392  {
393  return base_type::is_tombstone_key(key);
394  }
395 
396  /*! \brief checks if \c key is equal to \c (EmptyKey||TombstoneKey)
397  * \return \c bool
398  */
400  static constexpr bool is_valid_key(key_type key) noexcept
401  {
402  return base_type::is_valid_key(key);
403  }
404 
405  /*! \brief get random seed
406  * \return seed
407  */
409  key_type seed() const noexcept
410  {
411  return base_table_.seed();
412  }
413 
414  /*! \brief indicates if this object is a shallow copy
415  * \return \c bool
416  */
418  bool is_copy() const noexcept
419  {
420  return is_copy_;
421  }
422 
423 private:
424  base_type base_table_; //< base type aka SingleValueHashTable
425  const value_type max_count_; //< count after which new occurrences are ignored
426  bool is_copy_; //< indicates if this object is a shallow copy
427 
428 }; // class CountingHashTable
429 
430 } // namespace warpcore
431 
432 #endif /* WARPCORE_COUNTING_HASH_TABLE_CUH */