GPU-Accelerated Cuckoo Filter
Loading...
Searching...
No Matches
Classes | Public Types | Public Member Functions | Static Public Member Functions | Public Attributes | Static Public Attributes | List of all members
cuckoogpu::Filter< Config > Struct Template Reference

A CUDA-accelerated Cuckoo Filter implementation. More...

Collaboration diagram for cuckoogpu::Filter< Config >:
[legend]

Classes

struct  Bucket
 Bucket structure that holds the fingerprint and tags for a given bucket. More...
 
struct  PackedTag
 This is used by the sorted insert kernel to store the fingerprint and primary bucket index in a compact format that allows you to sort them directly since the bucket index lives in the upper bits. More...
 

Public Types

using T = typename Config::KeyType
 
using TagType = typename Config::TagType
 
using AltBucketPolicy = typename Config::AltBucketPolicy
 
using PackedTagType = typename std::conditional< bitsPerTag<=8, uint32_t, uint64_t >::type
 

Public Member Functions

 Filter (const Filter &)=delete
 
Filteroperator= (const Filter &)=delete
 
 Filter (size_t capacity)
 Constructs a new Cuckoo Filter.
 
 ~Filter ()
 Destroys the Cuckoo Filter.
 
size_t insertMany (const T *d_keys, const size_t n, bool *d_output=nullptr, cudaStream_t stream={})
 Inserts a batch of keys into the filter.
 
size_t insertManySorted (const T *d_keys, const size_t n, bool *d_output=nullptr, cudaStream_t stream={})
 This pre-sorts the input keys based on the primary bucket index to allow for coalesced memory access when you later insert them into the filter.
 
void containsMany (const T *d_keys, const size_t n, bool *d_output, cudaStream_t stream={})
 Checks for the existence of a batch of keys.
 
size_t deleteMany (const T *d_keys, const size_t n, bool *d_output=nullptr, cudaStream_t stream={})
 Tries to remove a set of keys from the filter.
 
size_t insertMany (const thrust::device_vector< T > &d_keys, thrust::device_vector< bool > &d_output, cudaStream_t stream={})
 Inserts keys from a Thrust device vector.
 
size_t insertMany (const thrust::device_vector< T > &d_keys, thrust::device_vector< uint8_t > &d_output, cudaStream_t stream={})
 Inserts keys from a Thrust device vector (uint8_t output).
 
size_t insertMany (const thrust::device_vector< T > &d_keys, cudaStream_t stream={})
 Inserts keys from a Thrust device vector without outputting results.
 
size_t insertManySorted (const thrust::device_vector< T > &d_keys, thrust::device_vector< bool > &d_output, cudaStream_t stream={})
 Inserts keys from a Thrust device vector, sorting them first.
 
size_t insertManySorted (const thrust::device_vector< T > &d_keys, thrust::device_vector< uint8_t > &d_output, cudaStream_t stream={})
 Inserts keys from a Thrust device vector, sorting them first (uint8_t output).
 
size_t insertManySorted (const thrust::device_vector< T > &d_keys, cudaStream_t stream={})
 Inserts keys from a Thrust device vector, sorting them first, without outputting results.
 
void containsMany (const thrust::device_vector< T > &d_keys, thrust::device_vector< bool > &d_output, cudaStream_t stream={})
 Checks for existence of keys in a Thrust device vector.
 
void containsMany (const thrust::device_vector< T > &d_keys, thrust::device_vector< uint8_t > &d_output, cudaStream_t stream={})
 Checks for existence of keys in a Thrust device vector (uint8_t output).
 
size_t deleteMany (const thrust::device_vector< T > &d_keys, thrust::device_vector< bool > &d_output, cudaStream_t stream={})
 Deletes keys in a Thrust device vector.
 
size_t deleteMany (const thrust::device_vector< T > &d_keys, thrust::device_vector< uint8_t > &d_output, cudaStream_t stream={})
 Deletes keys in a Thrust device vector (uint8_t output).
 
size_t deleteMany (const thrust::device_vector< T > &d_keys, cudaStream_t stream={})
 Deletes keys in a Thrust device vector without outputting results.
 
void clear ()
 Clears the filter, removing all items.
 
float loadFactor ()
 Calculates the current load factor of the filter.
 
size_t occupiedSlots ()
 Returns the total number of occupied slots.
 
size_t deleteCasAttempts ()
 Returns the total number of delete CAS attempts (compare_exchange calls).
 
size_t deleteCasFailures ()
 Returns the total number of failed delete CAS attempts.
 
void resetDeleteCasCounters ()
 Resets the delete CAS counters to zero.
 
size_t capacity ()
 Returns the total capacity of the filter.
 
size_t getNumBuckets () const
 Returns the number of buckets in the filter.
 
size_t sizeInBytes () const
 Returns the size of the filter in bytes.
 
size_t countOccupiedSlots ()
 Counts occupied slots by iterating over all buckets on the host.
 
__device__ bool tryRemoveAtBucket (size_t bucketIdx, TagType tag)
 Attempt to remove a single instance of a fingerprint from a bucket.
 
__device__ bool tryInsertAtBucket (size_t bucketIdx, TagType tag)
 Attempts to insert a tag into a specific bucket.
 
__device__ bool insertWithEvictionDFS (TagType fp, size_t startBucket, uint32_t *evictionAttempts=nullptr)
 Inserts a fingerprint into the filter by evicting existing fingerprints.
 
__device__ bool insertWithEvictionBFS (TagType fp, size_t startBucket, uint32_t *evictionAttempts=nullptr)
 Inserts a fingerprint using repeated shallow breadth-first attempts.
 
__device__ bool insert (const T &key, uint32_t *evictionAttempts=nullptr)
 Inserts a single key into the filter.
 
__device__ bool contains (const T &key) const
 Checks if a key exists in the filter.
 
__device__ bool remove (const T &key)
 Removes a key from the filter.
 

Static Public Member Functions

template<typename H >
static __host__ __device__ uint64_t hash64 (const H &key)
 
static __host__ __device__ cuda::std::tuple< size_t, size_t, TagType, TagTypegetCandidateBucketsAndFPs (const T &key, size_t numBuckets)
 
static __host__ __device__ size_t getAlternateBucket (size_t bucket, TagType fp, size_t numBuckets)
 Computes the alternate bucket for a fingerprint.
 
static __host__ __device__ cuda::std::tuple< size_t, TagTypegetAlternateBucketWithNewFp (size_t bucket, TagType fp, size_t numBuckets)
 Computes alternate bucket AND updated fingerprint for choice bit policies.
 
static size_t calculateNumBuckets (size_t capacity)
 The number of buckets is enforced to be a power of two in order to allow for efficient modulo on the bucket indices.
 

Public Attributes

size_t numBuckets
 Number of buckets in the filter.
 
Bucketd_buckets
 Pointer to the device memory for the buckets.
 
cuda::std::atomic< size_t > * d_numOccupied {}
 Pointer to the device memory for the occupancy counter.
 
cuda::std::atomic< size_t > * d_deleteCasAttempts {}
 Pointer to device memory for the delete CAS attempt counter.
 
