Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add compound aggregations to cudf::segmented_reduce #12573

Merged
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
a9fdb94
Add compound aggregations to cudf::segmented_reduce
davidwendt Jan 18, 2023
d8d89af
Merge branch 'branch-23.02' into reduction-segmented-compound
davidwendt Jan 18, 2023
2d32592
Merge branch 'branch-23.02' into reduction-segmented-compound
davidwendt Jan 18, 2023
94d15f9
Merge branch 'branch-23.02' into reduction-segmented-compound
davidwendt Jan 19, 2023
26d2f0d
add gtests with nulls include/exclude
davidwendt Jan 19, 2023
ebc41a1
reduce number of nulls in new gtests
davidwendt Jan 19, 2023
1ecece3
Merge branch 'branch-23.02' into reduction-segmented-compound
davidwendt Jan 24, 2023
96a6643
Merge branch 'branch-23.02' into reduction-segmented-compound
davidwendt Jan 24, 2023
60bdf8b
Merge branch 'reduction-segmented-compound' of github.com:davidwendt/…
davidwendt Jan 24, 2023
ca27894
update include statements
davidwendt Jan 24, 2023
c1f0939
update doxygen for consistency
davidwendt Jan 24, 2023
cdc2f9c
remove unneeded namespace specification
davidwendt Jan 24, 2023
7b42240
Merge branch 'branch-23.04' into reduction-segmented-compound
davidwendt Jan 24, 2023
3064979
add more error gtests
davidwendt Jan 24, 2023
7436879
fix copyright year
davidwendt Jan 24, 2023
105fe62
remove unneeded include
davidwendt Jan 24, 2023
1b31af2
Merge branch 'branch-23.04' into reduction-segmented-compound
davidwendt Jan 25, 2023
5fbad16
Merge branch 'reduction-segmented-compound' of github.com:davidwendt/…
davidwendt Jan 25, 2023
c9ad9f5
Merge branch 'branch-23.04' into reduction-segmented-compound
davidwendt Jan 25, 2023
fafe40f
Merge branch 'branch-23.04' into reduction-segmented-compound
davidwendt Jan 25, 2023
e8d1123
Merge branch 'reduction-segmented-compound' of github.com:davidwendt/…
davidwendt Jan 25, 2023
7a31c4d
Merge branch 'branch-23.04' into reduction-segmented-compound
davidwendt Jan 26, 2023
8bef913
Merge branch 'branch-23.04' into reduction-segmented-compound
davidwendt Jan 26, 2023
facc772
Merge branch 'reduction-segmented-compound' of github.com:davidwendt/…
davidwendt Jan 26, 2023
d139d83
Merge branch 'branch-23.04' into reduction-segmented-compound
davidwendt Jan 26, 2023
d35c475
refactor validity-mask logic into separate source file
davidwendt Jan 28, 2023
8055499
Merge branch 'branch-23.04' into reduction-segmented-compound
davidwendt Jan 28, 2023
ea12e69
Merge branch 'branch-23.04' into reduction-segmented-compound
davidwendt Jan 30, 2023
bdd0e1d
Merge branch 'branch-23.04' into reduction-segmented-compound
davidwendt Jan 30, 2023
35e2cbe
Merge branch 'branch-23.04' into reduction-segmented-compound
davidwendt Jan 30, 2023
d53b536
Merge branch 'reduction-segmented-compound' of github.com:davidwendt/…
davidwendt Jan 30, 2023
a500a15
Merge branch 'branch-23.04' into reduction-segmented-compound
davidwendt Jan 31, 2023
46fb462
Merge branch 'reduction-segmented-compound' of github.com:davidwendt/…
davidwendt Jan 31, 2023
700e61e
Merge branch 'branch-23.04' into reduction-segmented-compound
davidwendt Feb 1, 2023
af56df5
Merge branch 'branch-23.04' into reduction-segmented-compound
davidwendt Feb 1, 2023
67540f2
Merge branch 'reduction-segmented-compound' of github.com:davidwendt/…
davidwendt Feb 1, 2023
af9d778
Merge branch 'branch-23.04' into reduction-segmented-compound
davidwendt Feb 2, 2023
5bedc84
additional refactor for update_validity
davidwendt Feb 2, 2023
04f7205
Merge branch 'branch-23.04' into reduction-segmented-compound
davidwendt Feb 3, 2023
2d2587b
rename update-validity
davidwendt Feb 3, 2023
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
1 change: 1 addition & 0 deletions conda/recipes/libcudf/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ outputs:
- test -f $PREFIX/include/cudf/detail/scan.hpp
- test -f $PREFIX/include/cudf/detail/scatter.hpp
- test -f $PREFIX/include/cudf/detail/search.hpp
- test -f $PREFIX/include/cudf/detail/segmented_reduction_functions.hpp
- test -f $PREFIX/include/cudf/detail/sequence.hpp
- test -f $PREFIX/include/cudf/detail/sorting.hpp
- test -f $PREFIX/include/cudf/detail/stream_compaction.hpp
Expand Down
19 changes: 12 additions & 7 deletions cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -440,13 +440,18 @@ add_library(
src/reductions/scan/scan.cpp
src/reductions/scan/scan_exclusive.cu
src/reductions/scan/scan_inclusive.cu
src/reductions/segmented_all.cu
src/reductions/segmented_any.cu
src/reductions/segmented_max.cu
src/reductions/segmented_min.cu
src/reductions/segmented_product.cu
src/reductions/segmented_reductions.cpp
src/reductions/segmented_sum.cu
src/reductions/segmented/all.cu
src/reductions/segmented/any.cu
src/reductions/segmented/max.cu
src/reductions/segmented/mean.cu
src/reductions/segmented/min.cu
src/reductions/segmented/product.cu
src/reductions/segmented/reductions.cpp
src/reductions/segmented/std.cu
src/reductions/segmented/sum.cu
src/reductions/segmented/sum_of_squares.cu
src/reductions/segmented/update_validity.cu
src/reductions/segmented/var.cu
src/reductions/std.cu
src/reductions/sum.cu
src/reductions/sum_of_squares.cu
Expand Down
10 changes: 7 additions & 3 deletions cpp/include/cudf/detail/aggregation/aggregation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,9 @@ class all_aggregation final : public reduce_aggregation, public segmented_reduce
/**
* @brief Derived class for specifying a sum_of_squares aggregation
*/
class sum_of_squares_aggregation final : public groupby_aggregation, public reduce_aggregation {
class sum_of_squares_aggregation final : public groupby_aggregation,
public reduce_aggregation,
public segmented_reduce_aggregation {
public:
sum_of_squares_aggregation() : aggregation(SUM_OF_SQUARES) {}

Expand All @@ -313,7 +315,8 @@ class sum_of_squares_aggregation final : public groupby_aggregation, public redu
*/
class mean_aggregation final : public rolling_aggregation,
public groupby_aggregation,
public reduce_aggregation {
public reduce_aggregation,
public segmented_reduce_aggregation {
public:
mean_aggregation() : aggregation(MEAN) {}

Expand Down Expand Up @@ -353,7 +356,8 @@ class m2_aggregation : public groupby_aggregation {
*/
class std_var_aggregation : public rolling_aggregation,
public groupby_aggregation,
public reduce_aggregation {
public reduce_aggregation,
public segmented_reduce_aggregation {
public:
size_type _ddof; ///< Delta degrees of freedom

Expand Down
91 changes: 2 additions & 89 deletions cpp/include/cudf/detail/reduction.cuh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2022, NVIDIA CORPORATION.
* Copyright (c) 2019-2023, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,7 +16,7 @@

#pragma once

#include "reduction_operators.cuh"
#include <cudf/detail/reduction_operators.cuh>

#include <cudf/column/column_factories.hpp>
#include <cudf/utilities/type_dispatcher.hpp>
Expand All @@ -27,7 +27,6 @@
#include <rmm/exec_policy.hpp>

#include <cub/device/device_reduce.cuh>
#include <cub/device/device_segmented_reduce.cuh>

#include <thrust/for_each.h>
#include <thrust/iterator/iterator_traits.h>
Expand Down Expand Up @@ -229,92 +228,6 @@ std::unique_ptr<scalar> reduce(InputIterator d_in,
return std::unique_ptr<scalar>(result);
}

/**
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These functions were moved to segmented_reduction.cuh

* @brief Compute the specified simple reduction over each of the segments in the
* input range of elements.
*
* @tparam InputIterator the input column iterator
* @tparam OffsetIterator the offset column iterator
* @tparam OutputIterator the output column iterator
* @tparam BinaryOp the device binary operator used to reduce
* @tparam OutputType the output type of reduction
*
* @param[in] d_in the begin iterator to input
* @param[in] d_offset_begin the begin iterator to offset
* @param[in] d_offset_end the end iterator to offset. Note: This is
* num_segments+1 elements past `d_offset_begin`.
* @param[out] d_out the begin iterator to output
* @param[in] binary_op the reduction operator
* @param[in] identity the identity element of the reduction operator
* @param[in] initial_value Initial value of the reduction
* @param[in] stream CUDA stream used for device memory operations and kernel launches
*
*/
template <typename InputIterator,
typename OffsetIterator,
typename OutputIterator,
typename BinaryOp,
typename OutputType = typename thrust::iterator_value<OutputIterator>::type,
typename std::enable_if_t<is_fixed_width<OutputType>() &&
!cudf::is_fixed_point<OutputType>()>* = nullptr>
void segmented_reduce(InputIterator d_in,
OffsetIterator d_offset_begin,
OffsetIterator d_offset_end,
OutputIterator d_out,
BinaryOp binary_op,
OutputType initial_value,
rmm::cuda_stream_view stream)
{
auto const num_segments = static_cast<size_type>(std::distance(d_offset_begin, d_offset_end)) - 1;

// Allocate temporary storage
rmm::device_buffer d_temp_storage;
size_t temp_storage_bytes = 0;
cub::DeviceSegmentedReduce::Reduce(d_temp_storage.data(),
temp_storage_bytes,
d_in,
d_out,
num_segments,
d_offset_begin,
d_offset_begin + 1,
binary_op,
initial_value,
stream.value());
d_temp_storage = rmm::device_buffer{temp_storage_bytes, stream};

// Run reduction
cub::DeviceSegmentedReduce::Reduce(d_temp_storage.data(),
temp_storage_bytes,
d_in,
d_out,
num_segments,
d_offset_begin,
d_offset_begin + 1,
binary_op,
initial_value,
stream.value());
}

template <typename InputIterator,
typename OffsetIterator,
typename OutputIterator,
typename BinaryOp,
typename OutputType = typename thrust::iterator_value<OutputIterator>::type,
typename std::enable_if_t<!(is_fixed_width<OutputType>() &&
!cudf::is_fixed_point<OutputType>())>* = nullptr>
void segmented_reduce(InputIterator,
OffsetIterator,
OffsetIterator,
OutputIterator,
BinaryOp,
OutputType,
rmm::cuda_stream_view)
{
CUDF_FAIL(
"Unsupported data types called on segmented_reduce. Only numeric and chrono types are "
"supported.");
}

} // namespace detail
} // namespace reduction
} // namespace cudf
168 changes: 1 addition & 167 deletions cpp/include/cudf/detail/reduction_functions.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2022, NVIDIA CORPORATION.
* Copyright (c) 2019-2023, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -338,171 +338,5 @@ std::unique_ptr<scalar> merge_sets(
rmm::cuda_stream_view stream,
rmm::mr::device_memory_resource* mr = rmm::mr::get_current_device_resource());

/**
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These functions were moved to segmented_reduction_functions.hpp

* @brief Compute sum of each segment in input column.
*
* If an input segment is empty, the segment result is null.
*
* @throw cudf::logic_error if input column type is not convertible to `output_dtype`.
* @throw cudf::logic_error if `output_dtype` is not an arithmetic type.
*
* @param col Input column to compute sum
* @param offsets Indices to identify segment boundaries
* @param output_dtype Data type of return type and typecast elements of input column
* @param null_handling If `null_policy::INCLUDE`, all elements in a segment must be valid for the
* reduced value to be valid. If `null_policy::EXCLUDE`, the reduced value is valid if any element
* in the segment is valid.
* @param init Initial value of each sum
* @param stream CUDA stream used for device memory operations and kernel launches
* @param mr Device memory resource used to allocate the returned column's device memory
* @return Sums of segments in type `output_dtype`
*/
std::unique_ptr<column> segmented_sum(
column_view const& col,
device_span<size_type const> offsets,
data_type const output_dtype,
null_policy null_handling,
std::optional<std::reference_wrapper<scalar const>> init,
rmm::cuda_stream_view stream,
rmm::mr::device_memory_resource* mr = rmm::mr::get_current_device_resource());

/**
* @brief Computes product of each segment in input column.
*
* If an input segment is empty, the segment result is null.
*
* @throw cudf::logic_error if input column type is not convertible to `output_dtype`.
* @throw cudf::logic_error if `output_dtype` is not an arithmetic type.
*
* @param col Input column to compute product
* @param offsets Indices to identify segment boundaries
* @param output_dtype data type of return type and typecast elements of input column
* @param null_handling If `null_policy::INCLUDE`, all elements in a segment must be valid for the
* reduced value to be valid. If `null_policy::EXCLUDE`, the reduced value is valid if any element
* in the segment is valid.
* @param init Initial value of each product
* @param stream CUDA stream used for device memory operations and kernel launches
* @param mr Device memory resource used to allocate the returned scalar's device memory
* @return Product as scalar of type `output_dtype`
*/
std::unique_ptr<column> segmented_product(
column_view const& col,
device_span<size_type const> offsets,
data_type const output_dtype,
null_policy null_handling,
std::optional<std::reference_wrapper<scalar const>> init,
rmm::cuda_stream_view stream,
rmm::mr::device_memory_resource* mr = rmm::mr::get_current_device_resource());

/**
* @brief Compute minimum of each segment in input column.
*
* If an input segment is empty, the segment result is null.
*
* @throw cudf::logic_error if input column type is convertible to `output_dtype`.
*
* @param col Input column to compute minimum
* @param offsets Indices to identify segment boundaries
* @param output_dtype Data type of return type and typecast elements of input column
* @param null_handling If `null_policy::INCLUDE`, all elements in a segment must be valid for the
* reduced value to be valid. If `null_policy::EXCLUDE`, the reduced value is valid if any element
* in the segment is valid.
* @param init Initial value of each minimum
* @param stream CUDA stream used for device memory operations and kernel launches
* @param mr Device memory resource used to allocate the returned scalar's device memory
* @return Minimums of segments in type `output_dtype`
*/
std::unique_ptr<column> segmented_min(
column_view const& col,
device_span<size_type const> offsets,
data_type const output_dtype,
null_policy null_handling,
std::optional<std::reference_wrapper<scalar const>> init,
rmm::cuda_stream_view stream,
rmm::mr::device_memory_resource* mr = rmm::mr::get_current_device_resource());

/**
* @brief Compute maximum of each segment in input column.
*
* If an input segment is empty, the segment result is null.
*
* @throw cudf::logic_error if input column type is convertible to `output_dtype`.
*
* @param col Input column to compute maximum
* @param offsets Indices to identify segment boundaries
* @param output_dtype Data type of return type and typecast elements of input column
* @param null_handling If `null_policy::INCLUDE`, all elements in a segment must be valid for the
* reduced value to be valid. If `null_policy::EXCLUDE`, the reduced value is valid if any element
* in the segment is valid.
* @param init Initial value of each maximum
* @param stream CUDA stream used for device memory operations and kernel launches
* @param mr Device memory resource used to allocate the returned scalar's device memory
* @return Maximums of segments in type `output_dtype`
*/
std::unique_ptr<column> segmented_max(
column_view const& col,
device_span<size_type const> offsets,
data_type const output_dtype,
null_policy null_handling,
std::optional<std::reference_wrapper<scalar const>> init,
rmm::cuda_stream_view stream,
rmm::mr::device_memory_resource* mr = rmm::mr::get_current_device_resource());

/**
* @brief Compute if any of the values in the segment are true when typecasted to bool.
*
* If an input segment is empty, the segment result is null.
*
* @throw cudf::logic_error if input column type is not convertible to bool.
* @throw cudf::logic_error if `output_dtype` is not bool8.
*
* @param col Input column to compute any
* @param offsets Indices to identify segment boundaries
* @param output_dtype Data type of return type and typecast elements of input column
* @param null_handling If `null_policy::INCLUDE`, all elements in a segment must be valid for the
* reduced value to be valid. If `null_policy::EXCLUDE`, the reduced value is valid if any element
* in the segment is valid.
* @param init Initial value of each any
* @param stream CUDA stream used for device memory operations and kernel launches
* @param mr Device memory resource used to allocate the returned scalar's device memory
* @return Column of bool8 for the results of the segments
*/
std::unique_ptr<column> segmented_any(
column_view const& col,
device_span<size_type const> offsets,
data_type const output_dtype,
null_policy null_handling,
std::optional<std::reference_wrapper<scalar const>> init,
rmm::cuda_stream_view stream,
rmm::mr::device_memory_resource* mr = rmm::mr::get_current_device_resource());

/**
* @brief Compute if all of the values in the segment are true when typecasted to bool.
*
* If an input segment is empty, the segment result is null.
*
* @throw cudf::logic_error if input column type is not convertible to bool.
* @throw cudf::logic_error if `output_dtype` is not bool8.
*
* @param col Input column to compute all
* @param offsets Indices to identify segment boundaries
* @param output_dtype Data type of return type and typecast elements of input column
* @param null_handling If `null_policy::INCLUDE`, all elements in a segment must be valid for the
* reduced value to be valid. If `null_policy::EXCLUDE`, the reduced value is valid if any element
* in the segment is valid.
* @param init Initial value of each all
* @param stream CUDA stream used for device memory operations and kernel launches
* @param mr Device memory resource used to allocate the returned scalar's device memory
* @return Column of bool8 for the results of the segments
*/
std::unique_ptr<column> segmented_all(
column_view const& col,
device_span<size_type const> offsets,
data_type const output_dtype,
null_policy null_handling,
std::optional<std::reference_wrapper<scalar const>> init,
rmm::cuda_stream_view stream,
rmm::mr::device_memory_resource* mr = rmm::mr::get_current_device_resource());

} // namespace reduction
} // namespace cudf
Loading