Support empty segments in segmented bitmask reductions - #23689
Conversation
7b0eb55 to
76d938b
Compare
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Enterprise Run ID: 📒 Files selected for processing (3)
Included review availability: Your plan includes up to 12 reviews per rolling hour; 11 remain after this review. 📝 WalkthroughSummary by CodeRabbit
WalkthroughChangesThe segmented bitmask API now supports identity values, empty segments, and offset validation. The benchmark generates empty segments safely, and tests cover identity behavior and invalid offsets. Segmented bitmask operations
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: ⚪ Minimal · up to The change is localized to segmented bitmask reduction behavior and its tests and benchmark inputs; no actionable merge-blocking risk remains after normal checks and review. Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
Comment |
…ity seed Seeding each segment's reduction with the identity of the binary operator, instead of loading the segment's first mask, gives an empty segment a well defined result (an all-valid destination mask, null count zero) and removes the read of sources[segment_start] that a segment with no masks would otherwise perform out of bounds. Also validate that segment offsets are non-decreasing and within the mask array, and stop the bitmask benchmark's segment size generator from drawing negative sizes, which produced non-monotonic offsets and an illegal memory access for a small expected_masks_per_segment.
76d938b to
9b5cc7a
Compare
…ty-segments # Conflicts: # cpp/tests/bitmask/bitmask_tests.cpp
| auto const segment_id = cudf::detail::grid_1d::global_thread_id() / warp.size(); | ||
| auto const segment_id = cudf::detail::grid_1d::global_thread_id() / warp.size(); | ||
|
|
||
| if (segment_id >= num_segments) { return; } |
There was a problem hiding this comment.
exit before reading from segment_offsets
|
/ok to test 400bf84 |
Description
segmented_offset_bitmask_binopseeded each segment's reduction by loading the segment's first mask,sources[segment_start], before knowing whether the segment contains any masks. An empty segment therefore had no defined result and read a mask it does not own; for a trailing empty segment, that read is past the end of the mask array.With this PR, seeding is done with the identity of the binary operator. An empty segment then means the identity, which for bitwise AND is an all-valid mask with a null count of zero; this is now documented on the public
segmented_bitmask_andoverloads.The kernel also indexed
segment_offsetsanddestinationsbefore thesegment_id >= num_segmentsguard, which the excess warps of the last block do whenever the segment count is not a multiple of the warps per block; those loads now happen after the guard.Segment offsets are additionally validated as non-decreasing and within the mask array, since a decreasing pair leaves a segment's bounds meaningless. The bitmask benchmark's segment size generator was producing exactly that: it truncated draws from an unbounded normal distribution into
size_type, so a smallexpected_masks_per_segmentgave negative sizes and an illegal memory access. It now clamps at zero, keeping empty segments.Checklist