cuda::std::atomic< size_t > * d_deleteCasFailures {}
 Pointer to device memory for the failed delete CAS counter.
 
size_t h_numOccupied = 0
 Number of occupied buckets in the filter.
 

Static Public Attributes

static constexpr size_t bitsPerTag = Config::bitsPerTag
 
static constexpr size_t tagEntryBytes = sizeof(TagType)
 
static constexpr size_t bucketSize = Config::bucketSize
 
static constexpr size_t maxEvictions = Config::maxEvictions
 
static constexpr size_t blockSize = Config::blockSize
 
static constexpr TagType EMPTY = 0
 
static constexpr size_t fpMask = (1ULL << bitsPerTag) - 1
 

Detailed Description

template<typename Config>
struct cuckoogpu::Filter< Config >

A CUDA-accelerated Cuckoo Filter implementation.

This class implements a Cuckoo Filter using CUDA for high-throughput insertion, lookup, and deletion. It supports concurrent operations and uses atomic operations for thread safety within buckets.

Template Parameters
ConfigThe configuration structure defining filter parameters.

Definition at line 141 of file CuckooFilter.cuh.

Member Typedef Documentation

◆ AltBucketPolicy

template<typename Config >
using cuckoogpu::Filter< Config >::AltBucketPolicy = typename Config::AltBucketPolicy

Definition at line 146 of file CuckooFilter.cuh.

◆ PackedTagType

template<typename Config >
using cuckoogpu::Filter< Config >::PackedTagType = typename std::conditional<bitsPerTag <= 8, uint32_t, uint64_t>::type

Definition at line 160 of file CuckooFilter.cuh.

◆ T

template<typename Config >
using cuckoogpu::Filter< Config >::T = typename Config::KeyType

Definition at line 142 of file CuckooFilter.cuh.

◆ TagType

template<typename Config >
using cuckoogpu::Filter< Config >::TagType = typename Config::TagType

Definition at line 145 of file CuckooFilter.cuh.

Constructor & Destructor Documentation

◆ Filter() [1/2]

template<typename Config >
cuckoogpu::Filter< Config >::Filter ( const Filter< Config > &  )
delete

◆ Filter() [2/2]

template<typename Config >
cuckoogpu::Filter< Config >::Filter ( size_t  capacity)
inlineexplicit

Constructs a new Cuckoo Filter.

Allocates device memory for buckets and occupancy counters.

Parameters
capacityDesired capacity (number of items) for the filter.

Definition at line 411 of file CuckooFilter.cuh.

412 CUCKOO_CUDA_CALL(cudaMalloc(&d_buckets, numBuckets * sizeof(Bucket)));
413 CUCKOO_CUDA_CALL(cudaMalloc(&d_numOccupied, sizeof(cuda::std::atomic<size_t>)));
414#ifdef CUCKOO_FILTER_COUNT_DELETE_CAS
415 CUCKOO_CUDA_CALL(cudaMalloc(&d_deleteCasAttempts, sizeof(cuda::std::atomic<size_t>)));
416 CUCKOO_CUDA_CALL(cudaMalloc(&d_deleteCasFailures, sizeof(cuda::std::atomic<size_t>)));
417#endif
418#ifdef CUCKOO_FILTER_COUNT_EVICTIONS
419 CUCKOO_CUDA_CALL(cudaMalloc(&d_numEvictions, sizeof(cuda::std::atomic<size_t>)));
420#endif
421
422 clear();
423 }
cuda::std::atomic< size_t > * d_numOccupied
Pointer to the device memory for the occupancy counter.
static size_t calculateNumBuckets(size_t capacity)
The number of buckets is enforced to be a power of two in order to allow for efficient modulo on the ...
void clear()
Clears the filter, removing all items.
size_t numBuckets
Number of buckets in the filter.
Bucket * d_buckets
Pointer to the device memory for the buckets.
cuda::std::atomic< size_t > * d_deleteCasFailures
Pointer to device memory for the failed delete CAS counter.
cuda::std::atomic< size_t > * d_deleteCasAttempts
Pointer to device memory for the delete CAS attempt counter.
size_t capacity()
Returns the total capacity of the filter.
#define CUCKOO_CUDA_CALL(err)
Macro for checking CUDA errors.
Definition helpers.cuh:184
Here is the call graph for this function:

◆ ~Filter()

template<typename Config >
cuckoogpu::Filter< Config >::~Filter ( )
inline

Destroys the Cuckoo Filter.

Frees allocated device memory.

Definition at line 430 of file CuckooFilter.cuh.

430 {
431 if (d_buckets) {
432 CUCKOO_CUDA_CALL(cudaFree(d_buckets));
433 }
434 if (d_numOccupied) {
436 }
437#ifdef CUCKOO_FILTER_COUNT_DELETE_CAS
440 }
443 }
444#endif
445#ifdef CUCKOO_FILTER_COUNT_EVICTIONS
446 if (d_numEvictions) {
447 CUCKOO_CUDA_CALL(cudaFree(d_numEvictions));
448 }
449#endif
450 }

Member Function Documentation

◆ calculateNumBuckets()

template<typename Config >
static size_t cuckoogpu::Filter< Config >::calculateNumBuckets ( size_t  capacity)
inlinestatic

The number of buckets is enforced to be a power of two in order to allow for efficient modulo on the bucket indices.

Definition at line 397 of file CuckooFilter.cuh.

397 {
398 return AltBucketPolicy::calculateNumBuckets(capacity);
399 }
Here is the call graph for this function:

◆ capacity()

template<typename Config >
size_t cuckoogpu::Filter< Config >::capacity ( )
inline

Returns the total capacity of the filter.

Returns
size_t Total number of slots.

Definition at line 1076 of file CuckooFilter.cuh.

1076 {
1077 return numBuckets * bucketSize;
1078 }
static constexpr size_t bucketSize
Here is the caller graph for this function:

◆ clear()

template<typename Config >
void cuckoogpu::Filter< Config >::clear ( )
inline

Clears the filter, removing all items.

Definition at line 973 of file CuckooFilter.cuh.

973 {
974 CUCKOO_CUDA_CALL(cudaMemset(d_buckets, 0, numBuckets * sizeof(Bucket)));
975 CUCKOO_CUDA_CALL(cudaMemset(d_numOccupied, 0, sizeof(cuda::std::atomic<size_t>)));
976#ifdef CUCKOO_FILTER_COUNT_DELETE_CAS
977 CUCKOO_CUDA_CALL(cudaMemset(d_deleteCasAttempts, 0, sizeof(cuda::std::atomic<size_t>)));
978 CUCKOO_CUDA_CALL(cudaMemset(d_deleteCasFailures, 0, sizeof(cuda::std::atomic<size_t>)));
979#endif
980#ifdef CUCKOO_FILTER_COUNT_EVICTIONS
981 CUCKOO_CUDA_CALL(cudaMemset(d_numEvictions, 0, sizeof(cuda::std::atomic<size_t>)));
982#endif
983 h_numOccupied = 0;
984 }
size_t h_numOccupied
Number of occupied buckets in the filter.
Here is the caller graph for this function:

◆ contains()

