Skip to content

Commit 2f06c8e

Browse files
authored
Merge branch 'main' into fea/pylibcudf/gpumemoryview-slicing
2 parents e29dffb + 969575e commit 2f06c8e

14 files changed

Lines changed: 512 additions & 157 deletions

cpp/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,6 +1008,14 @@ add_library(
10081008
src/stream_compaction/apply_boolean_mask.cu
10091009
src/stream_compaction/distinct.cu
10101010
src/stream_compaction/distinct_helpers.cu
1011+
src/stream_compaction/distinct_helpers_flat_nan_equal_any.cu
1012+
src/stream_compaction/distinct_helpers_flat_nan_equal_ordered.cu
1013+
src/stream_compaction/distinct_helpers_flat_nan_unequal_any.cu
1014+
src/stream_compaction/distinct_helpers_flat_nan_unequal_ordered.cu
1015+
src/stream_compaction/distinct_helpers_nested_nan_equal_any.cu
1016+
src/stream_compaction/distinct_helpers_nested_nan_equal_ordered.cu
1017+
src/stream_compaction/distinct_helpers_nested_nan_unequal_any.cu
1018+
src/stream_compaction/distinct_helpers_nested_nan_unequal_ordered.cu
10111019
src/stream_compaction/drop_nans.cu
10121020
src/stream_compaction/drop_nulls.cu
10131021
src/stream_compaction/filter/filter.cu

cpp/src/hash/murmurhash3_x86_32.cu

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,26 @@
44
*/
55
#include "murmurhash3_x86_32.cuh"
66

7+
#include <cudf/column/column.hpp>
78
#include <cudf/column/column_factories.hpp>
89
#include <cudf/detail/nvtx/ranges.hpp>
910
#include <cudf/detail/row_operator/hashing.cuh>
11+
#include <cudf/detail/row_operator/preprocessed_table.cuh>
12+
#include <cudf/hashing.hpp>
1013
#include <cudf/hashing/detail/hashing.hpp>
1114
#include <cudf/hashing/detail/murmurhash3_x86_32.cuh>
15+
#include <cudf/table/table_view.hpp>
16+
#include <cudf/types.hpp>
1217
#include <cudf/utilities/error.hpp>
1318

1419
#include <rmm/cuda_stream_view.hpp>
20+
#include <rmm/resource_ref.hpp>
1521

1622
#include <cub/device/device_for.cuh>
1723

24+
#include <cstdint>
25+
#include <memory>
26+
1827
namespace cudf {
1928
namespace hashing {
2029
namespace detail {

cpp/src/stream_compaction/distinct.cu

Lines changed: 56 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,36 @@
11
/*
2-
* SPDX-FileCopyrightText: Copyright (c) 2019-2025, NVIDIA CORPORATION.
2+
* SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

66
#include "distinct_helpers.hpp"
7+
#include "hash/murmurhash3_x86_32.cuh"
78

8-
#include <cudf/column/column_view.hpp>
9+
#include <cudf/column/column.hpp>
10+
#include <cudf/copying.hpp>
911
#include <cudf/detail/cuco_helpers.hpp>
1012
#include <cudf/detail/gather.hpp>
11-
#include <cudf/detail/iterator.cuh>
1213
#include <cudf/detail/nvtx/ranges.hpp>
1314
#include <cudf/detail/row_operator/equality.cuh>
1415
#include <cudf/detail/row_operator/hashing.cuh>
1516
#include <cudf/detail/stream_compaction.hpp>
17+
#include <cudf/hashing.hpp>
18+
#include <cudf/stream_compaction.hpp>
1619
#include <cudf/table/table.hpp>
1720
#include <cudf/table/table_view.hpp>
1821
#include <cudf/types.hpp>
1922
#include <cudf/utilities/memory_resource.hpp>
2023

2124
#include <rmm/cuda_stream_view.hpp>
25+
#include <rmm/device_buffer.hpp>
2226
#include <rmm/device_uvector.hpp>
2327
#include <rmm/mr/polymorphic_allocator.hpp>
28+
#include <rmm/resource_ref.hpp>
2429

30+
#include <cuco/types.cuh>
31+
32+
#include <memory>
33+
#include <type_traits>
2534
#include <utility>
2635
#include <vector>
2736

@@ -85,24 +94,54 @@ rmm::device_uvector<size_type> distinct_indices(table_view const& input,
8594
auto const row_hash = cudf::detail::row::hash::row_hasher(preprocessed_input);
8695
auto const row_equal = cudf::detail::row::equality::self_comparator(preprocessed_input);
8796

88-
auto const helper_func = [&](auto const& d_equal) {
97+
auto const helper_func = [&](auto const& d_equal, auto const& d_hash, auto const& reduce_func) {
8998
using RowEqual = std::decay_t<decltype(d_equal)>;
90-
auto set = distinct_set_t<RowEqual>{num_rows,
91-
0.5, // desired load factor
92-
cuco::empty_key{cudf::detail::CUDF_SIZE_TYPE_SENTINEL},
93-
d_equal,
94-
{row_hash.device_hasher(has_nulls)},
95-
{},
96-
{},
97-
rmm::mr::polymorphic_allocator<char>{},
98-
stream.value()};
99-
return detail::reduce_by_row(set, num_rows, keep, stream, mr);
99+
using RowHash = std::decay_t<decltype(d_hash)>;
100+
auto set =
101+
distinct_set_t<RowEqual, RowHash>{num_rows,
102+
0.5, // desired load factor
103+
cuco::empty_key{cudf::detail::CUDF_SIZE_TYPE_SENTINEL},
104+
d_equal,
105+
d_hash,
106+
{},
107+
{},
108+
rmm::mr::polymorphic_allocator<char>{},
109+
stream.value()};
110+
return reduce_func(set);
100111
};
101112

102-
if (cudf::detail::has_nested_columns(input)) {
103-
return dispatch_row_equal<true>(nulls_equal, nans_equal, has_nulls, row_equal, helper_func);
113+
if (has_nested_columns) {
114+
if (keep == duplicate_keep_option::KEEP_ANY) {
115+
auto const hashes =
116+
cudf::hashing::detail::murmurhash3_x86_32(preprocessed_input,
117+
num_rows,
118+
cudf::DEFAULT_HASH_SEED,
119+
stream,
120+
cudf::get_current_device_resource_ref());
121+
auto const d_hash = distinct_precomputed_hash{hashes->view().data<hash_value_type>()};
122+
return dispatch_row_equal<true>(
123+
nulls_equal, nans_equal, has_nulls, row_equal, [&](auto const& d_equal) {
124+
return helper_func(d_equal, d_hash, [&](auto& set) {
125+
return detail::reduce_by_row_keep_any(set, num_rows, stream, mr);
126+
});
127+
});
128+
}
129+
130+
auto const d_hash = row_hash.device_hasher(has_nulls);
131+
return dispatch_row_equal<true>(
132+
nulls_equal, nans_equal, has_nulls, row_equal, [&](auto const& d_equal) {
133+
return helper_func(d_equal, d_hash, [&](auto& set) {
134+
return detail::reduce_by_row_keep_first_last_none(set, num_rows, keep, stream, mr);
135+
});
136+
});
104137
} else {
105-
return dispatch_row_equal<false>(nulls_equal, nans_equal, has_nulls, row_equal, helper_func);
138+
auto const d_hash = row_hash.device_hasher(has_nulls);
139+
return dispatch_row_equal<false>(
140+
nulls_equal, nans_equal, has_nulls, row_equal, [&](auto const& d_equal) {
141+
return helper_func(d_equal, d_hash, [&](auto& set) {
142+
return detail::reduce_by_row(set, num_rows, keep, stream, mr);
143+
});
144+
});
106145
}
107146
}
108147

Lines changed: 31 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1,136 +1,67 @@
11
/*
2-
* SPDX-FileCopyrightText: Copyright (c) 2022-2026, NVIDIA CORPORATION.
2+
* SPDX-FileCopyrightText: Copyright (c) 2022-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

66
#include "distinct_helpers.hpp"
77

88
#include <cudf/detail/algorithms/copy_if.cuh>
9+
#include <cudf/stream_compaction.hpp>
10+
#include <cudf/types.hpp>
11+
#include <cudf/utilities/memory_resource.hpp>
12+
13+
#include <rmm/cuda_stream_view.hpp>
14+
#include <rmm/exec_policy.hpp>
15+
#include <rmm/resource_ref.hpp>
916

1017
#include <cuda/functional>
1118
#include <cuda/iterator>
12-
#include <cuda/std/atomic>
1319
#include <cuda/std/iterator>
20+
#include <thrust/uninitialized_fill.h>
1421

1522
namespace cudf::detail {
1623

17-
template <typename RowEqual>
18-
rmm::device_uvector<size_type> reduce_by_row(distinct_set_t<RowEqual>& set,
19-
size_type num_rows,
20-
duplicate_keep_option keep,
21-
rmm::cuda_stream_view stream,
22-
rmm::device_async_resource_ref mr)
24+
void initialize_reduction_results(size_type* results,
25+
size_type num_rows,
26+
duplicate_keep_option keep,
27+
rmm::cuda_stream_view stream)
2328
{
24-
auto output_indices = rmm::device_uvector<size_type>(num_rows, stream, mr);
25-
26-
// If we don't care about order, just gather indices of distinct keys taken from set.
27-
if (keep == duplicate_keep_option::KEEP_ANY) {
28-
auto const iter = cuda::counting_iterator<cudf::size_type>{0};
29-
set.insert_async(iter, iter + num_rows, stream.value());
30-
auto const output_end = set.retrieve_all(output_indices.begin(), stream.value());
31-
output_indices.resize(cuda::std::distance(output_indices.begin(), output_end), stream);
32-
return output_indices;
33-
}
34-
35-
auto reduction_results = rmm::device_uvector<size_type>(num_rows, stream, mr);
3629
thrust::uninitialized_fill(
3730
rmm::exec_policy_nosync(stream, cudf::get_current_device_resource_ref()),
38-
reduction_results.begin(),
39-
reduction_results.end(),
31+
results,
32+
results + num_rows,
4033
reduction_init_value(keep));
34+
}
4135

42-
auto set_ref = set.ref(cuco::op::insert_and_find);
43-
44-
thrust::for_each(rmm::exec_policy_nosync(stream, cudf::get_current_device_resource_ref()),
45-
cuda::counting_iterator<cudf::size_type>{0},
46-
cuda::counting_iterator{num_rows},
47-
[set_ref, keep, reduction_results = reduction_results.begin()] __device__(
48-
size_type const idx) mutable {
49-
auto const [inserted_idx_ptr, _] = set_ref.insert_and_find(idx);
50-
51-
auto ref = cuda::atomic_ref<size_type, cuda::thread_scope_device>{
52-
reduction_results[*inserted_idx_ptr]};
53-
if (keep == duplicate_keep_option::KEEP_FIRST) {
54-
// Store the smallest index of all rows that are equal.
55-
ref.fetch_min(idx, cuda::memory_order_relaxed);
56-
} else if (keep == duplicate_keep_option::KEEP_LAST) {
57-
// Store the greatest index of all rows that are equal.
58-
ref.fetch_max(idx, cuda::memory_order_relaxed);
59-
} else {
60-
// Count the number of rows in each group of rows that are compared equal.
61-
ref.fetch_add(size_type{1}, cuda::memory_order_relaxed);
62-
}
63-
});
64-
65-
auto const map_end = [&] {
36+
size_type copy_reduction_results(size_type const* results,
37+
size_type num_rows,
38+
size_type* output,
39+
duplicate_keep_option keep,
40+
rmm::cuda_stream_view stream)
41+
{
42+
auto const output_end = [&] {
6643
if (keep == duplicate_keep_option::KEEP_NONE) {
67-
// Reduction results with `KEEP_NONE` are either group sizes of equal rows, or `0`.
68-
// Thus, we only output index of the rows in the groups having group size of `1`.
44+
// KEEP_NONE stores group sizes; retain only singleton groups.
6945
return cudf::detail::copy_if(
7046
cuda::counting_iterator<size_type>{0},
7147
cuda::counting_iterator<size_type>{num_rows},
72-
output_indices.begin(),
48+
output,
7349
cuda::proclaim_return_type<bool>(
74-
[reduction_results = reduction_results.begin()] __device__(auto const idx) {
75-
return reduction_results[idx] == size_type{1};
76-
}),
50+
[results] __device__(auto const idx) { return results[idx] == size_type{1}; }),
7751
stream);
7852
}
7953

80-
// Reduction results with `KEEP_FIRST` and `KEEP_LAST` are row indices of the first/last row in
81-
// each group of equal rows (which are the desired output indices), or the value given by
82-
// `reduction_init_value()`.
54+
// KEEP_FIRST and KEEP_LAST store desired row indices or the mode's initial marker.
8355
return cudf::detail::copy_if(
84-
reduction_results.begin(),
85-
reduction_results.end(),
86-
output_indices.begin(),
56+
results,
57+
results + num_rows,
58+
output,
8759
cuda::proclaim_return_type<bool>([init_value = reduction_init_value(keep)] __device__(
8860
auto const idx) { return idx != init_value; }),
8961
stream);
9062
}();
9163

92-
output_indices.resize(cuda::std::distance(output_indices.begin(), map_end), stream);
93-
return output_indices;
64+
return cuda::std::distance(output, output_end);
9465
}
9566

96-
template rmm::device_uvector<size_type> reduce_by_row(
97-
distinct_set_t<cudf::detail::row::equality::device_row_comparator<
98-
false,
99-
cudf::nullate::DYNAMIC,
100-
cudf::detail::row::equality::nan_equal_physical_equality_comparator>>& set,
101-
size_type num_rows,
102-
duplicate_keep_option keep,
103-
rmm::cuda_stream_view stream,
104-
rmm::device_async_resource_ref mr);
105-
106-
template rmm::device_uvector<size_type> reduce_by_row(
107-
distinct_set_t<cudf::detail::row::equality::device_row_comparator<
108-
true,
109-
cudf::nullate::DYNAMIC,
110-
cudf::detail::row::equality::nan_equal_physical_equality_comparator>>& set,
111-
size_type num_rows,
112-
duplicate_keep_option keep,
113-
rmm::cuda_stream_view stream,
114-
rmm::device_async_resource_ref mr);
115-
116-
template rmm::device_uvector<size_type> reduce_by_row(
117-
distinct_set_t<cudf::detail::row::equality::device_row_comparator<
118-
false,
119-
cudf::nullate::DYNAMIC,
120-
cudf::detail::row::equality::physical_equality_comparator>>& set,
121-
size_type num_rows,
122-
duplicate_keep_option keep,
123-
rmm::cuda_stream_view stream,
124-
rmm::device_async_resource_ref mr);
125-
126-
template rmm::device_uvector<size_type> reduce_by_row(
127-
distinct_set_t<cudf::detail::row::equality::device_row_comparator<
128-
true,
129-
cudf::nullate::DYNAMIC,
130-
cudf::detail::row::equality::physical_equality_comparator>>& set,
131-
size_type num_rows,
132-
duplicate_keep_option keep,
133-
rmm::cuda_stream_view stream,
134-
rmm::device_async_resource_ref mr);
135-
13667
} // namespace cudf::detail

0 commit comments

Comments
 (0)