-
Notifications
You must be signed in to change notification settings - Fork 932
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
Nested struct binop comparison #9452
Changes from 78 commits
262c2a2
a865fe0
ce4440c
1472c5f
4a31fb6
ce2d727
10c95f9
12cd09e
b6fa590
d64c1f9
57900da
f170149
de129a1
5e84e89
b632192
4266f8c
367ec07
5a1f016
1f29168
1d6263e
97bd5e1
48d0355
6cf0e16
9ec2acf
3016abf
b2a7973
191da69
2cf2b28
2b634c4
19f1afb
f316a0a
c684ef1
7f36241
8cf0660
2abefd5
8cc05e2
1bde152
470acfe
ce21d90
83fa370
2b77739
de09cec
8ad9545
251d607
703aaf8
43e451b
9ec4a41
201a89b
cc164d6
1bb1534
6c6c8ab
42e58ae
475c896
1dae04a
62224cf
a35600d
b6f0397
fcc1dd2
5abf2a8
9d50ac0
8628c24
a836a96
a537805
f7af41f
1af4643
4d929d9
2298988
bf1c6ee
5d87db2
fd716b9
2dd2045
7ba960e
84833e7
a944b4f
4d197ea
08092fe
d8986c5
548dcf1
1dd1159
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -16,6 +16,7 @@ | |||||||||||||||
|
||||||||||||||||
#pragma once | ||||||||||||||||
|
||||||||||||||||
#include <cudf/binaryop.hpp> | ||||||||||||||||
#include <cudf/column/column_device_view.cuh> | ||||||||||||||||
#include <cudf/detail/hashing.hpp> | ||||||||||||||||
#include <cudf/detail/iterator.cuh> | ||||||||||||||||
|
@@ -45,6 +46,7 @@ | |||||||||||||||
#include <utility> | ||||||||||||||||
|
||||||||||||||||
namespace cudf { | ||||||||||||||||
|
||||||||||||||||
namespace experimental { | ||||||||||||||||
|
||||||||||||||||
/** | ||||||||||||||||
|
@@ -68,28 +70,31 @@ struct dispatch_void_if_nested { | |||||||||||||||
}; | ||||||||||||||||
|
||||||||||||||||
namespace row { | ||||||||||||||||
|
||||||||||||||||
namespace lexicographic { | ||||||||||||||||
|
||||||||||||||||
/** | ||||||||||||||||
* @brief Computes whether one row is lexicographically *less* than another row. | ||||||||||||||||
* @brief Computes the lexicographic comparison between 2 rows. | ||||||||||||||||
* | ||||||||||||||||
* Lexicographic ordering is determined by: | ||||||||||||||||
* - Two rows are compared element by element. | ||||||||||||||||
* - The first mismatching element defines which row is lexicographically less | ||||||||||||||||
* or greater than the other. | ||||||||||||||||
* - If the rows are compared without mismatched elements, the rows are equivalent | ||||||||||||||||
* | ||||||||||||||||
* | ||||||||||||||||
* Lexicographic ordering is exactly equivalent to doing an alphabetical sort of | ||||||||||||||||
* two words, for example, `aac` would be *less* than (or precede) `abb`. The | ||||||||||||||||
* second letter in both words is the first non-equal letter, and `a < b`, thus | ||||||||||||||||
* `aac < abb`. | ||||||||||||||||
* | ||||||||||||||||
* @tparam Nullate A cudf::nullate type describing whether to check for nulls. | ||||||||||||||||
* @tparam NanConfig default configuration nans are equal, if set to true triggers specialized IEEE | ||||||||||||||||
* 754 compliant nan handling | ||||||||||||||||
*/ | ||||||||||||||||
template <typename Nullate> | ||||||||||||||||
template <typename Nullate, bool NanConfig = false> | ||||||||||||||||
class device_row_comparator { | ||||||||||||||||
friend class self_comparator; | ||||||||||||||||
|
||||||||||||||||
// friend class self_comparator; | ||||||||||||||||
public: // needs to be removed, pending strict typing for indices | ||||||||||||||||
/** | ||||||||||||||||
* @brief Construct a function object for performing a lexicographic | ||||||||||||||||
* comparison between the rows of two tables. | ||||||||||||||||
|
@@ -139,13 +144,20 @@ class device_row_comparator { | |||||||||||||||
* @param null_precedence Indicates how null values are ordered with other values | ||||||||||||||||
* @param depth The depth of the column if part of a nested column @see | ||||||||||||||||
* preprocessed_table::depths | ||||||||||||||||
* @param nan_result Specifies what value should be returned if either element is `nan` | ||||||||||||||||
*/ | ||||||||||||||||
__device__ element_comparator(Nullate check_nulls, | ||||||||||||||||
column_device_view lhs, | ||||||||||||||||
column_device_view rhs, | ||||||||||||||||
null_order null_precedence = null_order::BEFORE, | ||||||||||||||||
int depth = 0) | ||||||||||||||||
: _lhs{lhs}, _rhs{rhs}, _nulls{check_nulls}, _null_precedence{null_precedence}, _depth{depth} | ||||||||||||||||
int depth = 0, | ||||||||||||||||
weak_ordering nan_result = weak_ordering::EQUIVALENT) | ||||||||||||||||
: _lhs{lhs}, | ||||||||||||||||
_rhs{rhs}, | ||||||||||||||||
_check_nulls{check_nulls}, | ||||||||||||||||
_null_precedence{null_precedence}, | ||||||||||||||||
_depth{depth}, | ||||||||||||||||
_nan_result{nan_result} | ||||||||||||||||
{ | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
|
@@ -162,7 +174,7 @@ class device_row_comparator { | |||||||||||||||
__device__ cuda::std::pair<weak_ordering, int> operator()( | ||||||||||||||||
size_type const lhs_element_index, size_type const rhs_element_index) const noexcept | ||||||||||||||||
{ | ||||||||||||||||
if (_nulls) { | ||||||||||||||||
if (_check_nulls) { | ||||||||||||||||
bool const lhs_is_null{_lhs.is_null(lhs_element_index)}; | ||||||||||||||||
bool const rhs_is_null{_rhs.is_null(rhs_element_index)}; | ||||||||||||||||
|
||||||||||||||||
|
@@ -171,8 +183,12 @@ class device_row_comparator { | |||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
return cuda::std::pair(relational_compare(_lhs.element<Element>(lhs_element_index), | ||||||||||||||||
_rhs.element<Element>(rhs_element_index)), | ||||||||||||||||
return cuda::std::pair(NanConfig | ||||||||||||||||
? relational_compare(_lhs.element<Element>(lhs_element_index), | ||||||||||||||||
_rhs.element<Element>(rhs_element_index), | ||||||||||||||||
_nan_result) | ||||||||||||||||
: relational_compare(_lhs.element<Element>(lhs_element_index), | ||||||||||||||||
_rhs.element<Element>(rhs_element_index)), | ||||||||||||||||
std::numeric_limits<int>::max()); | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
|
@@ -211,29 +227,32 @@ class device_row_comparator { | |||||||||||||||
++depth; | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
auto const comparator = element_comparator{_nulls, lcol, rcol, _null_precedence, depth}; | ||||||||||||||||
auto const comparator = | ||||||||||||||||
element_comparator{_check_nulls, lcol, rcol, _null_precedence, depth, _nan_result}; | ||||||||||||||||
return cudf::type_dispatcher<dispatch_void_if_nested>( | ||||||||||||||||
lcol.type(), comparator, lhs_element_index, rhs_element_index); | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
private: | ||||||||||||||||
column_device_view const _lhs; | ||||||||||||||||
column_device_view const _rhs; | ||||||||||||||||
Nullate const _nulls; | ||||||||||||||||
Nullate const _check_nulls; | ||||||||||||||||
null_order const _null_precedence; | ||||||||||||||||
int const _depth; | ||||||||||||||||
weak_ordering _nan_result; | ||||||||||||||||
}; | ||||||||||||||||
|
||||||||||||||||
public: | ||||||||||||||||
/** | ||||||||||||||||
* @brief Checks whether the row at `lhs_index` in the `lhs` table compares | ||||||||||||||||
* lexicographically less than the row at `rhs_index` in the `rhs` table. | ||||||||||||||||
* lexicographically less, greater, or equivalent to the row at `rhs_index` in the `rhs` table. | ||||||||||||||||
* | ||||||||||||||||
* @param lhs_index The index of row in the `lhs` table to examine | ||||||||||||||||
* @param rhs_index The index of the row in the `rhs` table to examine | ||||||||||||||||
* @return `true` if row from the `lhs` table compares less than row in the `rhs` table | ||||||||||||||||
* @return weak ordering comparison of the row in the `lhs` table relative to the row in the `rhs` | ||||||||||||||||
* table | ||||||||||||||||
*/ | ||||||||||||||||
__device__ bool operator()(size_type const lhs_index, size_type const rhs_index) const noexcept | ||||||||||||||||
__device__ weak_ordering operator()(size_type lhs_index, size_type rhs_index) const noexcept | ||||||||||||||||
{ | ||||||||||||||||
int last_null_depth = std::numeric_limits<int>::max(); | ||||||||||||||||
for (size_type i = 0; i < _lhs.num_columns(); ++i) { | ||||||||||||||||
|
@@ -247,17 +266,31 @@ class device_row_comparator { | |||||||||||||||
_null_precedence.has_value() ? (*_null_precedence)[i] : null_order::BEFORE; | ||||||||||||||||
|
||||||||||||||||
auto const comparator = | ||||||||||||||||
element_comparator{_check_nulls, _lhs.column(i), _rhs.column(i), null_precedence, depth}; | ||||||||||||||||
NanConfig ? element_comparator{_check_nulls, | ||||||||||||||||
_lhs.column(i), | ||||||||||||||||
_rhs.column(i), | ||||||||||||||||
null_precedence, | ||||||||||||||||
depth, | ||||||||||||||||
ascending ? weak_ordering::GREATER : weak_ordering::LESS} | ||||||||||||||||
|
||||||||||||||||
: element_comparator{_check_nulls, | ||||||||||||||||
_lhs.column(i), | ||||||||||||||||
_rhs.column(i), | ||||||||||||||||
null_precedence, | ||||||||||||||||
depth, | ||||||||||||||||
weak_ordering::EQUIVALENT}; | ||||||||||||||||
|
||||||||||||||||
weak_ordering state; | ||||||||||||||||
cuda::std::tie(state, last_null_depth) = | ||||||||||||||||
cudf::type_dispatcher(_lhs.column(i).type(), comparator, lhs_index, rhs_index); | ||||||||||||||||
|
||||||||||||||||
if (state == weak_ordering::EQUIVALENT) { continue; } | ||||||||||||||||
|
||||||||||||||||
return state == (ascending ? weak_ordering::LESS : weak_ordering::GREATER); | ||||||||||||||||
return ascending | ||||||||||||||||
? state | ||||||||||||||||
: (state == weak_ordering::GREATER ? weak_ordering::LESS : weak_ordering::GREATER); | ||||||||||||||||
} | ||||||||||||||||
return false; | ||||||||||||||||
return weak_ordering::EQUIVALENT; | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
private: | ||||||||||||||||
|
@@ -269,6 +302,42 @@ class device_row_comparator { | |||||||||||||||
std::optional<device_span<null_order const>> const _null_precedence; | ||||||||||||||||
}; // class device_row_comparator | ||||||||||||||||
|
||||||||||||||||
/** | ||||||||||||||||
* @brief Wraps and interprets the result of templated Comparator that returns a weak_ordering. | ||||||||||||||||
* Returns true if the weak_ordering matches any of the templated values. | ||||||||||||||||
* | ||||||||||||||||
* Note that this should never be used with only `weak_ordering::EQUIVALENT`. | ||||||||||||||||
* An equality comparator should be used instead for optimal performance. | ||||||||||||||||
* | ||||||||||||||||
* @tparam Comparator generic comparator that returns a weak_ordering. | ||||||||||||||||
* @tparam values weak_ordering parameter pack of orderings to interpret as true | ||||||||||||||||
*/ | ||||||||||||||||
template <typename Comparator, weak_ordering... values> | ||||||||||||||||
struct weak_ordering_comparator_impl { | ||||||||||||||||
__device__ bool operator()(size_type const& lhs, size_type const& rhs) | ||||||||||||||||
Comment on lines
+315
to
+317
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can actually Double check that I'm using the right names here.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For reference, the compiler complains about |
||||||||||||||||
{ | ||||||||||||||||
weak_ordering const result = comparator(lhs, rhs); | ||||||||||||||||
return ((result == values) || ...); | ||||||||||||||||
} | ||||||||||||||||
Comparator comparator; | ||||||||||||||||
}; | ||||||||||||||||
|
||||||||||||||||
/** | ||||||||||||||||
* @brief Wraps and interprets the result of device_row_comparator, true if the result is | ||||||||||||||||
* weak_ordering::LESS meaning one row is lexicographically *less* than another row. | ||||||||||||||||
* | ||||||||||||||||
* @tparam Nullate A cudf::nullate type describing whether to check for nulls. | ||||||||||||||||
*/ | ||||||||||||||||
template <typename Nullate, bool NanConfig = false> | ||||||||||||||||
using less_comparator = | ||||||||||||||||
weak_ordering_comparator_impl<device_row_comparator<Nullate, NanConfig>, weak_ordering::LESS>; | ||||||||||||||||
|
||||||||||||||||
template <typename Nullate, bool NanConfig = false> | ||||||||||||||||
using less_equivalent_comparator = | ||||||||||||||||
weak_ordering_comparator_impl<device_row_comparator<Nullate, NanConfig>, | ||||||||||||||||
weak_ordering::LESS, | ||||||||||||||||
weak_ordering::EQUIVALENT>; | ||||||||||||||||
|
||||||||||||||||
struct preprocessed_table { | ||||||||||||||||
using table_device_view_owner = | ||||||||||||||||
std::invoke_result_t<decltype(table_device_view::create), table_view, rmm::cuda_stream_view>; | ||||||||||||||||
|
@@ -416,11 +485,11 @@ class self_comparator { | |||||||||||||||
* | ||||||||||||||||
* @tparam Nullate A cudf::nullate type describing whether to check for nulls. | ||||||||||||||||
*/ | ||||||||||||||||
template <typename Nullate> | ||||||||||||||||
device_row_comparator<Nullate> device_comparator(Nullate nullate = {}) const | ||||||||||||||||
template <typename Nullate, bool NanConfig = false> | ||||||||||||||||
less_comparator<Nullate, NanConfig> device_comparator(Nullate nullate = {}) const | ||||||||||||||||
{ | ||||||||||||||||
return device_row_comparator( | ||||||||||||||||
nullate, *d_t, *d_t, d_t->depths(), d_t->column_order(), d_t->null_precedence()); | ||||||||||||||||
return less_comparator<Nullate, NanConfig>{device_row_comparator<Nullate, NanConfig>( | ||||||||||||||||
nullate, *d_t, *d_t, d_t->depths(), d_t->column_order(), d_t->null_precedence())}; | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
private: | ||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's try to pull out the
NanConfig
and related changes into a separate PR.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#10870