template<typename Config >
__device__ bool cuckoogpu::Filter< Config >::contains ( const T key) const
inline

Checks if a key exists in the filter.

Parameters
keyThe key to check.
Returns
true if the key is found, false otherwise.

Definition at line 1466 of file CuckooFilter.cuh.

1466 {
1467 auto [i1, i2, fp1, fp2] = getCandidateBucketsAndFPs(key, numBuckets);
1468
1469 // fp1 is for bucket i1, fp2 is for bucket i2
1470 // For non-choice-bit policies, fp1 == fp2
1471 return d_buckets[i1].contains(fp1) || d_buckets[i2].contains(fp2);
1472 }
static __host__ __device__ cuda::std::tuple< size_t, size_t, TagType, TagType > getCandidateBucketsAndFPs(const T &key, size_t numBuckets)
__device__ bool contains(TagType tag) const
Checks if a tag is present in the bucket using vectorized loads.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ containsMany() [1/3]

template<typename Config >
void cuckoogpu::Filter< Config >::containsMany ( const T d_keys,
const size_t  n,
bool *  d_output,
cudaStream_t  stream = {} 
)
inline

Checks for the existence of a batch of keys.

Parameters
d_keysPointer to device memory containing keys to check.
nNumber of keys to check.
d_outputPointer to device memory to store results (true/false).
streamCUDA stream to use for the operation.

Definition at line 646 of file CuckooFilter.cuh.

646 {}) {
647 size_t numBlocks = SDIV(n, blockSize);
649 <<<numBlocks, blockSize, 0, stream>>>(d_keys, d_output, n, this);
650
651 CUCKOO_CUDA_CALL(cudaStreamSynchronize(stream));
652 }
static constexpr size_t blockSize
#define SDIV(x, y)
Integer division with rounding up (ceiling).
Definition helpers.cuh:178
__host__ __device__ __forceinline__ constexpr bool hasZero(WordType v)
Checks if a packed word contains a zero slot.
Definition helpers.cuh:96
Here is the caller graph for this function:

◆ containsMany() [2/3]

template<typename Config >
void cuckoogpu::Filter< Config >::containsMany ( const thrust::device_vector< T > &  d_keys,
thrust::device_vector< bool > &  d_output,
cudaStream_t  stream = {} 
)
inline

Checks for existence of keys in a Thrust device vector.

Parameters
d_keysVector of keys to check.
d_outputVector to store results (bool). Resized if necessary.
streamCUDA stream.

Definition at line 876 of file CuckooFilter.cuh.

879 {}
880 ) {
881 if (d_output.size() != d_keys.size()) {
882 d_output.resize(d_keys.size());
883 }
885 thrust::raw_pointer_cast(d_keys.data()),
886 d_keys.size(),
887 thrust::raw_pointer_cast(d_output.data()),
888 stream
889 );
890 }
void containsMany(const T *d_keys, const size_t n, bool *d_output, cudaStream_t stream={})
Checks for the existence of a batch of keys.

◆ containsMany() [3/3]

template<typename Config >
void cuckoogpu::Filter< Config >::containsMany ( const thrust::device_vector< T > &  d_keys,
thrust::device_vector< uint8_t > &  d_output,
cudaStream_t  stream = {} 
)
inline

Checks for existence of keys in a Thrust device vector (uint8_t output).

Parameters
d_keysVector of keys to check.
d_outputVector to store results (uint8_t). Resized if necessary.
streamCUDA stream.

Definition at line 898 of file CuckooFilter.cuh.

901 {}
902 ) {
903 if (d_output.size() != d_keys.size()) {
904 d_output.resize(d_keys.size());
905 }
907 thrust::raw_pointer_cast(d_keys.data()),
908 d_keys.size(),
909 reinterpret_cast<bool*>(thrust::raw_pointer_cast(d_output.data())),
910 stream
911 );
912 }

◆ countOccupiedSlots()

template<typename Config >
size_t cuckoogpu::Filter< Config >::countOccupiedSlots ( )
inline

Counts occupied slots by iterating over all buckets on the host.

This is a slow operation used for verification/debugging.

Returns
size_t Actual number of occupied slots.

Definition at line 1103 of file CuckooFilter.cuh.

1103 {
1104 std::vector<Bucket> h_buckets(numBuckets);
1105
1106 CUCKOO_CUDA_CALL(cudaMemcpy(
1107 h_buckets.data(), d_buckets, numBuckets * sizeof(Bucket), cudaMemcpyDeviceToHost
1108 ));
1109
1110 size_t occupiedCount = 0;
1111
1112 for (size_t bucketIdx = 0; bucketIdx < numBuckets; ++bucketIdx) {
1113 const Bucket& bucket = h_buckets[bucketIdx];
1114
1115 for (size_t atomicIdx = 0; atomicIdx < Bucket::wordCount; ++atomicIdx) {
1116 uint64_t packed = reinterpret_cast<const uint64_t&>(bucket.packedTags[atomicIdx]);
1117
1118 for (size_t tagIdx = 0; tagIdx < Bucket::tagsPerWord; ++tagIdx) {
1119 auto tag = bucket.extractTag(packed, tagIdx);
1120
1121 if (tag != EMPTY) {
1122 occupiedCount++;
1123 }
1124 }
1125 }
1126 }
1127
1128 return occupiedCount;
1129 }
static constexpr TagType EMPTY
static constexpr size_t tagsPerWord
static constexpr size_t wordCount
Here is the call graph for this function:

◆ deleteCasAttempts()

template<typename Config >
size_t cuckoogpu::Filter< Config >::deleteCasAttempts ( )
inline

Returns the total number of delete CAS attempts (compare_exchange calls).

Only available when CUCKOO_FILTER_COUNT_DELETE_CAS is defined.

Returns
size_t Number of delete CAS attempts.

Definition at line 1040 of file CuckooFilter.cuh.

1040 {
1041 size_t count;
1043 cudaMemcpy(&count, d_deleteCasAttempts, sizeof(size_t), cudaMemcpyDeviceToHost)
1044 );
1045 return count;
1046 }

◆ deleteCasFailures()

template<typename Config >
size_t cuckoogpu::Filter< Config >::deleteCasFailures ( )
inline

Returns the total number of failed delete CAS attempts.

Only available when CUCKOO_FILTER_COUNT_DELETE_CAS is defined.

Returns
size_t Number of failed delete CAS attempts.

Definition at line 1055 of file CuckooFilter.cuh.

1055 {
1056 size_t count;
1058 cudaMemcpy(&count, d_deleteCasFailures, sizeof(size_t), cudaMemcpyDeviceToHost)
1059 );
1060 return count;
1061 }

◆ deleteMany() [1/4]

template<typename Config >
size_t cuckoogpu::Filter< Config >::deleteMany ( const T d_keys,
const size_t  n,
bool *  d_output = nullptr,
cudaStream_t  stream = {} 
)
inline

Tries to remove a set of keys from the filter.

If the key is not present, it is ignored.

Parameters
d_keysPointer to the array of keys to remove
nNumber of keys to remove
d_outputOptional pointer to an output array indicating the success of each key removal
streamCUDA stream to use for the operation
Returns
size_t Updated number of occupied slots in the filter

