Skip to content

Support empty segments in segmented bitmask reductions - #23689

Draft
vuule wants to merge 12 commits into
NVIDIA:mainfrom
vuule:segmented-bitmask-empty-segments
Draft

Support empty segments in segmented bitmask reductions#23689
vuule wants to merge 12 commits into
NVIDIA:mainfrom
vuule:segmented-bitmask-empty-segments

Conversation

@vuule

@vuule vuule commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Description

segmented_offset_bitmask_binop seeded 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_and overloads.

The kernel also indexed segment_offsets and destinations before the segment_id >= num_segments guard, 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 small expected_masks_per_segment gave negative sizes and an illegal memory access. It now clamps at zero, keeping empty segments.

Checklist

  • I am familiar with the Contributing Guidelines.
  • New or existing tests cover these changes.
  • The documentation is up to date with these changes.

@copy-pr-bot

copy-pr-bot Bot commented Aug 17, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@github-actions github-actions Bot added the libcudf Affects libcudf (C++/CUDA) code. label Aug 17, 2026
@vuule
vuule force-pushed the segmented-bitmask-empty-segments branch from 7b0eb55 to 76d938b Compare August 17, 2026 22:40
@vuule vuule changed the title Define empty segments in segmented bitmask reductions and fix the benchmark's segment generator Support empty segments in segmented bitmask reductions Aug 17, 2026
@vuule
vuule marked this pull request as ready for review August 17, 2026 22:52
@vuule
vuule requested a review from a team as a code owner August 17, 2026 22:52
@coderabbitai

coderabbitai Bot commented Aug 17, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: c9c3e6e2-ea5f-4665-9a50-8344b257841a

📥 Commits

Reviewing files that changed from the base of the PR and between dbf991d and 76d938b.

📒 Files selected for processing (3)
  • cpp/benchmarks/bitmask/bitmask_and.cpp
  • cpp/include/cudf/detail/null_mask.cuh
  • cpp/tests/bitmask/bitmask_tests.cpp

Included review availability: Your plan includes up to 12 reviews per rolling hour; 11 remain after this review.


📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • Improved segmented bitmask operations to correctly handle empty segments, including leading, trailing, and interior gaps.
    • Added validation for invalid segment offsets, such as decreasing or out-of-range values.
    • Ensured empty segments produce the correct identity mask and null counts.
  • Tests

    • Added coverage for empty segments and invalid offset handling.

Walkthrough

Changes

The 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

Layer / File(s) Summary
Identity-aware kernel and validation
cpp/include/cudf/detail/null_mask.cuh
Segmented bitmask functions accept an identity value, validate non-decreasing in-bounds offsets, and initialize empty destinations with the identity.
Empty-segment benchmark generation
cpp/benchmarks/bitmask/bitmask_and.cpp
Generated segment sizes are clamped to zero, with headers added for the generation and scan operations.
Empty-segment and offset validation tests
cpp/tests/bitmask/bitmask_tests.cpp
Tests cover leading, interior, and trailing empty segments, identity masks, null counts, decreasing offsets, and out-of-range offsets.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to 76d93

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: bdice

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The description clearly explains support for empty segments, identity-based reduction, offset validation, and benchmark fixes.
Title check ✅ Passed The title clearly and concisely summarizes the primary change: support for empty segments in segmented bitmask reductions.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@vuule
vuule marked this pull request as draft August 17, 2026 23:01
Comment thread cpp/benchmarks/bitmask/bitmask_and.cpp Outdated
Comment thread cpp/include/cudf/detail/null_mask.cuh Outdated
Comment thread cpp/include/cudf/detail/null_mask.cuh Outdated
…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.
@vuule
vuule force-pushed the segmented-bitmask-empty-segments branch from 76d938b to 9b5cc7a Compare August 17, 2026 23:52
@vuule vuule added bug Something isn't working non-breaking Non-breaking change labels Aug 18, 2026
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; }

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

exit before reading from segment_offsets

@vuule

vuule commented Aug 18, 2026

Copy link
Copy Markdown
Contributor Author

/ok to test 400bf84

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working libcudf Affects libcudf (C++/CUDA) code. non-breaking Non-breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants