Skip to content

Commit c8a4deb

Browse files
authored
Cleanup libcudf detail/aggregation.hpp/.cuh (#18642)
The detail/aggregation headers are cleaned up a bit to hopefully allow follow on work to address issue #18568 . No functionality is changed -- mostly some device code is moved from `aggregation.cuh` to `aggregation.cu`. Authors: - David Wendt (https://github.com/davidwendt) Approvers: - Bradley Dice (https://github.com/bdice) - Yunsong Wang (https://github.com/PointKernel) URL: #18642
1 parent 2df89e9 commit c8a4deb

File tree

6 files changed

+135
-144
lines changed

6 files changed

+135
-144
lines changed

cpp/include/cudf/detail/aggregation/aggregation.cuh

Lines changed: 1 addition & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,14 @@
1717
#pragma once
1818

1919
#include <cudf/aggregation.hpp>
20-
#include <cudf/column/column_device_view.cuh>
21-
#include <cudf/column/column_view.hpp>
2220
#include <cudf/detail/aggregation/aggregation.hpp>
23-
#include <cudf/detail/utilities/assert.cuh>
24-
#include <cudf/detail/utilities/device_atomics.cuh>
21+
#include <cudf/detail/utilities/device_operators.cuh>
2522
#include <cudf/table/table_view.hpp>
2623
#include <cudf/utilities/span.hpp>
27-
#include <cudf/utilities/traits.cuh>
2824

2925
#include <rmm/cuda_stream_view.hpp>
3026
#include <rmm/exec_policy.hpp>
3127

32-
#include <thrust/fill.h>
33-
3428
#include <type_traits>
3529

3630
namespace cudf {
@@ -121,107 +115,5 @@ constexpr bool has_corresponding_operator()
121115
return !std::is_same_v<typename corresponding_operator<k>::type, void>;
122116
}
123117

124-
/**
125-
* @brief Dispatched functor to initialize a column with the identity of an
126-
* aggregation operation.
127-
*
128-
* Given a type `T` and `aggregation kind k`, determines and sets the value of
129-
* each element of the passed column to the appropriate initial value for the
130-
* aggregation.
131-
*
132-
* The initial values set as per aggregation are:
133-
* SUM: 0
134-
* COUNT_VALID: 0 and VALID
135-
* COUNT_ALL: 0 and VALID
136-
* MIN: Max value of type `T`
137-
* MAX: Min value of type `T`
138-
* ARGMAX: `ARGMAX_SENTINEL`
139-
* ARGMIN: `ARGMIN_SENTINEL`
140-
*
141-
* Only works on columns of fixed-width types.
142-
*/
143-
struct identity_initializer {
144-
private:
145-
template <typename T, aggregation::Kind k>
146-
static constexpr bool is_supported()
147-
{
148-
return cudf::is_fixed_width<T>() and
149-
(k == aggregation::SUM or k == aggregation::MIN or k == aggregation::MAX or
150-
k == aggregation::COUNT_VALID or k == aggregation::COUNT_ALL or
151-
k == aggregation::ARGMAX or k == aggregation::ARGMIN or
152-
k == aggregation::SUM_OF_SQUARES or k == aggregation::STD or
153-
k == aggregation::VARIANCE or
154-
(k == aggregation::PRODUCT and is_product_supported<T>()));
155-
}
156-
157-
template <typename T, aggregation::Kind k>
158-
std::enable_if_t<not std::is_same_v<corresponding_operator_t<k>, void>, T>
159-
identity_from_operator()
160-
{
161-
using DeviceType = device_storage_type_t<T>;
162-
return corresponding_operator_t<k>::template identity<DeviceType>();
163-
}
164-
165-
template <typename T, aggregation::Kind k>
166-
std::enable_if_t<std::is_same_v<corresponding_operator_t<k>, void>, T> identity_from_operator()
167-
{
168-
CUDF_FAIL("Unable to get identity/sentinel from device operator");
169-
}
170-
171-
template <typename T, aggregation::Kind k>
172-
T get_identity()
173-
{
174-
if (k == aggregation::ARGMAX || k == aggregation::ARGMIN) {
175-
if constexpr (cudf::is_timestamp<T>())
176-
return k == aggregation::ARGMAX ? T{typename T::duration(ARGMAX_SENTINEL)}
177-
: T{typename T::duration(ARGMIN_SENTINEL)};
178-
else {
179-
using DeviceType = device_storage_type_t<T>;
180-
return k == aggregation::ARGMAX ? static_cast<DeviceType>(ARGMAX_SENTINEL)
181-
: static_cast<DeviceType>(ARGMIN_SENTINEL);
182-
}
183-
}
184-
return identity_from_operator<T, k>();
185-
}
186-
187-
public:
188-
template <typename T, aggregation::Kind k>
189-
std::enable_if_t<is_supported<T, k>(), void> operator()(mutable_column_view const& col,
190-
rmm::cuda_stream_view stream)
191-
{
192-
using DeviceType = device_storage_type_t<T>;
193-
thrust::fill(rmm::exec_policy(stream),
194-
col.begin<DeviceType>(),
195-
col.end<DeviceType>(),
196-
get_identity<DeviceType, k>());
197-
}
198-
199-
template <typename T, aggregation::Kind k>
200-
std::enable_if_t<not is_supported<T, k>(), void> operator()(mutable_column_view const& col,
201-
rmm::cuda_stream_view stream)
202-
{
203-
CUDF_FAIL("Unsupported aggregation for initializing values");
204-
}
205-
};
206-
207-
/**
208-
* @brief Initializes each column in a table with a corresponding identity value
209-
* of an aggregation operation.
210-
*
211-
* The `i`th column will be initialized with the identity value of the `i`th
212-
* aggregation operation in `aggs`.
213-
*
214-
* @throw cudf::logic_error if column type and corresponding agg are incompatible
215-
* @throw cudf::logic_error if column type is not fixed-width
216-
*
217-
* @param table The table of columns to initialize.
218-
* @param aggs A span of aggregation operations corresponding to the table
219-
* columns. The aggregations determine the identity value for each column.
220-
* @param stream CUDA stream used for device memory operations and kernel launches.
221-
*/
222-
void initialize_with_identity(mutable_table_view& table,
223-
host_span<cudf::aggregation::Kind const> aggs,
224-
rmm::cuda_stream_view stream);
225-
226118
} // namespace detail
227119
} // namespace cudf