Definition at line 665 of file CuckooFilter.cuh.

669 {}
670 ) {
671 size_t numBlocks = SDIV(n, blockSize);
673 <<<numBlocks, blockSize, 0, stream>>>(d_keys, d_output, n, this);
674
675 CUCKOO_CUDA_CALL(cudaStreamSynchronize(stream));
676
677 return occupiedSlots();
678 }
size_t occupiedSlots()
Returns the total number of occupied slots.
Here is the caller graph for this function:

◆ deleteMany() [2/4]

template<typename Config >
size_t cuckoogpu::Filter< Config >::deleteMany ( const thrust::device_vector< T > &  d_keys,
cudaStream_t  stream = {} 
)
inline

Deletes keys in a Thrust device vector without outputting results.

Parameters
d_keysVector of keys to delete.
streamCUDA stream.
Returns
size_t Total number of occupied slots.

Definition at line 966 of file CuckooFilter.cuh.

966 {}) {
967 return deleteMany(thrust::raw_pointer_cast(d_keys.data()), d_keys.size(), nullptr, stream);
968 }
size_t deleteMany(const T *d_keys, const size_t n, bool *d_output=nullptr, cudaStream_t stream={})
Tries to remove a set of keys from the filter.

◆ deleteMany() [3/4]

template<typename Config >
size_t cuckoogpu::Filter< Config >::deleteMany ( const thrust::device_vector< T > &  d_keys,
thrust::device_vector< bool > &  d_output,
cudaStream_t  stream = {} 
)
inline

Deletes keys in a Thrust device vector.

Parameters
d_keysVector of keys to delete.
d_outputVector to store results (bool). Resized if necessary.
streamCUDA stream.
Returns
size_t Total number of occupied slots.

Definition at line 921 of file CuckooFilter.cuh.

924 {}
925 ) {
926 if (d_output.size() != d_keys.size()) {
927 d_output.resize(d_keys.size());
928 }
929 return deleteMany(
930 thrust::raw_pointer_cast(d_keys.data()),
931 d_keys.size(),
932 thrust::raw_pointer_cast(d_output.data()),
933 stream
934 );
935 }

◆ deleteMany() [4/4]

template<typename Config >
size_t cuckoogpu::Filter< Config >::deleteMany ( const thrust::device_vector< T > &  d_keys,
thrust::device_vector< uint8_t > &  d_output,
cudaStream_t  stream = {} 
)
inline

Deletes keys in a Thrust device vector (uint8_t output).

Parameters
d_keysVector of keys to delete.
d_outputVector to store results (uint8_t). Resized if necessary.
streamCUDA stream.
Returns
size_t Total number of occupied slots.

Definition at line 944 of file CuckooFilter.cuh.

947 {}
948 ) {
949 if (d_output.size() != d_keys.size()) {
950 d_output.resize(d_keys.size());
951 }
952 return deleteMany(
953 thrust::raw_pointer_cast(d_keys.data()),
954 d_keys.size(),
955 reinterpret_cast<bool*>(thrust::raw_pointer_cast(d_output.data())),
956 stream
957 );
958 }

◆ getAlternateBucket()

template<typename Config >
static __host__ __device__ size_t cuckoogpu::Filter< Config >::getAlternateBucket ( size_t  bucket,
TagType  fp,
size_t  numBuckets 
)
inlinestatic

Computes the alternate bucket for a fingerprint.

Definition at line 376 of file CuckooFilter.cuh.

376 {
377 return AltBucketPolicy::getAlternateBucket(bucket, fp, numBuckets);
378 }

◆ getAlternateBucketWithNewFp()

template<typename Config >
static __host__ __device__ cuda::std::tuple< size_t, TagType > cuckoogpu::Filter< Config >::getAlternateBucketWithNewFp ( size_t  bucket,
TagType  fp,
size_t  numBuckets 
)
inlinestatic

Computes alternate bucket AND updated fingerprint for choice bit policies.

For non-choice-bit policies, returns the original fingerprint unchanged.

Definition at line 385 of file CuckooFilter.cuh.

385 {
386 if constexpr (AltBucketPolicy::usesChoiceBit) {
387 return AltBucketPolicy::getAlternateBucketWithNewFp(bucket, fp, numBuckets);
388 } else {
389 return {AltBucketPolicy::getAlternateBucket(bucket, fp, numBuckets), fp};
390 }
391 }
Here is the caller graph for this function:

◆ getCandidateBucketsAndFPs()

template<typename Config >
static __host__ __device__ cuda::std::tuple< size_t, size_t, TagType, TagType > cuckoogpu::Filter< Config >::getCandidateBucketsAndFPs ( const T key,
size_t  numBuckets 
)
inlinestatic

Definition at line 368 of file CuckooFilter.cuh.

368 {
369 return AltBucketPolicy::getCandidateBucketsAndFPs(key, numBuckets);
370 }
Here is the caller graph for this function:

◆ getNumBuckets()

template<typename Config >
size_t cuckoogpu::Filter< Config >::getNumBuckets ( ) const
inline

Returns the number of buckets in the filter.

Returns
size_t Number of buckets.

Definition at line 1084 of file CuckooFilter.cuh.

1084 {
1085 return numBuckets;
1086 }

◆ hash64()

template<typename Config >
template<typename H >
static __host__ __device__ uint64_t cuckoogpu::Filter< Config >::hash64 ( const H &  key)
inlinestatic

Definition at line 363 of file CuckooFilter.cuh.

363 {
364 return AltBucketPolicy::hash64(key);
365 }
Here is the caller graph for this function:

◆ insert()

template<typename Config >
__device__ bool cuckoogpu::Filter< Config >::insert ( const T key,
uint32_t *  evictionAttempts = nullptr 
)
inline

Inserts a single key into the filter.

Computes candidate buckets and attempts insertion, performing eviction if necessary.

Parameters
keyThe key to insert.
evictionAttemptsOptional pointer to a counter for eviction attempts
Returns
true if insertion succeeded, false if the filter is too full (max evictions reached).

Definition at line 1428 of file CuckooFilter.cuh.

1428 {
1429 auto [i1, i2, fp1, fp2] = getCandidateBucketsAndFPs(key, numBuckets);
1430
1431 // For all policies: fp1 is for bucket i1, fp2 is for bucket i2
1432 // For non-choice-bit policies, fp1 == fp2
1433 if (tryInsertAtBucket(i1, fp1) || tryInsertAtBucket(i2, fp2)) {
1434 return true;
1435 }
1436
1437 // For eviction, use correct fingerprint for the starting bucket
1438 auto startBucket = (fp1 & 1) == 0 ? i1 : i2;
1439 TagType evictFp;
1440
1441 if constexpr (AltBucketPolicy::usesChoiceBit) {
1442 evictFp = (fp1 & 1) == 0 ? fp1 : fp2;
1443 } else {
1444 evictFp = fp1;
1445 }
1446
1448 return insertWithEvictionBFS(evictFp, startBucket, evictionAttempts);
1449 } else if constexpr (Config::evictionPolicy == EvictionPolicy::DFS) {
1450 return insertWithEvictionDFS(evictFp, startBucket, evictionAttempts);
1451 } else {
1452 static_assert(
1455 "Unhandled eviction policy"
1456 );
1457 }
1458 }
__device__ bool tryInsertAtBucket(size_t bucketIdx, TagType tag)
Attempts to insert a tag into a specific bucket.
typename Config::TagType TagType
__device__ bool insertWithEvictionDFS(TagType fp, size_t startBucket, uint32_t *evictionAttempts=nullptr)
Inserts a fingerprint into the filter by evicting existing fingerprints.
__device__ bool insertWithEvictionBFS(TagType fp, size_t startBucket, uint32_t *evictionAttempts=nullptr)
Inserts a fingerprint using repeated shallow breadth-first attempts.
@ BFS
Breadth-first search (default)
@ DFS
Pure depth-first search.
static constexpr EvictionPolicy evictionPolicy
Here is the call graph for this function:
Here is the caller graph for this function:

