-
Notifications
You must be signed in to change notification settings - Fork 912
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
Introduce utility function to calculate inputs to rolling_window #16305
base: branch-25.02
Are you sure you want to change the base?
Conversation
72f221b
to
9988fd9
Compare
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.
I think windows_utils.cu
should be in src/rolling
and not src/rolling/detail
Should the declarations still live in |
Yes. I don't think you need the |
Debugging some fencepost errors... |
Fixed, I was bitten by switch-fallthrough (so I replaced it with cascading if-else). |
cpp/src/rolling/window_utils.cu
Outdated
CUDF_EXPECTS(length.type().id() == type_to_id<OffsetType>(), | ||
"Length must have same the resolution as the input."); |
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.
This is a tighter requirement than strictly necessary. We just need it to be the case that we can add OffsetType
to T
(so I think it should be OK for example having a TIMESTAMP_MICROSECONDS
column and adding a DURATION_SECONDS
offset/length).
But to fully handle that I think one needs triple type-dispatch over the three-tuple of (input_type, length, offset)
, so I decided not to do that unless it turns out to be absolutely necessary.
cpp/src/rolling/window_utils.cu
Outdated
CUDF_EXPECTS(have_same_types(input, length), | ||
"Input column, length, and offset must have the same type."); |
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.
Similarly here, I think it would be OK if length
and offset
are addable to input
. But this is easier.
Using the example from #15119, we can see the improvement in computing the window bounds:
So we see that as the window gets bigger, the time compute the window bounds increases linearly in the window size. In contrast, with this new implementation:
So now the time to compute the window is a bit slower for a window size of 1, but much faster as the windows get bigger. |
@@ -48,5 +48,14 @@ std::unique_ptr<column> rolling_window(column_view const& input, | |||
rmm::cuda_stream_view stream, | |||
rmm::device_async_resource_ref mr); | |||
|
|||
std::pair<std::unique_ptr<column>, std::unique_ptr<column>> windows_from_offset( |
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.
Should we consider including an @brief
description here?
scalar const& length, | ||
scalar const& offset, | ||
window_type const window_type, | ||
bool only_preceding, |
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.
Can this also be a const
?
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.
I don't think we should make copy-by-value parameters like this const
.
This is not needed by the caller and provides too much limitation to the internal implementation.
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.
Point taken, @davidwendt. For my own understanding, should the preceding parameter (window_type
) be subject to the same convention?
Maybe it doesn't apply, since it isn't obviously an enum?
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.
IMO, I think that it should apply to this enum parameter as well.
Forgive me if this is a complete tangent: This utility is in service of computing the window bounds for range window queries? I was wondering if you'd already had a look at the grouped-range functions implemented in
Note that the window bounds are calculated separately, depending upon the ordering, null-placement, and the presence of the group-by columns. Edit: For clarity, this is in service of Spark's window-function SQL: SELECT SUM(dollars) OVER (
PARTITION BY dept_id
ORDER BY sale_date ASC
RANGE BETWEEN INTERVAL 7 DAYS PRECEDING AND 7 DAYS FOLLOWING ) AS two_week_earnings
... |
Deciding if this should slip to 24.10 |
Will retarget to 24.10 and look for opportunities to reuse or share the existing implementations. |
/** | ||
* @brief Indicates which endpoints a rolling window contains. | ||
*/ | ||
enum class window_type : int32_t { |
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.
Trivial nit: One wonders if we might use a more descriptive name for this type. Something like window_margin(_type)
?
Edit: I mention this because window_bounds
was initially named window_type
, then window_bounds_type
, and then window_bounds
.
Your openness to this is deeply appreciated. I'd be happy to assist. My current implementation certainly doesn't tackle open/closed margins, or negative range values. |
Both polars and pandas specify rolling window extents by providing a scalar window length, along with whether the interval is open, closed, left-half-open, or right-half-open, and (for polars) a scalar offset. We currently use a numba kernel to convert this information into the pair of `preceding_window` and `following_window` columns that are the arguments to `rolling_window`. This kernel has a few problems: - For large window extents it has poor performance scaling as O(n * window_size); - It doesn't support different end point handling; - Since pandas doesn't require it, it doesn't support computing `following_window` information; - If we want to use it in cudf-polars, it introduces another dependency (numba). To address these concerns, implement a utility function in libcudf that takes window length and offset and computes the matching preceding/following columns. This implementation exploits the fact that the column we are rolling over must be sorted in ascending order and uses `thrust::lower_bound` to provide an O(n log n) run time for all window sizes. We also now support all endpoint handling required for cudf-polars. This provides the infrastructure to work on addressing (at least partially): - rapidsai#12774 - rapidsai#14334 - rapidsai#15086 - rapidsai#15119 - rapidsai#15192
Modernise use of op_impl to omit unnecessary T template parameter.
e.g. thrust::less, not std::less.
7d55d4e
to
d9010db
Compare
Check out this pull request on See visual diffs & provide feedback on Jupyter Notebooks. Powered by ReviewNB |
Description
Both polars and pandas specify rolling window extents by providing a scalar window length, along with whether the interval is open, closed, left-half-open, or right-half-open, and (for polars) a scalar offset. We currently use a numba kernel to convert this information into the pair of
preceding_window
andfollowing_window
columns that are the arguments torolling_window
. This kernel has a few problems:center
parameter), it doesn't support computingfollowing_window
information;To address these concerns, implement a utility function in libcudf that takes window length and offset and computes the matching preceding/following columns. This implementation exploits the fact that the column we are rolling over must be sorted in ascending order and uses$\mathcal{O}(n \log n)$ run time for all window sizes. We also now support all endpoint handling required for cudf-polars.
thrust::lower_bound
to provide anThis provides the infrastructure to work on addressing (at least partially):
closed=
parameter for rolling window #15192Checklist