2626
2727namespace xgboost ::common {
2828namespace detail {
29+
30+ #if CUB_VERSION >= 300000
31+ constexpr auto kCubSortOrderAscending = cub::SortOrder::Ascending;
32+ constexpr auto kCubSortOrderDescending = cub::SortOrder::Descending;
33+ #else
34+ constexpr bool kCubSortOrderAscending = false ;
35+ constexpr bool kCubSortOrderDescending = true ;
36+ #endif
37+
2938// Wrapper around cub sort to define is_decending
3039template <bool IS_DESCENDING , typename KeyT, typename BeginOffsetIteratorT,
3140 typename EndOffsetIteratorT>
@@ -42,8 +51,9 @@ static void DeviceSegmentedRadixSortKeys(CUDAContext const *ctx, void *d_temp_st
4251 cub::DoubleBuffer<KeyT> d_keys (const_cast <KeyT *>(d_keys_in), d_keys_out);
4352 cub::DoubleBuffer<cub::NullType> d_values;
4453
54+ constexpr auto kCubSortOrder = IS_DESCENDING ? kCubSortOrderDescending : kCubSortOrderAscending ;
4555 dh::safe_cuda ((cub::DispatchSegmentedRadixSort<
46- IS_DESCENDING , KeyT, cub::NullType, BeginOffsetIteratorT, EndOffsetIteratorT,
56+ kCubSortOrder , KeyT, cub::NullType, BeginOffsetIteratorT, EndOffsetIteratorT,
4757 OffsetT>::Dispatch (d_temp_storage, temp_storage_bytes, d_keys, d_values, num_items,
4858 num_segments, d_begin_offsets, d_end_offsets, begin_bit,
4959 end_bit, false , ctx->Stream (), debug_synchronous)));
@@ -68,21 +78,22 @@ void DeviceSegmentedRadixSortPair(void *d_temp_storage,
6878 CHECK_LE (num_items, std::numeric_limits<OffsetT>::max ());
6979 // For Thrust >= 1.12 or CUDA >= 11.4, we require system cub installation
7080
81+ constexpr auto kCubSortOrder = descending ? kCubSortOrderDescending : kCubSortOrderAscending ;
7182#if THRUST_MAJOR_VERSION >= 2
7283 dh::safe_cuda ((cub::DispatchSegmentedRadixSort<
73- descending , KeyT, ValueT, BeginOffsetIteratorT, EndOffsetIteratorT,
84+ kCubSortOrder , KeyT, ValueT, BeginOffsetIteratorT, EndOffsetIteratorT,
7485 OffsetT>::Dispatch (d_temp_storage, temp_storage_bytes, d_keys, d_values, num_items,
7586 num_segments, d_begin_offsets, d_end_offsets, begin_bit,
7687 end_bit, false , stream)));
7788#elif (THRUST_MAJOR_VERSION == 1 && THRUST_MINOR_VERSION >= 13)
7889 dh::safe_cuda ((cub::DispatchSegmentedRadixSort<
79- descending , KeyT, ValueT, BeginOffsetIteratorT, EndOffsetIteratorT,
90+ kCubSortOrder , KeyT, ValueT, BeginOffsetIteratorT, EndOffsetIteratorT,
8091 OffsetT>::Dispatch (d_temp_storage, temp_storage_bytes, d_keys, d_values, num_items,
8192 num_segments, d_begin_offsets, d_end_offsets, begin_bit,
8293 end_bit, false , stream, false )));
8394#else
8495 dh::safe_cuda (
85- (cub::DispatchSegmentedRadixSort<descending , KeyT, ValueT, BeginOffsetIteratorT,
96+ (cub::DispatchSegmentedRadixSort<kCubSortOrder , KeyT, ValueT, BeginOffsetIteratorT,
8697 OffsetT>::Dispatch (d_temp_storage, temp_storage_bytes,
8798 d_keys, d_values, num_items, num_segments,
8899 d_begin_offsets, d_end_offsets, begin_bit,
@@ -207,47 +218,48 @@ void ArgSort(Context const *ctx, Span<U> keys, Span<IdxT> sorted_idx) {
207218 // track https://github.com/NVIDIA/cub/pull/340 for 64bit length support
208219 using OffsetT = std::conditional_t <!dh::BuildWithCUDACub (), std::ptrdiff_t , int32_t >;
209220 CHECK_LE (sorted_idx.size (), std::numeric_limits<OffsetT>::max ());
221+
210222 if (accending) {
211223 void *d_temp_storage = nullptr ;
212224#if THRUST_MAJOR_VERSION >= 2
213- dh::safe_cuda ((cub::DispatchRadixSort<false , KeyT, ValueT, OffsetT>::Dispatch (
225+ dh::safe_cuda ((cub::DispatchRadixSort<detail:: kCubSortOrderAscending , KeyT, ValueT, OffsetT>::Dispatch (
214226 d_temp_storage, bytes, d_keys, d_values, sorted_idx.size (), 0 , sizeof (KeyT) * 8 , false ,
215227 cuctx->Stream ())));
216228#else
217- dh::safe_cuda ((cub::DispatchRadixSort<false , KeyT, ValueT, OffsetT>::Dispatch (
229+ dh::safe_cuda ((cub::DispatchRadixSort<detail:: kCubSortOrderAscending , KeyT, ValueT, OffsetT>::Dispatch (
218230 d_temp_storage, bytes, d_keys, d_values, sorted_idx.size (), 0 , sizeof (KeyT) * 8 , false ,
219231 nullptr , false )));
220232#endif
221233 dh::TemporaryArray<char > storage (bytes);
222234 d_temp_storage = storage.data ().get ();
223235#if THRUST_MAJOR_VERSION >= 2
224- dh::safe_cuda ((cub::DispatchRadixSort<false , KeyT, ValueT, OffsetT>::Dispatch (
236+ dh::safe_cuda ((cub::DispatchRadixSort<detail:: kCubSortOrderAscending , KeyT, ValueT, OffsetT>::Dispatch (
225237 d_temp_storage, bytes, d_keys, d_values, sorted_idx.size (), 0 , sizeof (KeyT) * 8 , false ,
226238 cuctx->Stream ())));
227239#else
228- dh::safe_cuda ((cub::DispatchRadixSort<false , KeyT, ValueT, OffsetT>::Dispatch (
240+ dh::safe_cuda ((cub::DispatchRadixSort<detail:: kCubSortOrderAscending , KeyT, ValueT, OffsetT>::Dispatch (
229241 d_temp_storage, bytes, d_keys, d_values, sorted_idx.size (), 0 , sizeof (KeyT) * 8 , false ,
230242 nullptr , false )));
231243#endif
232244 } else {
233245 void *d_temp_storage = nullptr ;
234246#if THRUST_MAJOR_VERSION >= 2
235- dh::safe_cuda ((cub::DispatchRadixSort<true , KeyT, ValueT, OffsetT>::Dispatch (
247+ dh::safe_cuda ((cub::DispatchRadixSort<detail:: kCubSortOrderDescending , KeyT, ValueT, OffsetT>::Dispatch (
236248 d_temp_storage, bytes, d_keys, d_values, sorted_idx.size (), 0 , sizeof (KeyT) * 8 , false ,
237249 cuctx->Stream ())));
238250#else
239- dh::safe_cuda ((cub::DispatchRadixSort<true , KeyT, ValueT, OffsetT>::Dispatch (
251+ dh::safe_cuda ((cub::DispatchRadixSort<detail:: kCubSortOrderDescending , KeyT, ValueT, OffsetT>::Dispatch (
240252 d_temp_storage, bytes, d_keys, d_values, sorted_idx.size (), 0 , sizeof (KeyT) * 8 , false ,
241253 nullptr , false )));
242254#endif
243255 dh::TemporaryArray<char > storage (bytes);
244256 d_temp_storage = storage.data ().get ();
245257#if THRUST_MAJOR_VERSION >= 2
246- dh::safe_cuda ((cub::DispatchRadixSort<true , KeyT, ValueT, OffsetT>::Dispatch (
258+ dh::safe_cuda ((cub::DispatchRadixSort<detail:: kCubSortOrderDescending , KeyT, ValueT, OffsetT>::Dispatch (
247259 d_temp_storage, bytes, d_keys, d_values, sorted_idx.size (), 0 , sizeof (KeyT) * 8 , false ,
248260 cuctx->Stream ())));
249261#else
250- dh::safe_cuda ((cub::DispatchRadixSort<true , KeyT, ValueT, OffsetT>::Dispatch (
262+ dh::safe_cuda ((cub::DispatchRadixSort<detail:: kCubSortOrderDescending , KeyT, ValueT, OffsetT>::Dispatch (
251263 d_temp_storage, bytes, d_keys, d_values, sorted_idx.size (), 0 , sizeof (KeyT) * 8 , false ,
252264 nullptr , false )));
253265#endif
@@ -277,6 +289,10 @@ void CopyIf(CUDAContext const *cuctx, InIt in_first, InIt in_second, OutIt out_f
277289template <typename InputIteratorT, typename OutputIteratorT, typename ScanOpT, typename OffsetT>
278290void InclusiveScan (xgboost::Context const *ctx, InputIteratorT d_in, OutputIteratorT d_out,
279291 ScanOpT scan_op, OffsetT num_items) {
292+ #if CUB_VERSION >= 300000
293+ static_assert (std::is_unsigned_v<OffsetT>, " OffsetT must be unsigned" );
294+ static_assert (sizeof (OffsetT) >= 4 , " OffsetT must be at least 4 bytes long" );
295+ #endif
280296 auto cuctx = ctx->CUDACtx ();
281297 std::size_t bytes = 0 ;
282298#if THRUST_MAJOR_VERSION >= 2
@@ -304,7 +320,11 @@ void InclusiveScan(xgboost::Context const *ctx, InputIteratorT d_in, OutputItera
304320template <typename InputIteratorT, typename OutputIteratorT, typename OffsetT>
305321void InclusiveSum (Context const *ctx, InputIteratorT d_in, OutputIteratorT d_out,
306322 OffsetT num_items) {
323+ #if CUB_VERSION >= 300000
324+ InclusiveScan (ctx, d_in, d_out, cuda::std::plus{}, num_items);
325+ #else
307326 InclusiveScan (ctx, d_in, d_out, cub::Sum{}, num_items);
327+ #endif
308328}
309329} // namespace xgboost::common
310330#endif // XGBOOST_COMMON_ALGORITHM_CUH_
0 commit comments