◆ insertMany() [1/4]

template<typename Config >
size_t cuckoogpu::Filter< Config >::insertMany ( const T d_keys,
const size_t  n,
bool *  d_output = nullptr,
cudaStream_t  stream = {} 
)
inline

Inserts a batch of keys into the filter.

Parameters
d_keysPointer to device memory containing keys to insert.
nNumber of keys to insert.
d_outputOptional pointer to an output array indicating the success of each key insertion.
streamCUDA stream to use for the operation.
Returns
size_t Total number of occupied slots after insertion.

Definition at line 462 of file CuckooFilter.cuh.

466 {}
467 ) {
468 size_t numBlocks = SDIV(n, blockSize);
470 <<<numBlocks, blockSize, 0, stream>>>(d_keys, d_output, n, this, nullptr);
471
472 CUCKOO_CUDA_CALL(cudaStreamSynchronize(stream));
473
474 return occupiedSlots();
475 }
Here is the caller graph for this function:

◆ insertMany() [2/4]

template<typename Config >
size_t cuckoogpu::Filter< Config >::insertMany ( const thrust::device_vector< T > &  d_keys,
cudaStream_t  stream = {} 
)
inline

Inserts keys from a Thrust device vector without outputting results.

Parameters
d_keysVector of keys to insert.
streamCUDA stream.
Returns
size_t Total number of occupied slots.

Definition at line 732 of file CuckooFilter.cuh.

732 {}) {
733 return insertMany(thrust::raw_pointer_cast(d_keys.data()), d_keys.size(), nullptr, stream);
734 }
size_t insertMany(const T *d_keys, const size_t n, bool *d_output=nullptr, cudaStream_t stream={})
Inserts a batch of keys into the filter.

◆ insertMany() [3/4]

template<typename Config >
size_t cuckoogpu::Filter< Config >::insertMany ( const thrust::device_vector< T > &  d_keys,
thrust::device_vector< bool > &  d_output,
cudaStream_t  stream = {} 
)
inline

Inserts keys from a Thrust device vector.

Parameters
d_keysVector of keys to insert.
d_outputVector to store results (bool). Resized if necessary.
streamCUDA stream.
Returns
size_t Total number of occupied slots.

Definition at line 687 of file CuckooFilter.cuh.

690 {}
691 ) {
692 if (d_output.size() != d_keys.size()) {
693 d_output.resize(d_keys.size());
694 }
695 return insertMany(
696 thrust::raw_pointer_cast(d_keys.data()),
697 d_keys.size(),
698 thrust::raw_pointer_cast(d_output.data()),
699 stream
700 );
701 }

◆ insertMany() [4/4]

template<typename Config >
size_t cuckoogpu::Filter< Config >::insertMany ( const thrust::device_vector< T > &  d_keys,
thrust::device_vector< uint8_t > &  d_output,
cudaStream_t  stream = {} 
)
inline

Inserts keys from a Thrust device vector (uint8_t output).

Parameters
d_keysVector of keys to insert.
d_outputVector to store results (uint8_t). Resized if necessary.
streamCUDA stream.
Returns
size_t Total number of occupied slots.

Definition at line 710 of file CuckooFilter.cuh.

713 {}
714 ) {
715 if (d_output.size() != d_keys.size()) {
716 d_output.resize(d_keys.size());
717 }
718 return insertMany(
719 thrust::raw_pointer_cast(d_keys.data()),
720 d_keys.size(),
721 reinterpret_cast<bool*>(thrust::raw_pointer_cast(d_output.data())),
722 stream
723 );
724 }

◆ insertManySorted() [1/4]

template<typename Config >
size_t cuckoogpu::Filter< Config >::insertManySorted ( const T d_keys,
const size_t  n,
bool *  d_output = nullptr,
cudaStream_t  stream = {} 
)
inline

This pre-sorts the input keys based on the primary bucket index to allow for coalesced memory access when you later insert them into the filter.

Parameters
d_keysPointer to device memory array of keys to insert
nNumber of keys to insert
d_outputOptional pointer to an output array indicating the success of each key insertion.
streamCUDA stream to use for the operation.
Returns
size_t Updated number of occupied slots in the filter

Definition at line 517 of file CuckooFilter.cuh.

521 {}
522 ) {
523 PackedTagType* d_packedTags;
524
525 CUCKOO_CUDA_CALL(cudaMallocAsync(&d_packedTags, n * sizeof(PackedTagType), stream));
526
527 size_t numBlocks = SDIV(n, blockSize);
528
530 <<<numBlocks, blockSize, 0, stream>>>(d_keys, d_packedTags, n, numBuckets);
531
532 void* d_tempStorage = nullptr;
533 size_t tempStorageBytes = 0;
534
535 cub::DeviceRadixSort::SortKeys(
536 d_tempStorage,
537 tempStorageBytes,
538 d_packedTags,
539 d_packedTags,
540 n,
541 0,
542 sizeof(PackedTagType) * 8,
543 stream
544 );
545
546 CUCKOO_CUDA_CALL(cudaMallocAsync(&d_tempStorage, tempStorageBytes, stream));
547
548 cub::DeviceRadixSort::SortKeys(
549 d_tempStorage,
550 tempStorageBytes,
551 d_packedTags,
552 d_packedTags,
553 n,
554 0,
555 sizeof(PackedTagType) * 8,
556 stream
557 );
558
559 CUCKOO_CUDA_CALL(cudaFreeAsync(d_tempStorage, stream));
560
562 <<<numBlocks, blockSize, 0, stream>>>(d_packedTags, d_output, n, this, nullptr);
563
564 CUCKOO_CUDA_CALL(cudaFreeAsync(d_packedTags, stream));
565 CUCKOO_CUDA_CALL(cudaStreamSynchronize(stream));
566
567 return occupiedSlots();
568 }
typename std::conditional< bitsPerTag<=8, uint32_t, uint64_t >::type PackedTagType

◆ insertManySorted() [2/4]

template<typename Config >
size_t cuckoogpu::Filter< Config >::insertManySorted ( const thrust::device_vector< T > &  d_keys,
cudaStream_t  stream = {} 
)
inline