cpp/include/cudf/detail/aggregation/aggregation.hpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1716,5 +1716,24 @@ constexpr inline bool is_valid_aggregation()
17161716
*/
17171717
bool is_valid_aggregation(data_type source, aggregation::Kind k);
17181718

1719+
/**
1720+
* @brief Initializes each column in a table with a corresponding identity value
1721+
* of an aggregation operation.
1722+
*
1723+
* The `i`th column will be initialized with the identity value of the `i`th
1724+
* aggregation operation in `aggs`.
1725+
*
1726+
* @throw cudf::logic_error if column type and corresponding agg are incompatible
1727+
* @throw cudf::logic_error if column type is not fixed-width
1728+
*
1729+
* @param table The table of columns to initialize.
1730+
* @param aggs A span of aggregation operations corresponding to the table
1731+
* columns. The aggregations determine the identity value for each column.
1732+
* @param stream CUDA stream used for device memory operations and kernel launches.
1733+
*/
1734+
void initialize_with_identity(mutable_table_view& table,
1735+
host_span<cudf::aggregation::Kind const> aggs,
1736+
rmm::cuda_stream_view stream);
1737+
17191738
} // namespace detail
17201739
} // namespace CUDF_EXPORT cudf

cpp/include/cudf/detail/utilities/device_operators.cuh

Lines changed: 21 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019-2024, NVIDIA CORPORATION.
2+
* Copyright (c) 2019-2025, NVIDIA CORPORATION.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -23,7 +23,6 @@
2323

2424
#include <cudf/fixed_point/fixed_point.hpp>
2525
#include <cudf/fixed_point/temporary.hpp>
26-
#include <cudf/scalar/scalar.hpp>
2726
#include <cudf/strings/string_view.cuh>
2827
#include <cudf/types.hpp>
2928
#include <cudf/utilities/error.hpp>
@@ -128,23 +127,17 @@ struct DeviceMin {
128127
return numeric::detail::min(lhs, rhs);
129128
}
130129

