cub::DeviceBatchedTopK#
-
struct DeviceBatchedTopK#
DeviceBatchedTopK provides device-wide, parallel operations for finding the largest (or smallest) K items from many segments of unordered data items residing within device-accessible memory.
Added in version 3.5.0: First appears in CUDA Toolkit 13.5.
Overview#
Given a batch of segments,
DeviceBatchedTopKfinds, independently for each segment, the K largest (or smallest) items.Argument annotation framework#
The parameters
segment_sizes,k, andnum_segmentscan be passed as annotated arguments fromcuda::args. An annotation tells the algorithm everything you know about a parameter: where its value comes from and how tightly it is bounded. The more you can tell the algorithm, and the more precisely (a compile-time constant rather than a runtime value, a tight bound rather than a loose one), the more it can specialize. For that reason, we encourage you to provide as much information as you have.Where the value comes from. The first three forms describe a single value shared by every segment, the last describes a distinct value per segment:
cuda::args::constant<N>{}for a value fixed at compile time.Nis both the value and its bound.cuda::args::immediate{value}for a single value known on the host at the call.cuda::args::deferred{iterator}for a single value read in stream order through a pointer or iterator, for example one produced on the device by a preceding launch.cuda::args::deferred_sequence{iterator}for a distinct value per segment, also read in stream order.
A plain integral value works too and is taken as a uniform
immediate(no extra bounds). A pointer or iterator, by contrast, must be wrapped explicitly indeferred(single value) ordeferred_sequence(per segment). Passing a raw pointer or iterator is rejected at compile time, because it would otherwise be misread as a single value rather than a sequence.How it is bounded. A bound lets the algorithm reason about a value it does not know exactly:
A compile-time bound,
cuda::args::bounds<lo, hi>(), may accompanyimmediate,deferred, ordeferred_sequence(aconstantis already its own bound). The kernel specializes on this range and uses it to size temporary storage (see Choosing argument bounds), so prefer the tightest range you can prove.A runtime bound,
cuda::args::bounds(lo, hi), may accompanydeferredanddeferred_sequencewhen the range is only known at runtime. When combined with a compile-time bound, the runtime bound must be at least as narrow, lying within the compile-time range and only tightening it further.
Which form each parameter accepts.
segment_sizesandkaccept all four forms.num_segmentsmust be a single value (constant,immediate, or a plain integral), never a per-segment sequence.segment_sizesmust also carry a small compile-time upper bound (aconstant<N>orcuda::args::bounds<lo, hi>()), and tight bounds on every parameter are encouraged.// segment_sizes (k is analogous): cuda::args::constant<256>{}; // fixed at compile time cuda::args::immediate{n, cuda::args::bounds<1, 1024>()}; // host value, at most 1024 cuda::args::deferred_sequence{d_sizes, cuda::args::bounds<1, 1024>()}; // per-segment, each at most 1024 // a uniform segment size produced on the device, capped at compile time and narrowed at runtime: cuda::args::deferred{d_size, cuda::args::bounds<1, 1024>(), cuda::args::bounds(1, runtime_max)};
Choosing argument bounds#
Prefer sharp (tight) upper bounds, especially for the segment size. The statically-known maximum segment size (the upper bound of the
segment_sizesannotation) does more than select the kernel: it can also drive how much temporary storage the algorithm requests. As a rough intuition, the temporary allocation may grow with the number of segments times some factor of the maximum segment size, so an unnecessarily loose upper bound can inflate temporary storage even when the actual segments are much smaller. The precise relationship is intentionally left unspecified and may change across releases (temporary-storage handling is an implementation detail). Treat this purely as guidance for choosing bounds rather than as a guarantee.Current constraints (initial API surface)#
This is an initial, intentionally restricted API surface. The following constraints are enforced at compile time (a
static_assertfires if violated):Small segments only. Every segment must be processable by a single thread block (one worker per segment). The statically-known maximum segment size (the upper bound of the
segment_sizesannotation) must be small enough that such a block fits within the shared-memory limit. Both uniform (fixed) and variable segment sizes are supported as long as this maximum is honored.Uniform number of segments.
num_segmentsmust be a single value, never a per-segment sequence.Explicit opt-out required for the output guarantees. The deterministic, stable-sorted default contract described in Determinism, tie-breaking, and output ordering below (and in Top-K: Determinism, Tie-Breaking, and Output Ordering) is not yet implemented. The caller must currently request non-deterministic, unsorted output explicitly by passing
cuda::execution::require(cuda::execution::determinism::not_guaranteed, cuda::execution::tie_break::unspecified, cuda::execution::output_ordering::unsorted)in the environment (determinismandtie_breakmust always be specified together).
Determinism, tie-breaking, and output ordering#
Like
cub::DeviceTopK, the result ofDeviceBatchedTopKis governed by two orthogonal execution requirements: which items are selected per segment (cuda::execution::determinism, optionally refined bycuda::execution::tie_break) and the order in which they are written (cuda::execution::output_ordering). When the caller does not opt out, the committed default is the most reproducible behavior: deterministic results (cuda::execution::determinism::gpu_to_gpu), ties resolved toward the smaller (lower) source index (cuda::execution::tie_break::prefer_smaller_index), and stable-sorted output (cuda::execution::output_ordering::stable_sorted). Callers opt out of these guarantees to obtain faster implementations.determinismandtie_breakmust always be specified together, or both omitted to take the default. A specifiedtie_breakofprefer_smaller_indexorprefer_larger_indexrequiresdeterminism::gpu_to_gpu.See Top-K: Determinism, Tie-Breaking, and Output Ordering for the full requirement model, worked examples, and guidance on choosing requirements.
Usage Considerations#
Dynamic parallelism. DeviceBatchedTopK methods can be called within kernel code on devices in which CUDA dynamic parallelism is supported.
Note
Current support. This release only implements the fully opted-out configuration, which must be requested explicitly:
cuda::execution::require(cuda::execution::determinism::not_guaranteed, cuda::execution::tie_break::unspecified, cuda::execution::output_ordering::unsorted). Any other combination (including an empty, no-requirement environment) is rejected at compile time. In this configuration the per-segment output is unordered and may be non-deterministic: if multiple items tie at the K-th position, the subset of tied elements returned is not uniquely defined and may vary between runs.Public Static Functions
-
template<typename KeyInputIteratorItT, typename KeyOutputIteratorItT, typename SegmentSizeParameterT, typename KParameterT, typename NumSegmentsParameterT, typename EnvT = ::cuda::std::execution::env<>>
static inline cudaError_t MaxKeys( - void *d_temp_storage,
- size_t &temp_storage_bytes,
- KeyInputIteratorItT d_keys_in,
- KeyOutputIteratorItT d_keys_out,
- SegmentSizeParameterT segment_sizes,
- KParameterT k,
- NumSegmentsParameterT num_segments,
- const EnvT &env = {}
Overview#
Finds, for each segment, the largest K keys from an unordered input sequence of keys.
Temporary storage for this operation. If
d_temp_storageisnullptr, the required size is written totemp_storage_byteswithout dereferencing iterators or launching kernels. Otherwise,d_temp_storagemust point to a device-accessible allocation of at leasttemp_storage_bytesbytes. No special alignment is required. See Two-Phase API (explicit temporary storage management) for usage guidance.
A Simple Example#
constexpr int num_segments = 2; constexpr int segment_size = 8; constexpr int k = 3; auto keys_in = thrust::device_vector<int>{5, -3, 1, 7, 8, 2, 4, 6, /**/ 0, 9, 3, 2, 1, 8, 7, 4}; auto keys_out = thrust::device_vector<int>(num_segments * k, thrust::no_init); // Per-segment iterators: d_keys_in[s] yields an iterator to the start of segment s. auto d_keys_in = cuda::make_strided_iterator(cuda::make_counting_iterator(thrust::raw_pointer_cast(keys_in.data())), segment_size); auto d_keys_out = cuda::make_strided_iterator(cuda::make_counting_iterator(thrust::raw_pointer_cast(keys_out.data())), k); // Argument annotations: a small, compile-time segment size and k, plus the runtime segment count and item-count // bound. constexpr auto segment_sizes = cuda::args::constant<segment_size>{}; constexpr auto k_arg = cuda::args::constant<k>{}; auto num_segs = cuda::args::immediate{cuda::std::int64_t{num_segments}}; // Top-k output is unordered and may be non-deterministic; this must be acknowledged via the environment. auto env = cuda::std::execution::env{cuda::execution::require( cuda::execution::determinism::not_guaranteed, cuda::execution::tie_break::unspecified, cuda::execution::output_ordering::unsorted)}; // Query temporary storage requirements size_t temp_storage_bytes = 0; auto error = cub::DeviceBatchedTopK::MaxKeys( nullptr, temp_storage_bytes, d_keys_in, d_keys_out, segment_sizes, k_arg, num_segs, env); // Allocate temporary storage and run thrust::device_vector<char> temp_storage(temp_storage_bytes, thrust::no_init); error = cub::DeviceBatchedTopK::MaxKeys( thrust::raw_pointer_cast(temp_storage.data()), temp_storage_bytes, d_keys_in, d_keys_out, segment_sizes, k_arg, num_segs, env); // Each segment's k largest keys are written to keys_out in unspecified order. The result set is fixed, // shown here sorted per segment: auto expected_result_set = thrust::device_vector<int>{8, 7, 6, /* segment 0 */ 9, 8, 7 /* segment 1 */};
Note
The behavior is undefined if an output range overlaps another output range or any input range. Input ranges may overlap one another.
- Template Parameters:
KeyInputIteratorItT – [inferred] Random-access input iterator over per-segment key-input iterators (may be a simple pointer type)
KeyOutputIteratorItT – [inferred] Random-access input iterator over per-segment key-output iterators (may be a simple pointer type)
SegmentSizeParameterT – [inferred] Type of the
segment_sizesargumentKParameterT – [inferred] Type of the
kargumentNumSegmentsParameterT – [inferred] Type of the
num_segmentsargumentEnvT – [inferred] Execution environment type. Default is
cuda::std::execution::env<>.
- Parameters:
d_temp_storage – [in] Device-accessible allocation of temporary storage. When
nullptr, the required allocation size is written totemp_storage_bytesand no work is done.temp_storage_bytes – [inout] Reference to size in bytes of
d_temp_storageallocationd_keys_in – [in] Iterator such that
d_keys_in[i]yields a random-access iterator to the keys of segmentid_keys_out – [out] Iterator such that
d_keys_out[i]yields a random-access output iterator for the top-k keys of segmentisegment_sizes – [in] Annotated argument providing the per-segment sizes (e.g.
cuda::args::constant<N>for a uniform size, orcuda::args::deferred_sequence{...}for variable sizes). Must carry a small compile-time maximum. Prefer a sharp (tight) upper bound, since a looser bound may increase temporary-storage usage (see the Choosing argument bounds section).k – [in] The number of selected items per segment, given as a
cuda::argsannotation or a plain integral value.num_segments – [in] The (uniform) number of segments, given as a
cuda::argsannotation or a plain integral value.env – [in]
[optional] Execution environment. Must require determinism::not_guaranteed, tie_break::unspecified, and output_ordering::unsorted.
-
template<typename KeyInputIteratorItT, typename KeyOutputIteratorItT, typename SegmentSizeParameterT, typename KParameterT, typename NumSegmentsParameterT, typename EnvT = ::cuda::std::execution::env<>>
static inline cudaError_t MaxKeys( - KeyInputIteratorItT d_keys_in,
- KeyOutputIteratorItT d_keys_out,
- SegmentSizeParameterT segment_sizes,
- KParameterT k,
- NumSegmentsParameterT num_segments,
- const EnvT &env = {}
Finds, for each segment, the largest K keys from an unordered input sequence of keys.
This is an environment-based API that allocates and manages the required temporary storage internally using the memory resource queried from the environment.
Snippet#
constexpr int num_segments = 2; constexpr int segment_size = 8; constexpr int k = 3; auto keys_in = thrust::device_vector<int>{5, -3, 1, 7, 8, 2, 4, 6, /**/ 0, 9, 3, 2, 1, 8, 7, 4}; auto keys_out = thrust::device_vector<int>(num_segments * k, thrust::no_init); auto d_keys_in = cuda::make_strided_iterator(cuda::make_counting_iterator(thrust::raw_pointer_cast(keys_in.data())), segment_size); auto d_keys_out = cuda::make_strided_iterator(cuda::make_counting_iterator(thrust::raw_pointer_cast(keys_out.data())), k); cuda::stream stream{cuda::devices[0]}; auto env = cuda::std::execution::env{ cuda::execution::require(cuda::execution::determinism::not_guaranteed, cuda::execution::tie_break::unspecified, cuda::execution::output_ordering::unsorted), cuda::stream_ref{stream}}; // The env-based overload allocates and frees the temporary storage internally. auto error = cub::DeviceBatchedTopK::MaxKeys( d_keys_in, d_keys_out, cuda::args::constant<segment_size>{}, cuda::args::constant<k>{}, cuda::args::immediate{cuda::std::int64_t{num_segments}}, env); // Each segment's k largest keys are written to keys_out in unspecified order. The result set is fixed, // shown here sorted per segment: auto expected_result_set = thrust::device_vector<int>{8, 7, 6, /* segment 0 */ 9, 8, 7 /* segment 1 */};
Note
The behavior is undefined if an output range overlaps another output range or any input range. Input ranges may overlap one another.
- Template Parameters:
KeyInputIteratorItT – [inferred] Random-access input iterator over per-segment key-input iterators (may be a simple pointer type)
KeyOutputIteratorItT – [inferred] Random-access input iterator over per-segment key-output iterators (may be a simple pointer type)
SegmentSizeParameterT – [inferred] Type of the
segment_sizesargumentKParameterT – [inferred] Type of the
kargumentNumSegmentsParameterT – [inferred] Type of the
num_segmentsargumentEnvT – [inferred] Execution environment type. Default is
cuda::std::execution::env<>.
- Parameters:
d_keys_in – [in] Iterator such that
d_keys_in[i]yields a random-access iterator to the keys of segmentid_keys_out – [out] Iterator such that
d_keys_out[i]yields a random-access output iterator for the top-k keys of segmentisegment_sizes – [in] Annotated argument providing the per-segment sizes (e.g.
cuda::args::constant<N>for a uniform size, orcuda::args::deferred_sequence{...}for variable sizes). Must carry a small compile-time maximum. Prefer a sharp (tight) upper bound, since a looser bound may increase temporary-storage usage (see the Choosing argument bounds section).k – [in] The number of selected items per segment, given as a
cuda::argsannotation or a plain integral value.num_segments – [in] The (uniform) number of segments, given as a
cuda::argsannotation or a plain integral value.env – [in]
[optional] Execution environment. Must require determinism::not_guaranteed, tie_break::unspecified, and output_ordering::unsorted.
-
template<typename KeyInputIteratorItT, typename KeyOutputIteratorItT, typename SegmentSizeParameterT, typename KParameterT, typename NumSegmentsParameterT, typename EnvT = ::cuda::std::execution::env<>>
static inline cudaError_t MinKeys( - void *d_temp_storage,
- size_t &temp_storage_bytes,
- KeyInputIteratorItT d_keys_in,
- KeyOutputIteratorItT d_keys_out,
- SegmentSizeParameterT segment_sizes,
- KParameterT k,
- NumSegmentsParameterT num_segments,
- const EnvT &env = {}
Finds, for each segment, the smallest K keys from an unordered input sequence of keys.
Temporary storage for this operation. If
d_temp_storageisnullptr, the required size is written totemp_storage_byteswithout dereferencing iterators or launching kernels. Otherwise,d_temp_storagemust point to a device-accessible allocation of at leasttemp_storage_bytesbytes. No special alignment is required. See Two-Phase API (explicit temporary storage management) for usage guidance.
A Simple Example#
constexpr int num_segments = 2; constexpr int segment_size = 8; constexpr int k = 3; auto keys_in = thrust::device_vector<int>{5, -3, 1, 7, 8, 2, 4, 6, /**/ 0, 9, 3, 2, 1, 8, 7, 4}; auto keys_out = thrust::device_vector<int>(num_segments * k, thrust::no_init); auto d_keys_in = cuda::make_strided_iterator(cuda::make_counting_iterator(thrust::raw_pointer_cast(keys_in.data())), segment_size); auto d_keys_out = cuda::make_strided_iterator(cuda::make_counting_iterator(thrust::raw_pointer_cast(keys_out.data())), k); constexpr auto segment_sizes = cuda::args::constant<segment_size>{}; constexpr auto k_arg = cuda::args::constant<k>{}; auto num_segs = cuda::args::immediate{cuda::std::int64_t{num_segments}}; auto env = cuda::std::execution::env{cuda::execution::require( cuda::execution::determinism::not_guaranteed, cuda::execution::tie_break::unspecified, cuda::execution::output_ordering::unsorted)}; size_t temp_storage_bytes = 0; auto error = cub::DeviceBatchedTopK::MinKeys( nullptr, temp_storage_bytes, d_keys_in, d_keys_out, segment_sizes, k_arg, num_segs, env); thrust::device_vector<char> temp_storage(temp_storage_bytes, thrust::no_init); error = cub::DeviceBatchedTopK::MinKeys( thrust::raw_pointer_cast(temp_storage.data()), temp_storage_bytes, d_keys_in, d_keys_out, segment_sizes, k_arg, num_segs, env); // Each segment's k smallest keys are written to keys_out in unspecified order. The result set is fixed, // shown here sorted per segment: auto expected_result_set = thrust::device_vector<int>{-3, 1, 2, /* segment 0 */ 0, 1, 2 /* segment 1 */};
Note
The behavior is undefined if an output range overlaps another output range or any input range. Input ranges may overlap one another.
- Template Parameters:
KeyInputIteratorItT – [inferred] Random-access input iterator over per-segment key-input iterators (may be a simple pointer type)
KeyOutputIteratorItT – [inferred] Random-access input iterator over per-segment key-output iterators (may be a simple pointer type)
SegmentSizeParameterT – [inferred] Type of the
segment_sizesargumentKParameterT – [inferred] Type of the
kargumentNumSegmentsParameterT – [inferred] Type of the
num_segmentsargumentEnvT – [inferred] Execution environment type. Default is
cuda::std::execution::env<>.
- Parameters:
d_temp_storage – [in] Device-accessible allocation of temporary storage. When
nullptr, the required allocation size is written totemp_storage_bytesand no work is done.temp_storage_bytes – [inout] Reference to size in bytes of
d_temp_storageallocationd_keys_in – [in] Iterator such that
d_keys_in[i]yields a random-access iterator to the keys of segmentid_keys_out – [out] Iterator such that
d_keys_out[i]yields a random-access output iterator for the top-k keys of segmentisegment_sizes – [in] Annotated argument providing the per-segment sizes (e.g.
cuda::args::constant<N>for a uniform size, orcuda::args::deferred_sequence{...}for variable sizes). Must carry a small compile-time maximum. Prefer a sharp (tight) upper bound, since a looser bound may increase temporary-storage usage (see the Choosing argument bounds section).k – [in] The number of selected items per segment, given as a
cuda::argsannotation or a plain integral value.num_segments – [in] The (uniform) number of segments, given as a
cuda::argsannotation or a plain integral value.env – [in]
[optional] Execution environment. Must require determinism::not_guaranteed, tie_break::unspecified, and output_ordering::unsorted.
-
template<typename KeyInputIteratorItT, typename KeyOutputIteratorItT, typename SegmentSizeParameterT, typename KParameterT, typename NumSegmentsParameterT, typename EnvT = ::cuda::std::execution::env<>>
static inline cudaError_t MinKeys( - KeyInputIteratorItT d_keys_in,
- KeyOutputIteratorItT d_keys_out,
- SegmentSizeParameterT segment_sizes,
- KParameterT k,
- NumSegmentsParameterT num_segments,
- const EnvT &env = {}
Finds, for each segment, the smallest K keys from an unordered input sequence of keys. Environment-based overload that allocates temporary storage internally.
Snippet#
constexpr int num_segments = 2; constexpr int segment_size = 8; constexpr int k = 3; auto keys_in = thrust::device_vector<int>{5, -3, 1, 7, 8, 2, 4, 6, /**/ 0, 9, 3, 2, 1, 8, 7, 4}; auto keys_out = thrust::device_vector<int>(num_segments * k, thrust::no_init); auto d_keys_in = cuda::make_strided_iterator(cuda::make_counting_iterator(thrust::raw_pointer_cast(keys_in.data())), segment_size); auto d_keys_out = cuda::make_strided_iterator(cuda::make_counting_iterator(thrust::raw_pointer_cast(keys_out.data())), k); cuda::stream stream{cuda::devices[0]}; auto env = cuda::std::execution::env{ cuda::execution::require(cuda::execution::determinism::not_guaranteed, cuda::execution::tie_break::unspecified, cuda::execution::output_ordering::unsorted), cuda::stream_ref{stream}}; auto error = cub::DeviceBatchedTopK::MinKeys( d_keys_in, d_keys_out, cuda::args::constant<segment_size>{}, cuda::args::constant<k>{}, cuda::args::immediate{cuda::std::int64_t{num_segments}}, env); // Each segment's k smallest keys are written to keys_out in unspecified order. The result set is fixed, // shown here sorted per segment: auto expected_result_set = thrust::device_vector<int>{-3, 1, 2, /* segment 0 */ 0, 1, 2 /* segment 1 */};
Note
The behavior is undefined if an output range overlaps another output range or any input range. Input ranges may overlap one another.
- Template Parameters:
KeyInputIteratorItT – [inferred] Random-access input iterator over per-segment key-input iterators (may be a simple pointer type)
KeyOutputIteratorItT – [inferred] Random-access input iterator over per-segment key-output iterators (may be a simple pointer type)
SegmentSizeParameterT – [inferred] Type of the
segment_sizesargumentKParameterT – [inferred] Type of the
kargumentNumSegmentsParameterT – [inferred] Type of the
num_segmentsargumentEnvT – [inferred] Execution environment type. Default is
cuda::std::execution::env<>.
- Parameters:
d_keys_in – [in] Iterator such that
d_keys_in[i]yields a random-access iterator to the keys of segmentid_keys_out – [out] Iterator such that
d_keys_out[i]yields a random-access output iterator for the top-k keys of segmentisegment_sizes – [in] Annotated argument providing the per-segment sizes (e.g.
cuda::args::constant<N>for a uniform size, orcuda::args::deferred_sequence{...}for variable sizes). Must carry a small compile-time maximum. Prefer a sharp (tight) upper bound, since a looser bound may increase temporary-storage usage (see the Choosing argument bounds section).k – [in] The number of selected items per segment, given as a
cuda::argsannotation or a plain integral value.num_segments – [in] The (uniform) number of segments, given as a
cuda::argsannotation or a plain integral value.env – [in]
[optional] Execution environment. Must require determinism::not_guaranteed, tie_break::unspecified, and output_ordering::unsorted.
-
template<typename KeyInputIteratorItT, typename KeyOutputIteratorItT, typename ValueInputIteratorItT, typename ValueOutputIteratorItT, typename SegmentSizeParameterT, typename KParameterT, typename NumSegmentsParameterT, typename EnvT = ::cuda::std::execution::env<>>
static inline cudaError_t MaxPairs( - void *d_temp_storage,
- size_t &temp_storage_bytes,
- KeyInputIteratorItT d_keys_in,
- KeyOutputIteratorItT d_keys_out,
- ValueInputIteratorItT d_values_in,
- ValueOutputIteratorItT d_values_out,
- SegmentSizeParameterT segment_sizes,
- KParameterT k,
- NumSegmentsParameterT num_segments,
- const EnvT &env = {}
Overview#
Finds, for each segment, the largest K keys and their corresponding values from an unordered input sequence of key-value pairs.
Temporary storage for this operation. If
d_temp_storageisnullptr, the required size is written totemp_storage_byteswithout dereferencing iterators or launching kernels. Otherwise,d_temp_storagemust point to a device-accessible allocation of at leasttemp_storage_bytesbytes. No special alignment is required. See Two-Phase API (explicit temporary storage management) for usage guidance.
A Simple Example#
constexpr int num_segments = 2; constexpr int segment_size = 8; constexpr int k = 3; auto keys_in = thrust::device_vector<int>{5, -3, 1, 7, 8, 2, 4, 6, /**/ 0, 9, 3, 2, 1, 8, 7, 4}; auto keys_out = thrust::device_vector<int>(num_segments * k, thrust::no_init); auto values_out = thrust::device_vector<int>(num_segments * k, thrust::no_init); auto d_keys_in = cuda::make_strided_iterator(cuda::make_counting_iterator(thrust::raw_pointer_cast(keys_in.data())), segment_size); auto d_keys_out = cuda::make_strided_iterator(cuda::make_counting_iterator(thrust::raw_pointer_cast(keys_out.data())), k); // Input values are the per-segment item indices [0, segment_size). auto d_values_in = cuda::make_constant_iterator(cuda::make_counting_iterator(0)); auto d_values_out = cuda::make_strided_iterator(cuda::make_counting_iterator(thrust::raw_pointer_cast(values_out.data())), k); constexpr auto segment_sizes = cuda::args::constant<segment_size>{}; constexpr auto k_arg = cuda::args::constant<k>{}; auto num_segs = cuda::args::immediate{cuda::std::int64_t{num_segments}}; auto env = cuda::std::execution::env{cuda::execution::require( cuda::execution::determinism::not_guaranteed, cuda::execution::tie_break::unspecified, cuda::execution::output_ordering::unsorted)}; size_t temp_storage_bytes = 0; auto error = cub::DeviceBatchedTopK::MaxPairs( nullptr, temp_storage_bytes, d_keys_in, d_keys_out, d_values_in, d_values_out, segment_sizes, k_arg, num_segs, env); thrust::device_vector<char> temp_storage(temp_storage_bytes, thrust::no_init); error = cub::DeviceBatchedTopK::MaxPairs( thrust::raw_pointer_cast(temp_storage.data()), temp_storage_bytes, d_keys_in, d_keys_out, d_values_in, d_values_out, segment_sizes, k_arg, num_segs, env); // keys_out holds each segment's k largest keys. The key set is fixed (shown here sorted per segment). For // keys that tie, which equal element's value is returned is unspecified. auto expected_result_set = thrust::device_vector<int>{8, 7, 6, /* segment 0 */ 9, 8, 7 /* segment 1 */};
Note
The behavior is undefined if an output range overlaps another output range or any input range. Input ranges may overlap one another.
- Template Parameters:
KeyInputIteratorItT – [inferred] Random-access input iterator over per-segment key-input iterators (may be a simple pointer type)
KeyOutputIteratorItT – [inferred] Random-access input iterator over per-segment key-output iterators (may be a simple pointer type)
ValueInputIteratorItT – [inferred] Random-access input iterator over per-segment value-input iterators (may be a simple pointer type)
ValueOutputIteratorItT – [inferred] Random-access input iterator over per-segment value-output iterators (may be a simple pointer type)
SegmentSizeParameterT – [inferred] Type of the
segment_sizesargumentKParameterT – [inferred] Type of the
kargumentNumSegmentsParameterT – [inferred] Type of the
num_segmentsargumentEnvT – [inferred] Execution environment type. Default is
cuda::std::execution::env<>.
- Parameters:
d_temp_storage – [in] Device-accessible allocation of temporary storage. When
nullptr, the required allocation size is written totemp_storage_bytesand no work is done.temp_storage_bytes – [inout] Reference to size in bytes of
d_temp_storageallocationd_keys_in – [in] Iterator such that
d_keys_in[i]yields a random-access iterator to the keys of segmentid_keys_out – [out] Iterator such that
d_keys_out[i]yields a random-access output iterator for the top-k keys of segmentid_values_in – [in] Iterator such that
d_values_in[i]yields a random-access iterator to the values of segmentid_values_out – [out] Iterator such that
d_values_out[i]yields a random-access output iterator for the values corresponding to the top-k keys of segmentisegment_sizes – [in] Annotated argument providing the per-segment sizes (e.g.
cuda::args::constant<N>for a uniform size, orcuda::args::deferred_sequence{...}for variable sizes). Must carry a small compile-time maximum. Prefer a sharp (tight) upper bound, since a looser bound may increase temporary-storage usage (see the Choosing argument bounds section).k – [in] The number of selected items per segment, given as a
cuda::argsannotation or a plain integral value.num_segments – [in] The (uniform) number of segments, given as a
cuda::argsannotation or a plain integral value.env – [in]
[optional] Execution environment. Must require determinism::not_guaranteed, tie_break::unspecified, and output_ordering::unsorted.
-
template<typename KeyInputIteratorItT, typename KeyOutputIteratorItT, typename ValueInputIteratorItT, typename ValueOutputIteratorItT, typename SegmentSizeParameterT, typename KParameterT, typename NumSegmentsParameterT, typename EnvT = ::cuda::std::execution::env<>>
static inline cudaError_t MaxPairs( - KeyInputIteratorItT d_keys_in,
- KeyOutputIteratorItT d_keys_out,
- ValueInputIteratorItT d_values_in,
- ValueOutputIteratorItT d_values_out,
- SegmentSizeParameterT segment_sizes,
- KParameterT k,
- NumSegmentsParameterT num_segments,
- const EnvT &env = {}
Finds, for each segment, the largest K keys and their corresponding values. Environment-based overload that allocates temporary storage internally.
Snippet#
constexpr int num_segments = 2; constexpr int segment_size = 8; constexpr int k = 3; auto keys_in = thrust::device_vector<int>{5, -3, 1, 7, 8, 2, 4, 6, /**/ 0, 9, 3, 2, 1, 8, 7, 4}; auto keys_out = thrust::device_vector<int>(num_segments * k, thrust::no_init); auto values_out = thrust::device_vector<int>(num_segments * k, thrust::no_init); auto d_keys_in = cuda::make_strided_iterator(cuda::make_counting_iterator(thrust::raw_pointer_cast(keys_in.data())), segment_size); auto d_keys_out = cuda::make_strided_iterator(cuda::make_counting_iterator(thrust::raw_pointer_cast(keys_out.data())), k); auto d_values_in = cuda::make_constant_iterator(cuda::make_counting_iterator(0)); auto d_values_out = cuda::make_strided_iterator(cuda::make_counting_iterator(thrust::raw_pointer_cast(values_out.data())), k); cuda::stream stream{cuda::devices[0]}; auto env = cuda::std::execution::env{ cuda::execution::require(cuda::execution::determinism::not_guaranteed, cuda::execution::tie_break::unspecified, cuda::execution::output_ordering::unsorted), cuda::stream_ref{stream}}; auto error = cub::DeviceBatchedTopK::MaxPairs( d_keys_in, d_keys_out, d_values_in, d_values_out, cuda::args::constant<segment_size>{}, cuda::args::constant<k>{}, cuda::args::immediate{cuda::std::int64_t{num_segments}}, env); // keys_out holds each segment's k largest keys. The key set is fixed (shown here sorted per segment). For // keys that tie, which equal element's value is returned is unspecified. auto expected_result_set = thrust::device_vector<int>{8, 7, 6, /* segment 0 */ 9, 8, 7 /* segment 1 */};
- Template Parameters:
KeyInputIteratorItT – [inferred] Random-access input iterator over per-segment key-input iterators (may be a simple pointer type)
KeyOutputIteratorItT – [inferred] Random-access input iterator over per-segment key-output iterators (may be a simple pointer type)
ValueInputIteratorItT – [inferred] Random-access input iterator over per-segment value-input iterators (may be a simple pointer type)
ValueOutputIteratorItT – [inferred] Random-access input iterator over per-segment value-output iterators (may be a simple pointer type)
SegmentSizeParameterT – [inferred] Type of the
segment_sizesargumentKParameterT – [inferred] Type of the
kargumentNumSegmentsParameterT – [inferred] Type of the
num_segmentsargumentEnvT – [inferred] Execution environment type. Default is
cuda::std::execution::env<>.
- Parameters:
d_keys_in – [in] Iterator such that
d_keys_in[i]yields a random-access iterator to the keys of segmentid_keys_out – [out] Iterator such that
d_keys_out[i]yields a random-access output iterator for the top-k keys of segmentid_values_in – [in] Iterator such that
d_values_in[i]yields a random-access iterator to the values of segmentid_values_out – [out] Iterator such that
d_values_out[i]yields a random-access output iterator for the values corresponding to the top-k keys of segmentisegment_sizes – [in] Annotated argument providing the per-segment sizes (e.g.
cuda::args::constant<N>for a uniform size, orcuda::args::deferred_sequence{...}for variable sizes). Must carry a small compile-time maximum. Prefer a sharp (tight) upper bound, since a looser bound may increase temporary-storage usage (see the Choosing argument bounds section).k – [in] The number of selected items per segment, given as a
cuda::argsannotation or a plain integral value.num_segments – [in] The (uniform) number of segments, given as a
cuda::argsannotation or a plain integral value.env – [in]
[optional] Execution environment. Must require determinism::not_guaranteed, tie_break::unspecified, and output_ordering::unsorted.
-
template<typename KeyInputIteratorItT, typename KeyOutputIteratorItT, typename ValueInputIteratorItT, typename ValueOutputIteratorItT, typename SegmentSizeParameterT, typename KParameterT, typename NumSegmentsParameterT, typename EnvT = ::cuda::std::execution::env<>>
static inline cudaError_t MinPairs( - void *d_temp_storage,
- size_t &temp_storage_bytes,
- KeyInputIteratorItT d_keys_in,
- KeyOutputIteratorItT d_keys_out,
- ValueInputIteratorItT d_values_in,
- ValueOutputIteratorItT d_values_out,
- SegmentSizeParameterT segment_sizes,
- KParameterT k,
- NumSegmentsParameterT num_segments,
- const EnvT &env = {}
Finds, for each segment, the smallest K keys and their corresponding values from an unordered input sequence of key-value pairs.
Temporary storage for this operation. If
d_temp_storageisnullptr, the required size is written totemp_storage_byteswithout dereferencing iterators or launching kernels. Otherwise,d_temp_storagemust point to a device-accessible allocation of at leasttemp_storage_bytesbytes. No special alignment is required. See Two-Phase API (explicit temporary storage management) for usage guidance.
A Simple Example#
constexpr int num_segments = 2; constexpr int segment_size = 8; constexpr int k = 3; auto keys_in = thrust::device_vector<int>{5, -3, 1, 7, 8, 2, 4, 6, /**/ 0, 9, 3, 2, 1, 8, 7, 4}; auto keys_out = thrust::device_vector<int>(num_segments * k, thrust::no_init); auto values_out = thrust::device_vector<int>(num_segments * k, thrust::no_init); auto d_keys_in = cuda::make_strided_iterator(cuda::make_counting_iterator(thrust::raw_pointer_cast(keys_in.data())), segment_size); auto d_keys_out = cuda::make_strided_iterator(cuda::make_counting_iterator(thrust::raw_pointer_cast(keys_out.data())), k); auto d_values_in = cuda::make_constant_iterator(cuda::make_counting_iterator(0)); auto d_values_out = cuda::make_strided_iterator(cuda::make_counting_iterator(thrust::raw_pointer_cast(values_out.data())), k); constexpr auto segment_sizes = cuda::args::constant<segment_size>{}; constexpr auto k_arg = cuda::args::constant<k>{}; auto num_segs = cuda::args::immediate{cuda::std::int64_t{num_segments}}; auto env = cuda::std::execution::env{cuda::execution::require( cuda::execution::determinism::not_guaranteed, cuda::execution::tie_break::unspecified, cuda::execution::output_ordering::unsorted)}; size_t temp_storage_bytes = 0; auto error = cub::DeviceBatchedTopK::MinPairs( nullptr, temp_storage_bytes, d_keys_in, d_keys_out, d_values_in, d_values_out, segment_sizes, k_arg, num_segs, env); thrust::device_vector<char> temp_storage(temp_storage_bytes, thrust::no_init); error = cub::DeviceBatchedTopK::MinPairs( thrust::raw_pointer_cast(temp_storage.data()), temp_storage_bytes, d_keys_in, d_keys_out, d_values_in, d_values_out, segment_sizes, k_arg, num_segs, env); // keys_out holds each segment's k smallest keys. The key set is fixed (shown here sorted per segment). For // keys that tie, which equal element's value is returned is unspecified. auto expected_result_set = thrust::device_vector<int>{-3, 1, 2, /* segment 0 */ 0, 1, 2 /* segment 1 */};
Note
The behavior is undefined if an output range overlaps another output range or any input range. Input ranges may overlap one another.
- Template Parameters:
KeyInputIteratorItT – [inferred] Random-access input iterator over per-segment key-input iterators (may be a simple pointer type)
KeyOutputIteratorItT – [inferred] Random-access input iterator over per-segment key-output iterators (may be a simple pointer type)
ValueInputIteratorItT – [inferred] Random-access input iterator over per-segment value-input iterators (may be a simple pointer type)
ValueOutputIteratorItT – [inferred] Random-access input iterator over per-segment value-output iterators (may be a simple pointer type)
SegmentSizeParameterT – [inferred] Type of the
segment_sizesargumentKParameterT – [inferred] Type of the
kargumentNumSegmentsParameterT – [inferred] Type of the
num_segmentsargumentEnvT – [inferred] Execution environment type. Default is
cuda::std::execution::env<>.
- Parameters:
d_temp_storage – [in] Device-accessible allocation of temporary storage. When
nullptr, the required allocation size is written totemp_storage_bytesand no work is done.temp_storage_bytes – [inout] Reference to size in bytes of
d_temp_storageallocationd_keys_in – [in] Iterator such that
d_keys_in[i]yields a random-access iterator to the keys of segmentid_keys_out – [out] Iterator such that
d_keys_out[i]yields a random-access output iterator for the top-k keys of segmentid_values_in – [in] Iterator such that
d_values_in[i]yields a random-access iterator to the values of segmentid_values_out – [out] Iterator such that
d_values_out[i]yields a random-access output iterator for the values corresponding to the top-k keys of segmentisegment_sizes – [in] Annotated argument providing the per-segment sizes (e.g.
cuda::args::constant<N>for a uniform size, orcuda::args::deferred_sequence{...}for variable sizes). Must carry a small compile-time maximum. Prefer a sharp (tight) upper bound, since a looser bound may increase temporary-storage usage (see the Choosing argument bounds section).k – [in] The number of selected items per segment, given as a
cuda::argsannotation or a plain integral value.num_segments – [in] The (uniform) number of segments, given as a
cuda::argsannotation or a plain integral value.env – [in]
[optional] Execution environment. Must require determinism::not_guaranteed, tie_break::unspecified, and output_ordering::unsorted.
-
template<typename KeyInputIteratorItT, typename KeyOutputIteratorItT, typename ValueInputIteratorItT, typename ValueOutputIteratorItT, typename SegmentSizeParameterT, typename KParameterT, typename NumSegmentsParameterT, typename EnvT = ::cuda::std::execution::env<>>
static inline cudaError_t MinPairs( - KeyInputIteratorItT d_keys_in,
- KeyOutputIteratorItT d_keys_out,
- ValueInputIteratorItT d_values_in,
- ValueOutputIteratorItT d_values_out,
- SegmentSizeParameterT segment_sizes,
- KParameterT k,
- NumSegmentsParameterT num_segments,
- const EnvT &env = {}
Finds, for each segment, the smallest K keys and their corresponding values. Environment-based overload that allocates temporary storage internally.
Snippet#
constexpr int num_segments = 2; constexpr int segment_size = 8; constexpr int k = 3; auto keys_in = thrust::device_vector<int>{5, -3, 1, 7, 8, 2, 4, 6, /**/ 0, 9, 3, 2, 1, 8, 7, 4}; auto keys_out = thrust::device_vector<int>(num_segments * k, thrust::no_init); auto values_out = thrust::device_vector<int>(num_segments * k, thrust::no_init); auto d_keys_in = cuda::make_strided_iterator(cuda::make_counting_iterator(thrust::raw_pointer_cast(keys_in.data())), segment_size); auto d_keys_out = cuda::make_strided_iterator(cuda::make_counting_iterator(thrust::raw_pointer_cast(keys_out.data())), k); auto d_values_in = cuda::make_constant_iterator(cuda::make_counting_iterator(0)); auto d_values_out = cuda::make_strided_iterator(cuda::make_counting_iterator(thrust::raw_pointer_cast(values_out.data())), k); cuda::stream stream{cuda::devices[0]}; auto env = cuda::std::execution::env{ cuda::execution::require(cuda::execution::determinism::not_guaranteed, cuda::execution::tie_break::unspecified, cuda::execution::output_ordering::unsorted), cuda::stream_ref{stream}}; auto error = cub::DeviceBatchedTopK::MinPairs( d_keys_in, d_keys_out, d_values_in, d_values_out, cuda::args::constant<segment_size>{}, cuda::args::constant<k>{}, cuda::args::immediate{cuda::std::int64_t{num_segments}}, env); // keys_out holds each segment's k smallest keys. The key set is fixed (shown here sorted per segment). For // keys that tie, which equal element's value is returned is unspecified. auto expected_result_set = thrust::device_vector<int>{-3, 1, 2, /* segment 0 */ 0, 1, 2 /* segment 1 */};
- Template Parameters:
KeyInputIteratorItT – [inferred] Random-access input iterator over per-segment key-input iterators (may be a simple pointer type)
KeyOutputIteratorItT – [inferred] Random-access input iterator over per-segment key-output iterators (may be a simple pointer type)
ValueInputIteratorItT – [inferred] Random-access input iterator over per-segment value-input iterators (may be a simple pointer type)
ValueOutputIteratorItT – [inferred] Random-access input iterator over per-segment value-output iterators (may be a simple pointer type)
SegmentSizeParameterT – [inferred] Type of the
segment_sizesargumentKParameterT – [inferred] Type of the
kargumentNumSegmentsParameterT – [inferred] Type of the
num_segmentsargumentEnvT – [inferred] Execution environment type. Default is
cuda::std::execution::env<>.
- Parameters:
d_keys_in – [in] Iterator such that
d_keys_in[i]yields a random-access iterator to the keys of segmentid_keys_out – [out] Iterator such that
d_keys_out[i]yields a random-access output iterator for the top-k keys of segmentid_values_in – [in] Iterator such that
d_values_in[i]yields a random-access iterator to the values of segmentid_values_out – [out] Iterator such that
d_values_out[i]yields a random-access output iterator for the values corresponding to the top-k keys of segmentisegment_sizes – [in] Annotated argument providing the per-segment sizes (e.g.
cuda::args::constant<N>for a uniform size, orcuda::args::deferred_sequence{...}for variable sizes). Must carry a small compile-time maximum. Prefer a sharp (tight) upper bound, since a looser bound may increase temporary-storage usage (see the Choosing argument bounds section).k – [in] The number of selected items per segment, given as a
cuda::argsannotation or a plain integral value.num_segments – [in] The (uniform) number of segments, given as a
cuda::argsannotation or a plain integral value.env – [in]
[optional] Execution environment. Must require determinism::not_guaranteed, tie_break::unspecified, and output_ordering::unsorted.