Inserts keys from a Thrust device vector, sorting them first, without outputting results.

Parameters
d_keysVector of keys to insert.
streamCUDA stream.
Returns
size_t Total number of occupied slots.

Definition at line 826 of file CuckooFilter.cuh.

826 {}) {
827 return insertManySorted(
828 thrust::raw_pointer_cast(d_keys.data()), d_keys.size(), nullptr, stream
829 );
830 }
size_t insertManySorted(const T *d_keys, const size_t n, bool *d_output=nullptr, cudaStream_t stream={})
This pre-sorts the input keys based on the primary bucket index to allow for coalesced memory access ...

◆ insertManySorted() [3/4]

template<typename Config >
size_t cuckoogpu::Filter< Config >::insertManySorted ( const thrust::device_vector< T > &  d_keys,
thrust::device_vector< bool > &  d_output,
cudaStream_t  stream = {} 
)
inline

Inserts keys from a Thrust device vector, sorting them first.

Parameters
d_keysVector of keys to insert.
d_outputVector to store results (bool). Resized if necessary.
streamCUDA stream.
Returns
size_t Total number of occupied slots.

Definition at line 780 of file CuckooFilter.cuh.

783 {}
784 ) {
785 if (d_output.size() != d_keys.size()) {
786 d_output.resize(d_keys.size());
787 }
788 return insertManySorted(
789 thrust::raw_pointer_cast(d_keys.data()),
790 d_keys.size(),
791 thrust::raw_pointer_cast(d_output.data()),
792 stream
793 );
794 }

◆ insertManySorted() [4/4]

template<typename Config >
size_t cuckoogpu::Filter< Config >::insertManySorted ( const thrust::device_vector< T > &  d_keys,
thrust::device_vector< uint8_t > &  d_output,
cudaStream_t  stream = {} 
)
inline

Inserts keys from a Thrust device vector, sorting them first (uint8_t output).

Parameters
d_keysVector of keys to insert.
d_outputVector to store results (uint8_t). Resized if necessary.
streamCUDA stream.
Returns
size_t Total number of occupied slots.

Definition at line 803 of file CuckooFilter.cuh.

806 {}
807 ) {
808 if (d_output.size() != d_keys.size()) {
809 d_output.resize(d_keys.size());
810 }
811 return insertManySorted(
812 thrust::raw_pointer_cast(d_keys.data()),
813 d_keys.size(),
814 reinterpret_cast<bool*>(thrust::raw_pointer_cast(d_output.data())),
815 stream
816 );
817 }

◆ insertWithEvictionBFS()

template<typename Config >
__device__ bool cuckoogpu::Filter< Config >::insertWithEvictionBFS ( TagType  fp,
size_t  startBucket,
uint32_t *  evictionAttempts = nullptr 
)
inline

Inserts a fingerprint using repeated shallow breadth-first attempts.

Each round scans a handful of candidate eviction slots in the current bucket and tries to place one candidate in its alternate bucket. If no shallow move succeeds, it evicts the last scanned candidate slot from the current bucket and restarts the same BFS round from that evicted tag's alternate bucket. This repeats until insertion succeeds or maxEvictions is reached.

Parameters
fpFingerprint to insert
evictionAttemptsOptional pointer to a counter for eviction attempts
startBucketIndex of the bucket to start the search from
Returns
true if the insertion was successful, false otherwise

Definition at line 1323 of file CuckooFilter.cuh.

1323 {
1324 constexpr size_t numCandidates = std::max(1UL, bucketSize / 2);
1325
1326 TagType currentFp = fp;
1327 size_t currentBucket = startBucket;
1328
1329 size_t evictions = 0;
1330 while (evictions < maxEvictions) {
1331 Bucket& bucket = d_buckets[currentBucket];
1332 size_t restartWord = 0;
1333 size_t restartTagIdx = 0;
1334
1335 for (size_t i = 0; i < numCandidates; ++i) {
1336 size_t evictSlot = (currentFp + i * 0x9E3779B1UL + (evictions + 1) * 0x85EBCA77) &
1337 (bucketSize - 1);
1338 size_t evictWord = evictSlot / Bucket::tagsPerWord;
1339 size_t evictTagIdx = evictSlot & (Bucket::tagsPerWord - 1);
1340 restartWord = evictWord;
1341 restartTagIdx = evictTagIdx;
1342
1343 auto packed = bucket.packedTags[evictWord].load(cuda::memory_order_relaxed);
1344 TagType candidateFp = bucket.extractTag(packed, evictTagIdx);
1345
1346 if (candidateFp == EMPTY) {
1347 if (tryInsertAtBucket(currentBucket, currentFp)) {
1348 return true;
1349 }
1350 continue;
1351 }
1352
1353 auto [altBucket, altFp] =
1354 getAlternateBucketWithNewFp(currentBucket, candidateFp, numBuckets);
1355 if (tryInsertAtBucket(altBucket, altFp)) {
1356 // Successfully inserted the evicted tag at its alternate location
1357 // Now atomically swap in our tag at the original location
1358 auto expected = bucket.packedTags[evictWord].load(cuda::memory_order_relaxed);
1359
1360 // Verify the tag is still there and try to replace it
1361 if (bucket.extractTag(expected, evictTagIdx) == candidateFp) {
1362 auto desired = bucket.replaceTag(expected, evictTagIdx, currentFp);
1363
1364 if (bucket.packedTags[evictWord].compare_exchange_strong(
1365 expected,
1366 desired,
1367 cuda::memory_order_relaxed,
1368 cuda::memory_order_relaxed
1369 )) {
1370#ifdef CUCKOO_FILTER_COUNT_EVICTIONS
1371 d_numEvictions->fetch_add(1, cuda::memory_order_relaxed);
1372 if (evictionAttempts != nullptr) {
1373 (*evictionAttempts)++;
1374 }
1375#endif
1376 return true;
1377 }
1378 }
1379
1380 // Failed to swap, clean up the tag we inserted to avoid duplicates
1381 tryRemoveAtBucket(altBucket, candidateFp);
1382 }
1383 }
1384
1385 // Evict the last scanned candidate and continue from its alternate location.
1386 auto expected = bucket.packedTags[restartWord].load(cuda::memory_order_relaxed);
1387 typename Bucket::WordType desired;
1388 TagType evictedFp;
1389
1390 do {
1391 evictedFp = bucket.extractTag(expected, restartTagIdx);
1392 desired = bucket.replaceTag(expected, restartTagIdx, currentFp);
1393 } while (!bucket.packedTags[restartWord].compare_exchange_strong(
1394 expected, desired, cuda::memory_order_relaxed, cuda::memory_order_relaxed
1395 ));
1396
1397 if (evictedFp == EMPTY) {
1398 return true;
1399 }
1400
1401#ifdef CUCKOO_FILTER_COUNT_EVICTIONS
1402 d_numEvictions->fetch_add(1, cuda::memory_order_relaxed);
1403 if (evictionAttempts != nullptr) {
1404 (*evictionAttempts)++;
1405 }
1406#endif
1407
1408 evictions++;
1409 auto [altBucket, altFp] =
1410 getAlternateBucketWithNewFp(currentBucket, evictedFp, numBuckets);
1411 currentBucket = altBucket;
1412 currentFp = altFp;
1413 }
1414
1415 return false;
1416 }
static constexpr size_t maxEvictions
static __host__ __device__ cuda::std::tuple< size_t, TagType > getAlternateBucketWithNewFp(size_t bucket, TagType fp, size_t numBuckets)
Computes alternate bucket AND updated fingerprint for choice bit policies.
__device__ bool tryRemoveAtBucket(size_t bucketIdx, TagType tag)
Attempt to remove a single instance of a fingerprint from a bucket.
typename Config::WordType WordType
cuda::std::atomic< WordType > packedTags[wordCount]
Here is the call graph for this function:
Here is the caller graph for this function:

