Fermat
hash.h
1 /*
2  * cugar
3  * Copyright (c) 2011-2018, NVIDIA CORPORATION. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the NVIDIA CORPORATION nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
32 #pragma once
33 
34 #include <cugar/basic/types.h>
35 #include <cugar/basic/atomics.h>
36 #include <cugar/basic/numbers.h>
37 #include <cugar/basic/cuda/pointers.h>
38 
39 namespace cugar {
40 namespace cuda {
41 
46 
49 
52 
56 
76 template <typename KeyT, typename HashT, KeyT INVALID_KEY = 0xFFFFFFFF>
77 struct HashSet
78 {
81  CUGAR_DEVICE
82  HashSet() {}
83 
91  CUGAR_DEVICE
92  HashSet(const uint32 _table_size, KeyT* _hash, KeyT* _unique, uint32* _count) :
93  table_size(_table_size),
94  hash(_hash),
95  unique(_unique),
96  count(_count)
97  {}
98 
104  CUGAR_DEVICE
105  void insert(const KeyT key, const HashT hash_code)
106  {
107  const HashT skip = (hash_code / table_size) | 1;
108 
109  HashT slot = hash_code;
110  KeyT old = INVALID_KEY;
111 
112  do
113  {
114  slot = (slot + skip) & (table_size - 1);
115  old = atomicCAS( &hash[slot], INVALID_KEY, key );
116  } while (old != INVALID_KEY && old != key);
117 
118  // assign compacted vertex slots
119  if (old == INVALID_KEY)
120  {
121  const uint32 unique_id = atomic_add( count, 1 );
122  unique[ unique_id ] = key;
123  }
124  }
125 
128  CUGAR_DEVICE
129  uint32 size() const { return *count; }
130 
133  CUGAR_DEVICE
134  KeyT get_unique(const uint32 i) const { return unique[i]; }
135 
136  uint32 table_size;
137  KeyT* hash;
138  KeyT* unique;
139  uint32* count;
140 };
141 
145 template <typename KeyT, typename HashT, uint32 CTA_SIZE, uint32 TABLE_SIZE, KeyT INVALID_KEY = 0xFFFFFFFF>
146 struct BlockHashSet : public HashSet<KeyT,HashT,INVALID_KEY>
147 {
148  struct TempStorage
149  {
150  KeyT hash[TABLE_SIZE];
151  KeyT unique[TABLE_SIZE];
152  uint32 count;
153  };
154 
157  CUGAR_DEVICE
159 
164  CUGAR_DEVICE
165  BlockHashSet(TempStorage& _storage) : HashSet( TABLE_SIZE, _storage.hash, _storage.unique, &_storage.count )
166  {
167  // clear the table
168  const uint32 ITEMS_PER_THREAD = TABLE_SIZE / CTA_SIZE;
169  for (uint32 i = 0; i < ITEMS_PER_THREAD; ++i)
170  storage.hash[ CTA_SIZE * i + threadIdx.x ] = INVALID_KEY;
171 
172  // initialize the counter
173  if (threadIdx.x == 0)
174  storage.count = 0;
175 
176  __syncthreads();
177  }
178 };
179 
180 
201 template <typename KeyT, typename HashT, KeyT INVALID_KEY = 0xFFFFFFFF>
202 struct HashMap
203 {
206  CUGAR_DEVICE
207  HashMap() {}
208 
217  CUGAR_DEVICE
218  HashMap(const uint32 _table_size, KeyT* _hash, KeyT* _unique, uint32* _slots, uint32* _count) :
219  table_size(_table_size),
220  hash(_hash),
221  unique(_unique),
222  slots(_slots),
223  count(_count) {}
224 
230  CUGAR_DEVICE
231  void insert(const KeyT key, const HashT hash_code)
232  {
233  const HashT skip = (hash_code / table_size) | 1;
234 
235  HashT slot = hash_code;
236  KeyT old = INVALID_KEY;
237 
238  do
239  {
240  slot = (slot + skip) & (table_size - 1);
241  old = atomicCAS( &hash[slot], INVALID_KEY, key );
242  } while (old != INVALID_KEY && old != key);
243 
244  // assign compacted vertex slots
245  if (old == INVALID_KEY)
246  {
247  const uint32 unique_id = atomic_add( count, 1 );
248  unique[ unique_id ] = key;
249  slots[ slot ] = unique_id;
250  }
251  }
252 
255  CUGAR_DEVICE
256  uint32 find(const KeyT key, const HashT hash_code)
257  {
258  const HashT skip = (hash_code / table_size) | 1;
259 
260  HashT slot = hash_code;
261 
262  do
263  {
264  slot = (slot + skip) & (table_size - 1);
265  if (hash[slot] == INVALID_KEY)
266  return 0xFFFFFFFFu;
267  }
268  while (hash[slot] != key);
269 
270  return slots[slot];
271  }
272 
275  CUGAR_DEVICE
276  uint32 size() const { return *count; }
277 
280  CUGAR_DEVICE
281  KeyT get_unique(const uint32 i) const { return unique[i]; }
282 
283  uint32 table_size;
284  KeyT* hash;
285  KeyT* unique;
286  uint32* slots;
287  uint32* count;
288 };
289 
321 template <typename KeyT, typename HashT, uint32 CTA_SIZE, uint32 TABLE_SIZE, KeyT INVALID_KEY = 0xFFFFFFFF>
322 struct BlockHashMap : public HashMap<KeyT,HashT,INVALID_KEY>
323 {
324  struct TempStorage
325  {
326  KeyT hash[TABLE_SIZE];
327  KeyT unique[TABLE_SIZE];
328  uint32 slots[TABLE_SIZE];
329  uint32 count;
330  };
331 
334  CUGAR_DEVICE
336 
341  CUGAR_DEVICE
342  BlockHashMap(TempStorage& _storage) : HashMap( TABLE_SIZE, _storage.hash, _storage.unique, _storage.slots, &_storage.count )
343  {
344  // clear the table
345  const uint32 ITEMS_PER_THREAD = TABLE_SIZE / CTA_SIZE;
346  for (uint32 i = 0; i < ITEMS_PER_THREAD; ++i)
347  hash[ CTA_SIZE * i + threadIdx.x ] = INVALID_KEY;
348 
349  // initialize the counter
350  if (threadIdx.x == 0)
351  *count = 0;
352 
353  __syncthreads();
354  }
355 };
356 
357 #if 0
358 
375 template <typename KeyT, typename HashT, KeyT INVALID_KEY = 0xFFFFFFFF>
376 struct SyncFreeHashMap
377 {
378  static const uint32 BUCKET_SIZE = 1;
379 
382  CUGAR_HOST_DEVICE
383  SyncFreeHashMap() {}
384 
393  CUGAR_HOST_DEVICE
394  SyncFreeHashMap(const uint32 _table_size, KeyT* _hash, KeyT* _unique, uint32* _slots, uint32* _count) :
395  hash(_hash),
396  unique((volatile KeyT*)_unique),
397  slots((volatile uint32*)_slots),
398  count(_count),
399  table_size(_table_size) {}
400 
406  CUGAR_DEVICE
407  bool try_insert(const KeyT key, const HashT hash_code, const uint32 n)
408  {
409  const HashT skip = (hash_code / table_size) | 1;
410 
411  HashT slot = hash_code;
412  KeyT old = INVALID_KEY;
413 
414  slot = (slot + skip * n) & (table_size - 1u);
415  old = atomicCAS(&hash[slot], INVALID_KEY, key);
416  if (old == INVALID_KEY || old == key)
417  {
418  // assign compacted vertex slots
419  if (old == INVALID_KEY)
420  {
421  const uint32 unique_id = atomic_add(count, 1);
422  unique[unique_id] = key;
423  slots[slot] = unique_id;
424  __threadfence(); // make sure the write will eventually be visible
425  }
426  return true;
427  }
428  return false;
429  }
430 
436  CUGAR_DEVICE
437  void insert(const KeyT key, const HashT hash_code)
438  {
439  const HashT skip = (hash_code / table_size) | 1;
440 
441  HashT slot = hash_code;
442  KeyT old = INVALID_KEY;
443 
444  do
445  {
446  slot = (slot + skip) & (table_size - 1u);
447  old = atomicCAS( &hash[slot], INVALID_KEY, key );
448  } while (old != INVALID_KEY && old != key);
449 
450  // assign compacted vertex slots
451  if (old == INVALID_KEY)
452  {
453  const uint32 unique_id = atomic_add( count, 1 );
454  unique[ unique_id ] = key;
455  slots[ slot ] = unique_id;
456  __threadfence(); // make sure the write will eventually be visible
457  }
458  }
459 
465  CUGAR_DEVICE
466  bool insert(const KeyT key, const HashT hash_code, uint32* pos)
467  {
468  const HashT skip = (hash_code / table_size) | 1;
469 
470  HashT slot = hash_code;
471  KeyT old = INVALID_KEY;
472 
473  do
474  {
475  slot = (slot + skip) & (table_size - 1u);
476  old = atomicCAS( &hash[slot], INVALID_KEY, key );
477  } while (old != INVALID_KEY && old != key);
478 
479  // assign compacted vertex slots
480  if (old == INVALID_KEY)
481  {
482  const uint32 unique_id = atomic_add( count, 1 );
483  unique[ unique_id ] = key;
484  slots[ slot ] = unique_id;
485  __threadfence(); // make sure the write will eventually be visible
486  *pos = unique_id;
487  return true; // first thread to fetch this entry
488  }
489  else
490  {
491  // loop until the slot has been written to
492  while (slots[slot] == 0xFFFFFFFFu) {}
493 
494  *pos = slots[slot];
495  return false; // pre-existing entry
496  }
497  }
498 
501  CUGAR_DEVICE
502  uint32 find(const KeyT key, const HashT hash_code)
503  {
504  const HashT skip = (hash_code / table_size) | 1;
505 
506  HashT slot = hash_code;
507 
508  do
509  {
510  slot = (slot + skip) & (table_size - 1u);
511  if (hash[slot] == INVALID_KEY)
512  return 0xFFFFFFFFu;
513  }
514  while (hash[slot] != key);
515 
516  // loop until the slot has been written to
517  while (slots[slot] == 0xFFFFFFFFu) {}
518 
519  return slots[slot];
520  }
521 
524  uint32 size() const { return *count; }
525 
528  KeyT get_unique(const uint32 i) const { return unique[i]; }
529 
530  KeyT* hash;
531  volatile KeyT* unique;
532  volatile uint32* slots;
533  uint32* count;
534  uint32 table_size;
535 };
536 
537 #else
538 
539 #define HASH_UNCACHED_LOAD(x) load<LOAD_VOLATILE>(x)
540 #define HASH_UNCACHED_STORE(x,v) store<STORE_VOLATILE>(x,v)
541 
558 template <typename KeyT, typename HashT, KeyT INVALID_KEY = 0xFFFFFFFF>
560 {
561  static const uint32 BUCKET_SIZE = 8;
562 
565  CUGAR_HOST_DEVICE
567 
576  CUGAR_HOST_DEVICE
577  SyncFreeHashMap(const uint32 _table_size, KeyT* _hash, KeyT* _unique, uint32* _slots, uint32* _count) :
578  hash(_hash),
579  unique(_unique),
580  slots(_slots),
581  count(_count),
582  table_size(_table_size) {}
583 
589  CUGAR_DEVICE
590  bool try_insert(const KeyT key, const HashT hash_code, const uint32 n)
591  {
592  const HashT skip = (hash_code / table_size) | 1;
593 
594  HashT slot = hash_code;
595  KeyT old = INVALID_KEY;
596 
597  // advance by n buckets
598  slot = (slot + skip * n) & (table_size - 1u);
599 
600  // look into one bucket
601  uint32 bucket = (slot / BUCKET_SIZE) * BUCKET_SIZE;
602 
603  // search within the bucket
604  #pragma unroll
605  for (uint32 bucket_index = 0; bucket_index < BUCKET_SIZE; ++bucket_index)
606  {
607  old = atomicCAS( &hash[bucket + bucket_index], INVALID_KEY, key );
608  if (old == INVALID_KEY || old == key)
609  {
610  slot = bucket + bucket_index;
611  break;
612  }
613  }
614 
615  if (old == INVALID_KEY || old == key)
616  {
617  // assign compacted vertex slots
618  if (old == INVALID_KEY)
619  {
620  const uint32 unique_id = atomic_add(count, 1);
621  HASH_UNCACHED_STORE(&unique[unique_id], key);
622  HASH_UNCACHED_STORE(&slots[slot], unique_id);
623  __threadfence(); // make sure the write will eventually be visible
624  }
625  return true;
626  }
627  return false;
628  }
629 
635  CUGAR_DEVICE
636  void insert(const KeyT key, const HashT hash_code)
637  {
638  const HashT skip = (hash_code / table_size) | 1;
639 
640  HashT slot = hash_code;
641  KeyT old = INVALID_KEY;
642 
643  while (1)
644  {
645  // wrap around
646  slot = slot & (table_size - 1u);
647 
648  // find the bucket containing this slot
649  uint32 bucket = (slot / BUCKET_SIZE) * BUCKET_SIZE;
650 
651  // search within the bucket
652  #pragma unroll
653  for (uint32 bucket_index = 0; bucket_index < BUCKET_SIZE; ++bucket_index)
654  {
655  old = atomicCAS( &hash[bucket + bucket_index], INVALID_KEY, key );
656  if (old == INVALID_KEY || old == key)
657  {
658  slot = bucket + bucket_index;
659  break;
660  }
661  }
662 
663  if (old == INVALID_KEY || old == key)
664  break;
665 
666  // linear probing
667  slot = slot + skip;
668  }
669 
670  // assign compacted vertex slots
671  if (old == INVALID_KEY)
672  {
673  const uint32 unique_id = atomic_add( count, 1 );
674  HASH_UNCACHED_STORE(&unique[ unique_id ], key);
675  HASH_UNCACHED_STORE(&slots[ slot ], unique_id);
676  __threadfence(); // make sure the write will eventually be visible
677  }
678  }
679 
685  CUGAR_DEVICE
686  bool insert(const KeyT key, const HashT hash_code, uint32* pos)
687  {
688  const HashT skip = (hash_code / table_size) | 1;
689 
690  HashT slot = hash_code;
691  KeyT old = INVALID_KEY;
692 
693  while (1)
694  {
695  // wrap around
696  slot = slot & (table_size - 1u);
697 
698  // find the bucket containing this slot
699  uint32 bucket = (slot / BUCKET_SIZE) * BUCKET_SIZE;
700 
701  // search within the bucket
702  #pragma unroll
703  for (uint32 bucket_index = 0; bucket_index < BUCKET_SIZE; ++bucket_index)
704  {
705  old = atomicCAS( &hash[bucket + bucket_index], INVALID_KEY, key );
706  if (old == INVALID_KEY || old == key)
707  {
708  slot = bucket + bucket_index;
709  break;
710  }
711  }
712 
713  if (old == INVALID_KEY || old == key)
714  break;
715 
716  // linear probing
717  slot = slot + skip;
718  }
719 
720  // assign compacted vertex slots
721  if (old == INVALID_KEY)
722  {
723  const uint32 unique_id = atomic_add( count, 1 );
724  HASH_UNCACHED_STORE(&unique[ unique_id ], key);
725  HASH_UNCACHED_STORE(&slots[ slot ], unique_id);
726  __threadfence(); // make sure the write will eventually be visible
727  *pos = unique_id;
728  return true; // first thread to fetch this entry
729  }
730  else
731  {
732  // loop until the slot has been written to
733  while (HASH_UNCACHED_LOAD(&slots[slot]) == 0xFFFFFFFFu) {}
734 
735  *pos = slots[slot];
736  return false; // pre-existing entry
737  }
738  }
739 
742  CUGAR_DEVICE
743  uint32 find(const KeyT key, const HashT hash_code)
744  {
745  const HashT skip = (hash_code / table_size) | 1;
746 
747  HashT slot = hash_code;
748  KeyT old = INVALID_KEY;
749 
750  while (1)
751  {
752  // wrap around
753  slot = slot & (table_size - 1u);
754 
755  // find the bucket containing this slot
756  uint32 bucket = (slot / BUCKET_SIZE) * BUCKET_SIZE;
757 
758  // search within the bucket
759  #pragma unroll
760  for (uint32 bucket_index = 0; bucket_index < BUCKET_SIZE; ++bucket_index)
761  {
762  old = hash[bucket + bucket_index];
763  if (old == INVALID_KEY)
764  return 0xFFFFFFFFu;
765 
766  if (old == key)
767  {
768  slot = bucket + bucket_index;
769  break;
770  }
771  }
772 
773  if (old == key)
774  break;
775 
776  // linear probing
777  slot = slot + skip;
778  }
779 
780  // loop until the slot has been written to
781  while (HASH_UNCACHED_LOAD(&slots[slot]) == 0xFFFFFFFFu) {}
782 
783  return slots[slot];
784  }
785 
788  uint32 size() const { return *count; }
789 
792  KeyT get_unique(const uint32 i) const { return unique[i]; }
793 
794  KeyT* hash;
795  KeyT* unique;
796  uint32* slots;
797  uint32* count;
798  uint32 table_size;
799 };
800 
817 template <typename KeyT, typename HashT, KeyT INVALID_KEY = 0xFFFFFFFF>
819 {
821  typedef typename pair_vector::type pair_type;
822 
823  static const uint32 BUCKET_SIZE = 8;
824 
827  CUGAR_HOST_DEVICE
829 
839  CUGAR_HOST_DEVICE
840  SyncFreeDoubleKeyHashMap(const uint32 _table_size, KeyT* _hash1, KeyT* _hash2, KeyT* _unique, uint32* _slots, uint32* _count) :
841  hash1(_hash1),
842  hash2(_hash2),
843  unique((volatile KeyT*)_unique),
844  slots((volatile uint32*)_slots),
845  count(_count),
846  table_size(_table_size) {}
847 
853  CUGAR_DEVICE
854  void insert(const KeyT key1, const KeyT key2, const HashT hash_code)
855  {
856  const HashT skip = (hash_code / table_size) | 1;
857 
858  HashT slot = hash_code;
859  KeyT old1 = INVALID_KEY;
860 
861  while (1)
862  {
863  // wrap around
864  slot = slot & (table_size - 1u);
865 
866  old1 = atomicCAS( &hash1[slot], INVALID_KEY, key1 );
867  if (old1 == INVALID_KEY || old1 == key1)
868  {
869  // search the second key within this bucket
870  KeyT old2 = INVALID_KEY;
871 
872  // find the bucket containing this slot
873  //const uint32 bucket = (slot / BUCKET_SIZE) * BUCKET_SIZE;
874  const uint32 bucket = slot;
875 
876  #pragma unroll
877  for (uint32 bucket_index = 0; bucket_index < BUCKET_SIZE; ++bucket_index)
878  {
879  old2 = atomicCAS( &hash2[bucket + bucket_index], INVALID_KEY, key2 );
880  if (old2 == INVALID_KEY || old2 == key2)
881  {
882  // we found a slot!
883  slot = bucket + bucket_index;
884 
885  // assign compacted vertex slots
886  if (old2 == INVALID_KEY)
887  {
888  const uint32 unique_id = atomic_add( count, 1 );
889  unique[ unique_id*2 + 0 ] = key1;
890  unique[ unique_id*2 + 1 ] = key2;
891  slots[ slot ] = unique_id;
892  __threadfence(); // make sure the write will eventually be visible
893  }
894  return;
895  }
896  }
897  }
898 
899  // linear probing
900  slot = slot + skip;
901  }
902  }
903 
909  CUGAR_DEVICE
910  bool insert(const KeyT key1, const KeyT key2, const HashT hash_code, uint32* pos)
911  {
912  const HashT skip = (hash_code / table_size) | 1;
913 
914  HashT slot = hash_code;
915  KeyT old1 = INVALID_KEY;
916 
917  while (1)
918  {
919  // wrap around
920  slot = slot & (table_size - 1u);
921 
922  old1 = atomicCAS( &hash1[slot], INVALID_KEY, key1 );
923  if (old1 == INVALID_KEY || old1 == key1)
924  {
925  // search the second key within this bucket
926  KeyT old2 = INVALID_KEY;
927 
928  //const uint32 bucket = (slot / BUCKET_SIZE) * BUCKET_SIZE;
929  const uint32 bucket = slot;
930 
931  #pragma unroll
932  for (uint32 bucket_index = 0; bucket_index < BUCKET_SIZE; ++bucket_index)
933  {
934  old2 = atomicCAS( &hash2[bucket + bucket_index], INVALID_KEY, key2 );
935  if (old2 == INVALID_KEY || old2 == key2)
936  {
937  // we found a slot!
938  slot = bucket + bucket_index;
939 
940  // assign compacted vertex slots
941  if (old2 == INVALID_KEY)
942  {
943  const uint32 unique_id = atomic_add( count, 1 );
944  unique[ unique_id*2 + 0 ] = key1;
945  unique[ unique_id*2 + 1 ] = key2;
946  slots[ slot ] = unique_id;
947  __threadfence(); // make sure the write will eventually be visible
948  *pos = unique_id;
949  return true; // first thread to fetch this entry
950  }
951  else
952  {
953  // loop until the slot has been written to
954  while (slots[slot] == 0xFFFFFFFFu) {}
955 
956  *pos = slots[slot];
957  return false; // pre-existing entry
958  }
959  }
960  }
961  }
962 
963  // linear probing
964  slot = slot + skip;
965  }
966  }
967 
970  CUGAR_DEVICE
971  uint32 find(const KeyT key1, const KeyT key2, const HashT hash_code)
972  {
973  const HashT skip = (hash_code / table_size) | 1;
974 
975  HashT slot = hash_code;
976 
977  while (1)
978  {
979  // wrap around
980  slot = slot & (table_size - 1u);
981 
982  KeyT old1 = hash1[slot];
983  if (old1 == INVALID_KEY)
984  return 0xFFFFFFFFu;
985 
986  if (old1 == key1)
987  {
988  //const uint32 bucket = (slot / BUCKET_SIZE) * BUCKET_SIZE;
989  const uint32 bucket = slot;
990 
991  // search within the bucket
992  #pragma unroll
993  for (uint32 bucket_index = 0; bucket_index < BUCKET_SIZE; ++bucket_index)
994  {
995  KeyT old2 = hash2[bucket + bucket_index];
996  if (old2 == INVALID_KEY)
997  return 0xFFFFFFFFu;
998 
999  if (old2 == key2)
1000  {
1001  // we found our slot
1002  slot = bucket + bucket_index;
1003 
1004  // loop until the slot has been written to
1005  while (slots[slot] == 0xFFFFFFFFu) {}
1006 
1007  return slots[slot];
1008  }
1009  }
1010  }
1011 
1012  // linear probing
1013  slot = slot + skip;
1014  }
1015  //return 0xFFFFFFFFu;
1016  }
1017 
1020  uint32 size() const { return *count; }
1021 
1024  pair_type get_unique(const uint32 i) const { return pair_vector::make(unique[i*2],unique[i*2+1]); }
1025 
1026  KeyT* hash1;
1027  KeyT* hash2;
1028  volatile KeyT* unique;
1029  volatile uint32* slots;
1030  uint32* count;
1031  uint32 table_size;
1032 };
1033 
1034 #endif
1035 
1039 
1040 } // namespace cuda
1041 } // namespace cugar
CUGAR_DEVICE uint32 size() const
Definition: hash.h:276
CUGAR_DEVICE KeyT get_unique(const uint32 i) const
Definition: hash.h:281
CUGAR_DEVICE BlockHashMap()
Definition: hash.h:335
CUGAR_DEVICE uint32 find(const KeyT key, const HashT hash_code)
Definition: hash.h:256
pair_type get_unique(const uint32 i) const
Definition: hash.h:1024
Definition: hash.h:202
uint32 size() const
Definition: hash.h:1020
CUGAR_HOST_DEVICE SyncFreeDoubleKeyHashMap(const uint32 _table_size, KeyT *_hash1, KeyT *_hash2, KeyT *_unique, uint32 *_slots, uint32 *_count)
Definition: hash.h:840
uint32 size() const
Definition: hash.h:788
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE float atomic_add(float *value, const float op)
Definition: atomics.h:100
CUGAR_DEVICE void insert(const KeyT key, const HashT hash_code)
Definition: hash.h:636
CUGAR_DEVICE KeyT get_unique(const uint32 i) const
Definition: hash.h:134
CUGAR_DEVICE HashSet(const uint32 _table_size, KeyT *_hash, KeyT *_unique, uint32 *_count)
Definition: hash.h:92
KeyT get_unique(const uint32 i) const
Definition: hash.h:792
Definition: hash.h:322
CUGAR_DEVICE HashMap(const uint32 _table_size, KeyT *_hash, KeyT *_unique, uint32 *_slots, uint32 *_count)
Definition: hash.h:218
CUGAR_HOST_DEVICE SyncFreeHashMap()
Definition: hash.h:566
CUGAR_DEVICE void insert(const KeyT key, const HashT hash_code)
Definition: hash.h:231
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE uint32 hash2(uint32 key)
Definition: numbers.h:663
CUGAR_DEVICE bool insert(const KeyT key, const HashT hash_code, uint32 *pos)
Definition: hash.h:686
Definition: hash.h:77
CUGAR_DEVICE bool insert(const KeyT key1, const KeyT key2, const HashT hash_code, uint32 *pos)
Definition: hash.h:910
Definition: hash.h:559
CUGAR_DEVICE uint32 find(const KeyT key, const HashT hash_code)
Definition: hash.h:743
Definition: numbers.h:368
CUGAR_DEVICE BlockHashMap(TempStorage &_storage)
Definition: hash.h:342
CUGAR_DEVICE BlockHashSet(TempStorage &_storage)
Definition: hash.h:165
CUGAR_DEVICE uint32 size() const
Definition: hash.h:129
Define a vector_view POD type and plain_view() for std::vector.
Definition: diff.h:38
CUGAR_DEVICE uint32 find(const KeyT key1, const KeyT key2, const HashT hash_code)
Definition: hash.h:971
CUGAR_DEVICE void insert(const KeyT key, const HashT hash_code)
Definition: hash.h:105
CUGAR_DEVICE HashSet()
Definition: hash.h:82
CUGAR_HOST_DEVICE SyncFreeDoubleKeyHashMap()
Definition: hash.h:828
CUGAR_DEVICE BlockHashSet()
Definition: hash.h:158
Definition: hash.h:146
CUGAR_DEVICE void insert(const KeyT key1, const KeyT key2, const HashT hash_code)
Definition: hash.h:854
CUGAR_DEVICE HashMap()
Definition: hash.h:207
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE uint32 hash(uint32 a)
Definition: numbers.h:649
CUGAR_HOST_DEVICE SyncFreeHashMap(const uint32 _table_size, KeyT *_hash, KeyT *_unique, uint32 *_slots, uint32 *_count)
Definition: hash.h:577
CUGAR_DEVICE bool try_insert(const KeyT key, const HashT hash_code, const uint32 n)
Definition: hash.h:590