Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions cudax/include/cuda/experimental/__cuco/fixed_capacity_set.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,54 @@ public:
__impl_->insert_async(__stream, __first, __last, ref());
}

//! @brief Inserts keys whose stencil satisfies `__pred` and returns the number of new keys inserted.
//!
//! The key `__first[i]` is inserted when `__pred(__stencil[i])` is true. Duplicate keys and keys
//! that cannot fit in the set do not contribute to the count.
//! @pre No selected input key equals the empty sentinel.
//! @note `__pred` may be invoked more than once for the same stencil element.
//! @note Synchronizes the supplied stream for nonempty input. For asynchronous execution use `insert_if_async`.
//! @throws cuda_error if the operation or stream synchronization fails
//! @tparam _InputIt Device-accessible random-access iterator with compatible key values
//! @tparam _StencilIt Device-accessible random-access iterator whose values are convertible to the
//! predicate's argument type
//! @tparam _Predicate Unary callable returning a value convertible to `bool`
//! @param[in] __stream Stream used for insertion
//! @param[in] __first Beginning of the input range
//! @param[in] __last End of the input range
//! @param[in] __stencil Beginning of the stencil range
//! @param[in] __pred Predicate applied to each stencil value to select keys for insertion
//! @return Number of successfully inserted keys
template <class _InputIt, class _StencilIt, class _Predicate>
_CCCL_HOST_API size_type
insert_if(::cuda::stream_ref __stream, _InputIt __first, _InputIt __last, _StencilIt __stencil, _Predicate __pred)
{
return __impl_->insert_if(__stream, __first, __last, __stencil, __pred, ref());
}

//! @brief Asynchronously inserts keys whose stencil satisfies `__pred` without returning an insertion count.
//!
//! The key `__first[i]` is inserted when `__pred(__stencil[i])` is true. Duplicate keys and keys
//! that cannot fit in the set are ignored.
//! @pre No selected input key equals the empty sentinel.
//! @note `__pred` may be invoked more than once for the same stencil element.
//! @throws cuda_error if insertion fails to launch
//! @tparam _InputIt Device-accessible random-access iterator with compatible key values
//! @tparam _StencilIt Device-accessible random-access iterator whose values are convertible to the
//! predicate's argument type
//! @tparam _Predicate Unary callable returning a value convertible to `bool`
//! @param[in] __stream Stream used for insertion
//! @param[in] __first Beginning of the input range
//! @param[in] __last End of the input range
//! @param[in] __stencil Beginning of the stencil range
//! @param[in] __pred Predicate applied to each stencil value to select keys for insertion
template <class _InputIt, class _StencilIt, class _Predicate>
_CCCL_HOST_API void insert_if_async(
::cuda::stream_ref __stream, _InputIt __first, _InputIt __last, _StencilIt __stencil, _Predicate __pred)
{
__impl_->insert_if_async(__stream, __first, __last, __stencil, __pred, ref());
}

//! @brief Writes whether each query key is present.
//!
//! @pre No query key equals the empty sentinel.
Expand Down
21 changes: 21 additions & 0 deletions cudax/test/cuco/fixed_capacity_set/test_insert_and_contains.cu
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ struct duplicate_key
}
};

struct is_negative
{
[[nodiscard]] _CCCL_DEVICE_API bool operator()(int value) const noexcept
{
return value < 0;
}
};

C2H_TEST("fixed_capacity_set insert and contains", "[container]", key_types, cg_sizes, bucket_sizes, probing_kinds)
{
using key_type = c2h::get<0, TestType>;
Expand Down Expand Up @@ -92,6 +100,19 @@ C2H_TEST("fixed_capacity_set insert and contains", "[container]", key_types, cg_
set.contains(context.stream, first, first + num_queries, found.begin());
REQUIRE(context.matches(found.data(), num_queries, num_keys));

// The stencil is negative only for the first half while every key is nonnegative, so the stencil, not the key,
// selects the first half.
const auto stencil = cuda::counting_iterator<int>{-num_keys / 2};
set.clear(context.stream);
REQUIRE(set.insert_if(context.stream, first, first + num_keys, stencil, is_negative{}) == num_keys / 2);
set.contains(context.stream, first, first + num_queries, found.begin());
REQUIRE(context.matches(found.data(), num_queries, num_keys / 2));

set.clear(context.stream);
set.insert_if_async(context.stream, first, first + num_keys, stencil, is_negative{});
set.contains(context.stream, first, first + num_queries, found.begin());
REQUIRE(context.matches(found.data(), num_queries, num_keys / 2));

set_type full{context.stream, context.mr, cuda::std::size_t{13}, cudax::cuco::empty_key{static_cast<key_type>(-1)}};
const int capacity = static_cast<int>(full.capacity());
REQUIRE(full.insert(context.stream, first, first + capacity) == full.capacity());
Expand Down
Loading