◆ insertWithEvictionDFS()

template<typename Config >
__device__ bool cuckoogpu::Filter< Config >::insertWithEvictionDFS ( TagType  fp,
size_t  startBucket,
uint32_t *  evictionAttempts = nullptr 
)
inline

Inserts a fingerprint into the filter by evicting existing fingerprints.

The thread first picks a pseudo-random target to replace with the new fingerprint. Then it tries to insert the evicted fingerprint into its alternate bucket. This process is repeated until either a fingerprint is inserted into an empty slot or the maximum number of evictions is reached.

Parameters
fpFingerprint to insert
startBucketIndex of the bucket to start the search from
evictionAttemptsOptional pointer to a counter for eviction attempts
Returns
true if the insertion was successful, false otherwise

Definition at line 1266 of file CuckooFilter.cuh.

1266 {
1267 TagType currentFp = fp;
1268 size_t currentBucket = startBucket;
1269
1270 for (size_t evictions = 0; evictions < maxEvictions; ++evictions) {
1271 auto evictSlot = (currentFp + (evictions + 1) * 0x9E3779B1UL) & (bucketSize - 1);
1272
1273 size_t evictWord = evictSlot / Bucket::tagsPerWord;
1274 size_t evictTagIdx = evictSlot & (Bucket::tagsPerWord - 1);
1275
1276 Bucket& bucket = d_buckets[currentBucket];
1277 auto expected = bucket.packedTags[evictWord].load(cuda::memory_order_relaxed);
1278 typename Bucket::WordType desired;
1279 TagType evictedFp;
1280
1281 do {
1282 evictedFp = bucket.extractTag(expected, evictTagIdx);
1283 desired = bucket.replaceTag(expected, evictTagIdx, currentFp);
1284 } while (!bucket.packedTags[evictWord].compare_exchange_strong(
1285 expected, desired, cuda::memory_order_relaxed, cuda::memory_order_relaxed
1286 ));
1287
1288#ifdef CUCKOO_FILTER_COUNT_EVICTIONS
1289 d_numEvictions->fetch_add(1, cuda::memory_order_relaxed);
1290 if (evictionAttempts != nullptr) {
1291 (*evictionAttempts)++;
1292 }
1293#endif
1294
1295 currentFp = evictedFp;
1296 auto [altBucket, newFp] =
1297 getAlternateBucketWithNewFp(currentBucket, evictedFp, numBuckets);
1298 currentBucket = altBucket;
1299 currentFp = newFp;
1300
1301 if (tryInsertAtBucket(currentBucket, currentFp)) {
1302 return true;
1303 }
1304 }
1305 return false;
1306 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ loadFactor()

template<typename Config >
float cuckoogpu::Filter< Config >::loadFactor ( )
inline

Calculates the current load factor of the filter.

Returns
float Load factor (occupied slots / total capacity).

Definition at line 990 of file CuckooFilter.cuh.

990 {
991 return static_cast<float>(occupiedSlots()) / (numBuckets * bucketSize);
992 }
Here is the call graph for this function:

◆ occupiedSlots()

template<typename Config >
size_t cuckoogpu::Filter< Config >::occupiedSlots ( )
inline

Returns the total number of occupied slots.

Retrieves the value from the device counter.

Returns
size_t Number of occupied slots.

Definition at line 1001 of file CuckooFilter.cuh.

1001 {
1003 cudaMemcpy(&h_numOccupied, d_numOccupied, sizeof(size_t), cudaMemcpyDeviceToHost)
1004 );
1005 return h_numOccupied;
1006 }
Here is the caller graph for this function:

◆ operator=()

template<typename Config >
Filter & cuckoogpu::Filter< Config >::operator= ( const Filter< Config > &  )
delete

◆ remove()

template<typename Config >
__device__ bool cuckoogpu::Filter< Config >::remove ( const T key)
inline

Removes a key from the filter.

Parameters
keyThe key to remove.
Returns
true if the key was found and removed, false otherwise.

Definition at line 1480 of file CuckooFilter.cuh.

