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> 76 template <
typename KeyT,
typename HashT, KeyT INVALID_KEY = 0xFFFFFFFF>
92 HashSet(
const uint32 _table_size, KeyT* _hash, KeyT* _unique, uint32* _count) :
93 table_size(_table_size),
105 void insert(
const KeyT key,
const HashT hash_code)
107 const HashT skip = (hash_code / table_size) | 1;
109 HashT slot = hash_code;
110 KeyT old = INVALID_KEY;
114 slot = (slot + skip) & (table_size - 1);
115 old = atomicCAS( &hash[slot], INVALID_KEY, key );
116 }
while (old != INVALID_KEY && old != key);
119 if (old == INVALID_KEY)
121 const uint32 unique_id =
atomic_add( count, 1 );
122 unique[ unique_id ] = key;
129 uint32
size()
const {
return *count; }
145 template <
typename KeyT,
typename HashT, u
int32 CTA_SIZE, u
int32 TABLE_SIZE, KeyT INVALID_KEY = 0xFFFFFFFF>
150 KeyT
hash[TABLE_SIZE];
151 KeyT unique[TABLE_SIZE];
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;
173 if (threadIdx.x == 0)
201 template <
typename KeyT,
typename HashT, KeyT INVALID_KEY = 0xFFFFFFFF>
218 HashMap(
const uint32 _table_size, KeyT* _hash, KeyT* _unique, uint32* _slots, uint32* _count) :
219 table_size(_table_size),
231 void insert(
const KeyT key,
const HashT hash_code)
233 const HashT skip = (hash_code / table_size) | 1;
235 HashT slot = hash_code;
236 KeyT old = INVALID_KEY;
240 slot = (slot + skip) & (table_size - 1);
241 old = atomicCAS( &
hash[slot], INVALID_KEY, key );
242 }
while (old != INVALID_KEY && old != key);
245 if (old == INVALID_KEY)
247 const uint32 unique_id =
atomic_add( count, 1 );
248 unique[ unique_id ] = key;
249 slots[ slot ] = unique_id;
256 uint32
find(
const KeyT key,
const HashT hash_code)
258 const HashT skip = (hash_code / table_size) | 1;
260 HashT slot = hash_code;
264 slot = (slot + skip) & (table_size - 1);
265 if (
hash[slot] == INVALID_KEY)
268 while (
hash[slot] != key);
276 uint32
size()
const {
return *count; }
321 template <
typename KeyT,
typename HashT, u
int32 CTA_SIZE, u
int32 TABLE_SIZE, KeyT INVALID_KEY = 0xFFFFFFFF>
326 KeyT
hash[TABLE_SIZE];
327 KeyT unique[TABLE_SIZE];
328 uint32 slots[TABLE_SIZE];
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;
350 if (threadIdx.x == 0)
375 template <
typename KeyT,
typename HashT, KeyT INVALID_KEY = 0xFFFFFFFF>
378 static const uint32 BUCKET_SIZE = 1;
394 SyncFreeHashMap(
const uint32 _table_size, KeyT* _hash, KeyT* _unique, uint32* _slots, uint32* _count) :
396 unique((
volatile KeyT*)_unique),
397 slots((
volatile uint32*)_slots),
399 table_size(_table_size) {}
407 bool try_insert(
const KeyT key,
const HashT hash_code,
const uint32 n)
409 const HashT skip = (hash_code / table_size) | 1;
411 HashT slot = hash_code;
412 KeyT old = INVALID_KEY;
414 slot = (slot + skip * n) & (table_size - 1u);
415 old = atomicCAS(&
hash[slot], INVALID_KEY, key);
416 if (old == INVALID_KEY || old == key)
419 if (old == INVALID_KEY)
421 const uint32 unique_id =
atomic_add(count, 1);
422 unique[unique_id] = key;
423 slots[slot] = unique_id;
437 void insert(
const KeyT key,
const HashT hash_code)
439 const HashT skip = (hash_code / table_size) | 1;
441 HashT slot = hash_code;
442 KeyT old = INVALID_KEY;
446 slot = (slot + skip) & (table_size - 1u);
447 old = atomicCAS( &
hash[slot], INVALID_KEY, key );
448 }
while (old != INVALID_KEY && old != key);
451 if (old == INVALID_KEY)
453 const uint32 unique_id =
atomic_add( count, 1 );
454 unique[ unique_id ] = key;
455 slots[ slot ] = unique_id;
466 bool insert(
const KeyT key,
const HashT hash_code, uint32* pos)
468 const HashT skip = (hash_code / table_size) | 1;
470 HashT slot = hash_code;
471 KeyT old = INVALID_KEY;
475 slot = (slot + skip) & (table_size - 1u);
476 old = atomicCAS( &
hash[slot], INVALID_KEY, key );
477 }
while (old != INVALID_KEY && old != key);
480 if (old == INVALID_KEY)
482 const uint32 unique_id =
atomic_add( count, 1 );
483 unique[ unique_id ] = key;
484 slots[ slot ] = unique_id;
492 while (slots[slot] == 0xFFFFFFFFu) {}
502 uint32 find(
const KeyT key,
const HashT hash_code)
504 const HashT skip = (hash_code / table_size) | 1;
506 HashT slot = hash_code;
510 slot = (slot + skip) & (table_size - 1u);
511 if (
hash[slot] == INVALID_KEY)
514 while (
hash[slot] != key);
517 while (slots[slot] == 0xFFFFFFFFu) {}
524 uint32
size()
const {
return *count; }
528 KeyT
get_unique(
const uint32 i)
const {
return unique[i]; }
531 volatile KeyT* unique;
532 volatile uint32* slots;
539 #define HASH_UNCACHED_LOAD(x) load<LOAD_VOLATILE>(x) 540 #define HASH_UNCACHED_STORE(x,v) store<STORE_VOLATILE>(x,v) 558 template <
typename KeyT,
typename HashT, KeyT INVALID_KEY = 0xFFFFFFFF>
561 static const uint32 BUCKET_SIZE = 8;
577 SyncFreeHashMap(
const uint32 _table_size, KeyT* _hash, KeyT* _unique, uint32* _slots, uint32* _count) :
582 table_size(_table_size) {}
590 bool try_insert(
const KeyT key,
const HashT hash_code,
const uint32 n)
592 const HashT skip = (hash_code / table_size) | 1;
594 HashT slot = hash_code;
595 KeyT old = INVALID_KEY;
598 slot = (slot + skip * n) & (table_size - 1u);
601 uint32 bucket = (slot / BUCKET_SIZE) * BUCKET_SIZE;
605 for (uint32 bucket_index = 0; bucket_index < BUCKET_SIZE; ++bucket_index)
607 old = atomicCAS( &
hash[bucket + bucket_index], INVALID_KEY, key );
608 if (old == INVALID_KEY || old == key)
610 slot = bucket + bucket_index;
615 if (old == INVALID_KEY || old == key)
618 if (old == INVALID_KEY)
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);
636 void insert(
const KeyT key,
const HashT hash_code)
638 const HashT skip = (hash_code / table_size) | 1;
640 HashT slot = hash_code;
641 KeyT old = INVALID_KEY;
646 slot = slot & (table_size - 1u);
649 uint32 bucket = (slot / BUCKET_SIZE) * BUCKET_SIZE;
653 for (uint32 bucket_index = 0; bucket_index < BUCKET_SIZE; ++bucket_index)
655 old = atomicCAS( &
hash[bucket + bucket_index], INVALID_KEY, key );
656 if (old == INVALID_KEY || old == key)
658 slot = bucket + bucket_index;
663 if (old == INVALID_KEY || old == key)
671 if (old == INVALID_KEY)
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);
686 bool insert(
const KeyT key,
const HashT hash_code, uint32* pos)
688 const HashT skip = (hash_code / table_size) | 1;
690 HashT slot = hash_code;
691 KeyT old = INVALID_KEY;
696 slot = slot & (table_size - 1u);
699 uint32 bucket = (slot / BUCKET_SIZE) * BUCKET_SIZE;
703 for (uint32 bucket_index = 0; bucket_index < BUCKET_SIZE; ++bucket_index)
705 old = atomicCAS( &
hash[bucket + bucket_index], INVALID_KEY, key );
706 if (old == INVALID_KEY || old == key)
708 slot = bucket + bucket_index;
713 if (old == INVALID_KEY || old == key)
721 if (old == INVALID_KEY)
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);
733 while (HASH_UNCACHED_LOAD(&slots[slot]) == 0xFFFFFFFFu) {}
743 uint32
find(
const KeyT key,
const HashT hash_code)
745 const HashT skip = (hash_code / table_size) | 1;
747 HashT slot = hash_code;
748 KeyT old = INVALID_KEY;
753 slot = slot & (table_size - 1u);
756 uint32 bucket = (slot / BUCKET_SIZE) * BUCKET_SIZE;
760 for (uint32 bucket_index = 0; bucket_index < BUCKET_SIZE; ++bucket_index)
762 old =
hash[bucket + bucket_index];
763 if (old == INVALID_KEY)
768 slot = bucket + bucket_index;
781 while (HASH_UNCACHED_LOAD(&slots[slot]) == 0xFFFFFFFFu) {}
788 uint32
size()
const {
return *count; }
817 template <
typename KeyT,
typename HashT, KeyT INVALID_KEY = 0xFFFFFFFF>
821 typedef typename pair_vector::type pair_type;
823 static const uint32 BUCKET_SIZE = 8;
843 unique((volatile KeyT*)_unique),
844 slots((volatile uint32*)_slots),
846 table_size(_table_size) {}
854 void insert(
const KeyT key1,
const KeyT key2,
const HashT hash_code)
856 const HashT skip = (hash_code / table_size) | 1;
858 HashT slot = hash_code;
859 KeyT old1 = INVALID_KEY;
864 slot = slot & (table_size - 1u);
866 old1 = atomicCAS( &hash1[slot], INVALID_KEY, key1 );
867 if (old1 == INVALID_KEY || old1 == key1)
870 KeyT old2 = INVALID_KEY;
874 const uint32 bucket = slot;
877 for (uint32 bucket_index = 0; bucket_index < BUCKET_SIZE; ++bucket_index)
879 old2 = atomicCAS( &
hash2[bucket + bucket_index], INVALID_KEY, key2 );
880 if (old2 == INVALID_KEY || old2 == key2)
883 slot = bucket + bucket_index;
886 if (old2 == INVALID_KEY)
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;
910 bool insert(
const KeyT key1,
const KeyT key2,
const HashT hash_code, uint32* pos)
912 const HashT skip = (hash_code / table_size) | 1;
914 HashT slot = hash_code;
915 KeyT old1 = INVALID_KEY;
920 slot = slot & (table_size - 1u);
922 old1 = atomicCAS( &hash1[slot], INVALID_KEY, key1 );
923 if (old1 == INVALID_KEY || old1 == key1)
926 KeyT old2 = INVALID_KEY;
929 const uint32 bucket = slot;
932 for (uint32 bucket_index = 0; bucket_index < BUCKET_SIZE; ++bucket_index)
934 old2 = atomicCAS( &
hash2[bucket + bucket_index], INVALID_KEY, key2 );
935 if (old2 == INVALID_KEY || old2 == key2)
938 slot = bucket + bucket_index;
941 if (old2 == INVALID_KEY)
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;
954 while (slots[slot] == 0xFFFFFFFFu) {}
971 uint32
find(
const KeyT key1,
const KeyT key2,
const HashT hash_code)
973 const HashT skip = (hash_code / table_size) | 1;
975 HashT slot = hash_code;
980 slot = slot & (table_size - 1u);
982 KeyT old1 = hash1[slot];
983 if (old1 == INVALID_KEY)
989 const uint32 bucket = slot;
993 for (uint32 bucket_index = 0; bucket_index < BUCKET_SIZE; ++bucket_index)
995 KeyT old2 =
hash2[bucket + bucket_index];
996 if (old2 == INVALID_KEY)
1002 slot = bucket + bucket_index;
1005 while (slots[slot] == 0xFFFFFFFFu) {}
1020 uint32
size()
const {
return *count; }
1024 pair_type
get_unique(
const uint32 i)
const {
return pair_vector::make(unique[i*2],unique[i*2+1]); }
1028 volatile KeyT* unique;
1029 volatile uint32* slots;
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
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
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
CUGAR_DEVICE bool insert(const KeyT key1, const KeyT key2, const HashT hash_code, uint32 *pos)
Definition: hash.h:910
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
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