131-
template <typename T,
132-
std::enable_if_t<!std::is_same_v<T, cudf::string_view> && !cudf::is_dictionary<T>() &&
133-
!cudf::is_fixed_point<T>()>* = nullptr>
130+
template <typename T, CUDF_ENABLE_IF(cudf::is_numeric<T>() && !cudf::is_fixed_point<T>())>
134131
CUDF_HOST_DEVICE static constexpr T identity()
135132
{
136-
// chrono types do not have std::numeric_limits specializations and should use T::max()
137-
// https://eel.is/c++draft/numeric.limits.general#6
138-
if constexpr (cudf::is_chrono<T>()) {
139-
return T::max();
140-
} else if constexpr (cuda::std::numeric_limits<T>::has_infinity) {
133+
if constexpr (cuda::std::numeric_limits<T>::has_infinity) {
141134
return cuda::std::numeric_limits<T>::infinity();
142135
} else {
143136
return cuda::std::numeric_limits<T>::max();
144137
}
145138
}
146139

147-
template <typename T, std::enable_if_t<cudf::is_fixed_point<T>()>* = nullptr>
140+
template <typename T, CUDF_ENABLE_IF(cudf::is_fixed_point<T>())>
148141
CUDF_HOST_DEVICE static constexpr T identity()
149142
{
150143
#ifndef __CUDA_ARCH__
@@ -155,14 +148,17 @@ struct DeviceMin {
155148
return cuda::std::numeric_limits<T>::max();
156149
}
157150

158-
// @brief identity specialized for string_view
159-
template <typename T, std::enable_if_t<std::is_same_v<T, cudf::string_view>>* = nullptr>
151+
// identity specialized for string_view and chrono types
152+
// chrono types do not have std::numeric_limits specializations and should use T::max()
153+
// https://eel.is/c++draft/numeric.limits.general#6
154+
template <typename T,
155+
CUDF_ENABLE_IF(cuda::std::is_same_v<T, cudf::string_view> || cudf::is_chrono<T>())>
160156
CUDF_HOST_DEVICE inline static constexpr T identity()
161157
{
162-
return string_view::max();
158+
return T::max();
163159
}
164160

165-
template <typename T, std::enable_if_t<cudf::is_dictionary<T>()>* = nullptr>
161+
template <typename T, CUDF_ENABLE_IF(cudf::is_dictionary<T>())>
166162
CUDF_HOST_DEVICE static constexpr T identity()
167163
{
168164
return static_cast<T>(T::max_value());
@@ -180,23 +176,17 @@ struct DeviceMax {
180176
return numeric::detail::max(lhs, rhs);
181177
}
182178

183-
template <typename T,
184-
std::enable_if_t<!std::is_same_v<T, cudf::string_view> && !cudf::is_dictionary<T>() &&
185-
!cudf::is_fixed_point<T>()>* = nullptr>
179+
template <typename T, CUDF_ENABLE_IF(cudf::is_numeric<T>() && !cudf::is_fixed_point<T>())>
186180
CUDF_HOST_DEVICE static constexpr T identity()
187181
{
188-
// chrono types do not have std::numeric_limits specializations and should use T::min()
189-
// https://eel.is/c++draft/numeric.limits.general#6
190-
if constexpr (cudf::is_chrono<T>()) {
191-
return T::min();
192-
} else if constexpr (cuda::std::numeric_limits<T>::has_infinity) {
182+
if constexpr (cuda::std::numeric_limits<T>::has_infinity) {
193183
return -cuda::std::numeric_limits<T>::infinity();
194184
} else {
195185
return cuda::std::numeric_limits<T>::lowest();
196186
}
197187
}
198188

199-
template <typename T, std::enable_if_t<cudf::is_fixed_point<T>()>* = nullptr>
189+
template <typename T, CUDF_ENABLE_IF(cudf::is_fixed_point<T>())>
200190
CUDF_HOST_DEVICE static constexpr T identity()
201191
{
202192
#ifndef __CUDA_ARCH__
@@ -207,13 +197,17 @@ struct DeviceMax {
207197
return cuda::std::numeric_limits<T>::lowest();
208198
}
209199

210-
template <typename T, std::enable_if_t<std::is_same_v<T, cudf::string_view>>* = nullptr>
200+
// identity specialized for string_view and chrono types
201+
// chrono types do not have std::numeric_limits specializations and should use T::min()
202+
// https://eel.is/c++draft/numeric.limits.general#6
203+
template <typename T,
204+
CUDF_ENABLE_IF(cuda::std::is_same_v<T, cudf::string_view> || cudf::is_chrono<T>())>
211205
CUDF_HOST_DEVICE inline static constexpr T identity()
212206
{
213-
return string_view::min();
207+
return T::min();
214208
}
215209

216-
template <typename T, std::enable_if_t<cudf::is_dictionary<T>()>* = nullptr>
210+
template <typename T, CUDF_ENABLE_IF(cudf::is_dictionary<T>())>
217211
CUDF_HOST_DEVICE static constexpr T identity()
218212
{
219213
return static_cast<T>(T::lowest_value());

cpp/src/aggregation/aggregation.cu

Lines changed: 90 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020-2024, NVIDIA CORPORATION.
2+
* Copyright (c) 2020-2025, NVIDIA CORPORATION.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,13 +16,99 @@
1616

1717
#include <cudf/detail/aggregation/aggregation.cuh>
1818
#include <cudf/detail/aggregation/aggregation.hpp>
19-
#include <cudf/table/table_view.hpp>
20-
#include <cudf/utilities/span.hpp>
2119

22-
#include <rmm/cuda_stream_view.hpp>
20+
#include <rmm/exec_policy.hpp>
21+
22+
#include <thrust/fill.h>
2323

2424
namespace cudf {
2525
namespace detail {
26+
namespace {
27+
28+
/**
29+
* @brief Dispatched functor to initialize a column with the identity of an
30+
* aggregation operation.
31+
*
32+
* Given a type `T` and `aggregation kind k`, determines and sets the value of
33+
* each element of the passed column to the appropriate initial value for the
34+
* aggregation.
35+
*
36+
* The initial values set as per aggregation are:
37+
* SUM: 0
38+
* COUNT_VALID: 0 and VALID
39+
* COUNT_ALL: 0 and VALID
40+
* MIN: Max value of type `T`
41+
* MAX: Min value of type `T`
42+
* ARGMAX: `ARGMAX_SENTINEL`
43+
* ARGMIN: `ARGMIN_SENTINEL`
44+
*
45+
* Only works on columns of fixed-width types.
46+
*/
47+
struct identity_initializer {
48+
private:
49+
template <typename T, aggregation::Kind k>
50+
static constexpr bool is_supported()
51+
{
52+
return cudf::is_fixed_width<T>() and
53+
(k == aggregation::SUM or k == aggregation::MIN or k == aggregation::MAX or
54+
k == aggregation::COUNT_VALID or k == aggregation::COUNT_ALL or
55+
k == aggregation::ARGMAX or k == aggregation::ARGMIN or
56+
k == aggregation::SUM_OF_SQUARES or k == aggregation::STD or
57+
k == aggregation::VARIANCE or
58+
(k == aggregation::PRODUCT and is_product_supported<T>()));
59+
}
60+
61+
template <typename T, aggregation::Kind k>
62+
std::enable_if_t<not std::is_same_v<corresponding_operator_t<k>, void>, T>
63+
identity_from_operator()
64+
{
65+
using DeviceType = device_storage_type_t<T>;
66+
return corresponding_operator_t<k>::template identity<DeviceType>();
67+
}
68+
69+
template <typename T, aggregation::Kind k>
70+
std::enable_if_t<std::is_same_v<corresponding_operator_t<k>, void>, T> identity_from_operator()
71+
{
72+
CUDF_FAIL("Unable to get identity/sentinel from device operator");
73+
}
74+
75+
template <typename T, aggregation::Kind k>
76+
T get_identity()
77+
{
78+
if (k == aggregation::ARGMAX || k == aggregation::ARGMIN) {
79+
if constexpr (cudf::is_timestamp<T>())
80+
return k == aggregation::ARGMAX ? T{typename T::duration(ARGMAX_SENTINEL)}
81+
: T{typename T::duration(ARGMIN_SENTINEL)};
82+
else {
83+
using DeviceType = device_storage_type_t<T>;
84+
return k == aggregation::ARGMAX ? static_cast<DeviceType>(ARGMAX_SENTINEL)
85+
: static_cast<DeviceType>(ARGMIN_SENTINEL);
86+
}
87+
}
88+
return identity_from_operator<T, k>();
89+
}
90+
91+
public:
92+
template <typename T, aggregation::Kind k>
93+
std::enable_if_t<is_supported<T, k>(), void> operator()(mutable_column_view const& col,
94+
rmm::cuda_stream_view stream)
95+
{
96+
using DeviceType = device_storage_type_t<T>;
97+
thrust::fill(rmm::exec_policy(stream),
98+
col.begin<DeviceType>(),
99+
col.end<DeviceType>(),
100+
get_identity<DeviceType, k>());
101+
}
102+
103+
template <typename T, aggregation::Kind k>
104+
std::enable_if_t<not is_supported<T, k>(), void> operator()(mutable_column_view const& col,
105+
rmm::cuda_stream_view stream)
106+
{
107+
CUDF_FAIL("Unsupported aggregation for initializing values");
108+
}
109+
};
110+
} // namespace
111+
26112
void initialize_with_identity(mutable_table_view& table,
27113
host_span<cudf::aggregation::Kind const> aggs,
28114
rmm::cuda_stream_view stream)

cpp/src/groupby/hash/create_sparse_results_table.cu

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2024, NVIDIA CORPORATION.
2+
* Copyright (c) 2024-2025, NVIDIA CORPORATION.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@
2020

2121
#include <cudf/aggregation.hpp>
2222
#include <cudf/column/column_factories.hpp>
23-
#include <cudf/detail/aggregation/aggregation.cuh>
23+
#include <cudf/detail/aggregation/aggregation.hpp>
2424
#include <cudf/table/table_view.hpp>
2525
#include <cudf/types.hpp>
2626
#include <cudf/utilities/span.hpp>

0 commit comments

Comments
 (0)