1480 {
1481 auto [i1, i2, fp1, fp2] = getCandidateBucketsAndFPs(key, numBuckets);
1482
1483 // fp1 is for bucket i1, fp2 is for bucket i2
1484 // For non-choice-bit policies, fp1 == fp2
1485 return tryRemoveAtBucket(i1, fp1) || tryRemoveAtBucket(i2, fp2);
1486 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ resetDeleteCasCounters()

template<typename Config >
void cuckoogpu::Filter< Config >::resetDeleteCasCounters ( )
inline

Resets the delete CAS counters to zero.

Definition at line 1066 of file CuckooFilter.cuh.

1066 {
1067 CUCKOO_CUDA_CALL(cudaMemset(d_deleteCasAttempts, 0, sizeof(cuda::std::atomic<size_t>)));
1068 CUCKOO_CUDA_CALL(cudaMemset(d_deleteCasFailures, 0, sizeof(cuda::std::atomic<size_t>)));
1069 }

◆ sizeInBytes()

template<typename Config >
size_t cuckoogpu::Filter< Config >::sizeInBytes ( ) const
inline

Returns the size of the filter in bytes.

Returns
size_t Size in bytes.

Definition at line 1092 of file CuckooFilter.cuh.

1092 {
1093 return numBuckets * sizeof(Bucket);
1094 }

◆ tryInsertAtBucket()

template<typename Config >
__device__ bool cuckoogpu::Filter< Config >::tryInsertAtBucket ( size_t  bucketIdx,
TagType  tag 
)
inline

Attempts to insert a tag into a specific bucket.

Scans the bucket for an empty slot and attempts to atomically place the tag.

Parameters
bucketIdxIndex of the bucket.
tagTag to insert.
Returns
true if insertion succeeded, false if the bucket is full.

Definition at line 1213 of file CuckooFilter.cuh.

1213 {
1214 Bucket& bucket = d_buckets[bucketIdx];
1215 const uint32_t startIdx = tag & (bucketSize - 1);
1216 const size_t startWord = startIdx / Bucket::tagsPerWord;
1217
1218 using WordType = typename Bucket::WordType;
1219
1220 for (size_t i = 0; i < Bucket::wordCount; ++i) {
1221 const size_t currWord = (startWord + i) & (Bucket::wordCount - 1);
1222 auto expected = bucket.packedTags[currWord].load(cuda::memory_order_relaxed);
1223
1224 while (true) {
1225 WordType zeroMask = detail::getZeroMask<TagType, WordType>(expected);
1226
1227 if (zeroMask == 0) {
1228 // No empty slots in this word, move to next
1229 break;
1230 }
1231
1232 // Find position of first empty slot (returns 1-indexed bit position)
1233 int bitPos;
1234 if constexpr (sizeof(WordType) == 4) {
1235 bitPos = __ffs(static_cast<int>(zeroMask)) - 1;
1236 } else {
1237 bitPos = __ffsll(static_cast<long long>(zeroMask)) - 1;
1238 }
1239 size_t j = bitPos / bitsPerTag;
1240
1241 auto desired = bucket.replaceTag(expected, j, tag);
1242
1243 if (bucket.packedTags[currWord].compare_exchange_strong(
1244 expected, desired, cuda::memory_order_relaxed, cuda::memory_order_relaxed
1245 )) {
1246 return true;
1247 }
1248 }
1249 }
1250 return false;
1251 }
static constexpr size_t bitsPerTag
Here is the call graph for this function:
Here is the caller graph for this function:

◆ tryRemoveAtBucket()

template<typename Config >
__device__ bool cuckoogpu::Filter< Config >::tryRemoveAtBucket ( size_t  bucketIdx,
TagType  tag 
)
inline

Attempt to remove a single instance of a fingerprint from a bucket.

Scans the atomic words that make up the bucket and attempts a CAS on each matching tag position until one removal succeeds. This allows multiple concurrent deleters to remove distinct copies when a bucket contains several identical fingerprints instead of all trying to clear the same slot

The function is lock-free and uses per-word compare-and-swap operations. It does NOT update any global occupancy counter, the caller is responsible for decrementing d_numOccupied if appropriate

Parameters
bucketIdxIndex of the bucket to search.
tagFingerprint value to remove (must not be EMPTY).
Returns
true if a single instance of tag was removed from the bucket; false if no matching tag remained (or another thread removed the last matching instance before this call could succeed).

Definition at line 1149 of file CuckooFilter.cuh.

1149 {
1150 Bucket& bucket = d_buckets[bucketIdx];
1151
1152 const uint32_t startSlot = tag & (bucketSize - 1);
1153 const size_t startWord = startSlot / Bucket::tagsPerWord;
1154
1155 using WordType = typename Bucket::WordType;
1156
1157 for (size_t i = 0; i < Bucket::wordCount; ++i) {
1158 const size_t currIdx = (startWord + i) & (Bucket::wordCount - 1);
1159
1160 while (true) {
1161 auto expected = bucket.packedTags[currIdx].load(cuda::memory_order_relaxed);
1162
1163 WordType matchMask = detail::getZeroMask<TagType, WordType>(
1165 );
1166
1167 if (matchMask == 0) {
1168 // No matching tags in this word
1169 break;
1170 }
1171
1172 // Find position of first matching tag
1173 int bitPos;
1174 if constexpr (sizeof(WordType) == 4) {
1175 bitPos = __ffs(static_cast<int>(matchMask)) - 1;
1176 } else {
1177 bitPos = __ffsll(static_cast<long long>(matchMask)) - 1;
1178 }
1179 size_t tagIdx = bitPos / bitsPerTag;
1180
1181 auto desired = bucket.replaceTag(expected, tagIdx, EMPTY);
1182
1183#ifdef CUCKOO_FILTER_COUNT_DELETE_CAS
1184 d_deleteCasAttempts->fetch_add(1, cuda::memory_order_relaxed);
1185#endif
1186 bool casSuccess = bucket.packedTags[currIdx].compare_exchange_weak(
1187 expected, desired, cuda::memory_order_relaxed, cuda::memory_order_relaxed
1188 );
1189#ifdef CUCKOO_FILTER_COUNT_DELETE_CAS
1190 if (!casSuccess) {
1191 d_deleteCasFailures->fetch_add(1, cuda::memory_order_relaxed);
1192 }
1193#endif
1194 if (casSuccess) {
1195 return true;
1196 }
1197 // CAS failed, retry with updated expected value
1198 }
1199 }
1200
1201 return false;
1202 }
Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ bitsPerTag

template<typename Config >
constexpr size_t cuckoogpu::Filter< Config >::bitsPerTag = Config::bitsPerTag
staticconstexpr

Definition at line 143 of file CuckooFilter.cuh.

◆ blockSize

template<typename Config >
constexpr size_t cuckoogpu::Filter< Config >::blockSize = Config::blockSize
staticconstexpr

Definition at line 152 of file CuckooFilter.cuh.

◆ bucketSize

template<typename Config >
constexpr size_t cuckoogpu::Filter< Config >::bucketSize = Config::bucketSize
staticconstexpr

Definition at line 149 of file CuckooFilter.cuh.

◆ d_buckets

template<typename Config >
Bucket* cuckoogpu::Filter< Config >::d_buckets

Pointer to the device memory for the buckets.

Definition at line 345 of file CuckooFilter.cuh.

◆ d_deleteCasAttempts

template<typename Config >
cuda::std::atomic<size_t>* cuckoogpu::Filter< Config >::d_deleteCasAttempts {}

Pointer to device memory for the delete CAS attempt counter.

Definition at line 351 of file CuckooFilter.cuh.

351{};

◆ d_deleteCasFailures

template<typename Config >
cuda::std::atomic<size_t>* cuckoogpu::Filter< Config >::d_deleteCasFailures {}

Pointer to device memory for the failed delete CAS counter.

Definition at line 353 of file CuckooFilter.cuh.

353{};

◆ d_numOccupied

template<typename Config >
cuda::std::atomic<size_t>* cuckoogpu::Filter< Config >::d_numOccupied {}

Pointer to the device memory for the occupancy counter.

Definition at line 347 of file CuckooFilter.cuh.

347{};

◆ EMPTY

template<typename Config >
constexpr TagType cuckoogpu::Filter< Config >::EMPTY = 0
staticconstexpr

Definition at line 210 of file CuckooFilter.cuh.

◆ fpMask

template<typename Config >
constexpr size_t cuckoogpu::Filter< Config >::fpMask = (1ULL << bitsPerTag) - 1
staticconstexpr

Definition at line 211 of file CuckooFilter.cuh.

◆ h_numOccupied

template<typename Config >
size_t cuckoogpu::Filter< Config >::h_numOccupied = 0

Number of occupied buckets in the filter.

Definition at line 360 of file CuckooFilter.cuh.

◆ maxEvictions

template<typename Config >
constexpr size_t cuckoogpu::Filter< Config >::maxEvictions = Config::maxEvictions
staticconstexpr

Definition at line 151 of file CuckooFilter.cuh.

◆ numBuckets

template<typename Config >
size_t cuckoogpu::Filter< Config >::numBuckets

Number of buckets in the filter.

Definition at line 344 of file CuckooFilter.cuh.

◆ tagEntryBytes

template<typename Config >
constexpr size_t cuckoogpu::Filter< Config >::tagEntryBytes = sizeof(TagType)
staticconstexpr

Definition at line 148 of file CuckooFilter.cuh.


The documentation for this struct was generated from the following file: