Skip to content

Forward-merge release/26.08 into main - #23390

Merged
gforsyth merged 22 commits into
mainfrom
release/26.08
Jul 27, 2026
Merged

Forward-merge release/26.08 into main#23390
gforsyth merged 22 commits into
mainfrom
release/26.08

Conversation

@rapids-bot

@rapids-bot rapids-bot Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Forward-merge triggered by push to release/26.08 that creates a PR to keep main up-to-date. If this PR is unable to be immediately merged due to conflicts, it will remain open for the team to manually merge. See forward-merger docs for more info.

Closes #23287.

The Glushkov eligibility checker previously rejected an `ACCEPT` item only when it appeared before the first character-consuming frontier item. This missed Thompson-priority frontiers such as `[LF, ACCEPT, CR-repeat]`, where a successful accept has higher priority than a later continuation. Flattening that ordering into Glushkov bit positions caused a reluctant `\r+?` delimiter to consume a second `\r`, producing greedy behavior in `split_record_re`.

This PR:

- rejects a Glushkov frontier whenever an `ACCEPT` item is followed by a later `CHAR_POS`, conservatively falling back to the Thompson engine;
- preserves safe frontiers that end in `ACCEPT`;
- adds `StringsSplitTest.SplitRecordRegexLazyQuantifier` to verify the delimiter length and resulting split records.

The change affects only patterns whose Thompson-priority ordering cannot be represented faithfully by the Glushkov fast path. Supported patterns continue to use Glushkov.

### Validation

- Focused `StringsSplitTest.SplitRecordRegexLazyQuantifier`: 1/1 passed.
- Focused regression with `LIBCUDF_DISABLE_GLUSHKOV=1`: 1/1 passed.
- Full `STRINGS_TEST`: 540/540 passed.
- Clean local `spark-rapids-jni` package using this cuDF checkout: `BUILD SUCCESS`; a second same-toolchain rebuild also completed successfully.
- NVIDIA/cudf-spark, Scala 2.13 / Spark 4.0.1, `RegularExpressionTranspilerSuite`: 97 succeeded, 0 failed, 6 pre-existing canceled tests; Maven `BUILD SUCCESS`. The original `string split fuzz - anchor focused` failure passed.

Authors:
  - David Wendt (https://github.com/davidwendt)

Approvers:
  - Muhammad Haseeb (https://github.com/mhaseeb123)
  - Yunsong Wang (https://github.com/PointKernel)
  - Vyas Ramasubramani (https://github.com/vyasr)
  - Igor Peshansky (https://github.com/igorpeshansky)

URL: #23381
@rapids-bot
rapids-bot Bot requested a review from a team as a code owner July 21, 2026 23:54
@rapids-bot
rapids-bot Bot requested review from lamarrr and ttnghia July 21, 2026 23:54
@rapids-bot

rapids-bot Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor Author

FAILURE - Unable to forward-merge due to an error, manual merge is necessary. Do not use the Resolve conflicts option in this PR, follow these instructions https://docs.rapids.ai/maintainers/forward-merger/

IMPORTANT: When merging this PR, do not use the auto-merger (i.e. the /merge comment). Instead, an admin must manually merge by changing the merging strategy to Create a Merge Commit. Otherwise, history will be lost and the branches become incompatible.

@github-actions github-actions Bot added the libcudf Affects libcudf (C++/CUDA) code. label Jul 21, 2026
…23366)

Split out of #23255 (5/6).

`GroupBy.agg` flattened a MultiIndex-column source's aggregation result to flat tuple labels instead of keeping hierarchical columns like pandas. Preserve the MultiIndex (and its per-level metadata) when the aggregation keeps the source's tuple labels; relabeling aggregations (`agg(new=(col, func))`) emit new flat labels, so the source's multi-level metadata is not attached to those.

Fixes 3 pandas-tests (`test_groupby_with_hier_columns`, `test_wrap_aggregated_output_multindex`, `test_multiindex_custom_func[<lambda>0]`); their xfail entries are removed. Attribution verified by running the node ids against an isolated build containing only this change (pass) and a clean build (fail).

Independent of the other #23255 split PRs; the unstack PR (4/6) depends on this one for two entangled tests.

Authors:
  - GALI PREM SAGAR (https://github.com/galipremsagar)

Approvers:
  - Vyas Ramasubramani (https://github.com/vyasr)

URL: #23366
@rapids-bot
rapids-bot Bot requested a review from a team as a code owner July 22, 2026 00:33
@rapids-bot
rapids-bot Bot requested review from Matt711 and mroeschke July 22, 2026 00:33
@github-actions github-actions Bot added Python Affects Python cuDF API. cudf.pandas Issues specific to cudf.pandas labels Jul 22, 2026
libcudf's SUM/PRODUCT scans promote narrow integers to 64-bit. pandas does the same for numpy dtypes (int8 -> int64, pandas GH#37493) but preserves masked extension dtypes (Int16 stays Int16, pandas GH#58811), wrapping on overflow. Cast the scan result back to the original dtype for masked integer inputs only.

Fixes 8 pandas-tests (`test_groupby_cumsum_mask[Int*/UInt*-True-3]`, `test_nan_in_cumsum_group_label`); their xfail entries are removed.

Authors:
  - GALI PREM SAGAR (https://github.com/galipremsagar)

Approvers:
  - Matthew Roeschke (https://github.com/mroeschke)

URL: #23299
@GPUtester GPUtester moved this to In Progress in cuDF Python Jul 22, 2026
…aitables (#23293)

To avoid cancellation in python leading to attempting to set a result on an already cancelled Future, use the new pattern introduced in rapidsai/rapidsmpf#1131

Authors:
  - Lawrence Mitchell (https://github.com/wence-)
  - Tom Augspurger (https://github.com/TomAugspurger)

Approvers:
  - Tom Augspurger (https://github.com/TomAugspurger)
  - Vyas Ramasubramani (https://github.com/vyasr)

URL: #23293
@rapids-bot
rapids-bot Bot requested review from a team as code owners July 22, 2026 02:12
Part of #22124

This PR rewrites the mixed inner/left/full joins as equality-then-filter: run the keys through `cudf::hash_join`, then apply the conditional predicate to the index pairs via a new `filter_join_indices` primitive (AST + JIT, plus `filter_join_indices_output_size`). `mixed_full_join` becomes a left join plus `finalize_full_join`.

This replaces the fused mixed-join kernels, reusing `hash_join` instead of duplicating it.

Authors:
  - Yunsong Wang (https://github.com/PointKernel)

Approvers:
  - Muhammad Haseeb (https://github.com/mhaseeb123)
  - Shruti Shivakumar (https://github.com/shrshi)
  - Nghia Truong (https://github.com/ttnghia)

URL: #23012
@rapids-bot
rapids-bot Bot requested a review from a team as a code owner July 22, 2026 05:57
@github-actions github-actions Bot added the CMake CMake build issue label Jul 22, 2026
…truct pre-filters for inner joins (#22996)

Add a streaming optimizer pass that attempts to pre-filter one side of an input to inner joins before actor-graph lowering. 

The pass uses existing dynamic-planning scan statistics and join metadata to determine where it is beneficial to push a semi-join against a join key onto the other side of a join.

The simplest example of such a rewrite is that we turn
```python
left.join(right, on="key", how="inner")
```
into, assuming we somehow determine that `right` is selective,
```python
(
    left.join(right.select("key"), on="key", how="semi")
    .join(right, on="key", how="inner")
)
```

The optimization pass handles the case where a "domain" key, used to provide the right-hand side of the semi join, is "simple" and derived directly from some input node, as well as the more complex case where a domain key is already constrained by some other semi-join filter.

Only inner joins are rewritten, and only if all the keys are simple column keys. If heuristics determine that simple keys are not selective, we also don't perform the rewrite.

Material results of this change running NDSH SF30K on 8xNVL4 nodes are (previous results come from the change in #22995):
* **Q5 doesn't OOM on 8 nodes anymore and improved runtime performance: 9.35s lukewarm, 5.14s hot** (previously 40.25s lukewarm, OOM on hot)
* Q9 unchanged performance or slight regression: 47.12s lukewarm, 32.68s hot (previously 43.63s lukewarm, 30.56s hot)

Authors:
  - Peter Andreas Entschev (https://github.com/pentschev)
  - Lawrence Mitchell (https://github.com/wence-)

Approvers:
  - Lawrence Mitchell (https://github.com/wence-)
  - Mads R. B. Kristensen (https://github.com/madsbk)
  - Tom Augspurger (https://github.com/TomAugspurger)

URL: #22996
@rapids-bot
rapids-bot Bot requested a review from a team as a code owner July 22, 2026 10:45
@github-actions github-actions Bot added the cudf-polars Issues specific to cudf-polars label Jul 22, 2026
Closes #23348

Fixes build/CI by linking RMM to cuDF testing libraries.

Authors:
  - Abigale Kim (https://github.com/abigalekim)

Approvers:
  - Kyle Edwards (https://github.com/KyleFromNVIDIA)
  - Muhammad Haseeb (https://github.com/mhaseeb123)
  - Bradley Dice (https://github.com/bdice)

URL: #23341
Closes #23178.

Fixes a lifetime hazard in Parquet statistics filtering where `stats_caster_base::host_column::to_device` could return while asynchronous copies were still reading buffers owned by the temporary host column. This keeps the host-owned value and null-mask buffers alive until the stream has consumed them, covering both fixed-width and string statistics.

Authors:
  - Aryan Srivastava (https://github.com/aryansri05)
  - https://github.com/nursexams-lgtm
  - Muhammad Haseeb (https://github.com/mhaseeb123)

Approvers:
  - Vukasin Milovanovic (https://github.com/vuule)
  - Muhammad Haseeb (https://github.com/mhaseeb123)
  - Basit Ayantunde (https://github.com/lamarrr)

URL: #23219
@jameslamb jameslamb mentioned this pull request Jul 22, 2026
3 tasks
We've observed some cudf-polars runs taking >1 hour to complete, while runs on different, but similar, hardware take <15 minutes.

We've resolved most of the outright hangs now. Under the assumption that it's preferable to wait for a job to complete rather than restarting, we'll bump the timeout here.

Authors:
  - Tom Augspurger (https://github.com/TomAugspurger)

Approvers:
  - Vyas Ramasubramani (https://github.com/vyasr)

URL: #23399
@rapids-bot
rapids-bot Bot requested a review from a team as a code owner July 22, 2026 16:58
@rapids-bot
rapids-bot Bot requested a review from jameslamb July 22, 2026 16:58
The `ci-imgs` change in rapidsai/ci-imgs#408 switched `citestwheel` images from CUDA `devel` to `base`, which no longer bundles `libcufile.so` with the container. Now we must install cuFile wheels in Python test environments that use CUDA wheels.

CUDA 12 uses `nvidia-cufile-cu12` with some caveats in the pinnings, because cuFile wheels weren't available until 12.6.3 so the `[cufile]` extra isn't reliable.

CUDA 13 uses the `cuda-toolkit[cufile]` extra.

Authors:
  - Bradley Dice (https://github.com/bdice)
  - Gil Forsyth (https://github.com/gforsyth)

Approvers:
  - Gil Forsyth (https://github.com/gforsyth)

URL: #23392
@rapids-bot
rapids-bot Bot requested a review from a team as a code owner July 22, 2026 17:06
@Matt711

Matt711 commented Jul 22, 2026

Copy link
Copy Markdown
Member

Working on the forward merge resolve PR

…3389)

Align the `java-build` and `java-gather` artifact set with what Maven Central requires for a release (main classifier JAR, sources.jar, javadoc.jar, POM).

Authors:
  - https://github.com/paul-aiyedun

Approvers:
  - Tim Liu (https://github.com/NvTimLiu)

URL: #23389
@rapids-bot
rapids-bot Bot requested a review from a team as a code owner July 22, 2026 17:33
@github-actions github-actions Bot added the Java Affects Java cuDF API. label Jul 22, 2026
galipremsagar and others added 11 commits July 22, 2026 22:24
#23365)

Split out of #23255 (2/6).

Rebuilding a frame's pandas columns `MultiIndex` from tuples re-sorts the levels and re-infers their dtypes, losing the exact source layout: unsorted explicit level orders (which change the behavior of pandas operations that work on level codes, e.g. legacy `stack(sort=True)` after a fast-to-slow conversion under `cudf.pandas`), categorical/object/int64 level dtypes (int64 levels with missing entries upcast to float64), and NaN column labels (fresh `float('nan')` objects hash unequal, so lookups miss).

- Prime the cached `to_pandas_index` with the exact source `pd.MultiIndex` at `DataFrame` construction and propagate it through accessor copies.
- Restore recorded per-level dtypes in `to_pandas_index` when the cast round-trips losslessly.
- Match NaN-containing column labels under pandas' all-NaNs-equal semantics.
- Read level dtypes off `MultiIndex.levels` (`get_level_values` materializes missing entries as NaN and upcasts), also for `cudf.MultiIndex` columns.
- Keep hierarchical columns through DataFrame binops when only level dtypes differ (restored `Int8` vs `int64` fails `Index.equals`).

Fixes 13 pandas-tests (constructor dict-NaN-key, concat keys with specific levels, groupby ordered multi-func aggregate, MultiIndex loc, and several `test_stack_unstack.py` cases); their xfail entries are removed. Attribution verified by running each node id against an isolated build containing only this change (pass) and a clean build (fail).

Independent of the other #23255 split PRs, but the stack (3/6) and unstack (4/6) PRs depend on this one.

Authors:
  - GALI PREM SAGAR (https://github.com/galipremsagar)

Approvers:
  - Vyas Ramasubramani (https://github.com/vyasr)

URL: #23365
This PR enables the experimental parquet reader to now also support retention vectors in addition to deletion vectors

Authors:
  - Muhammad Haseeb (https://github.com/mhaseeb123)

Approvers:
  - Vukasin Milovanovic (https://github.com/vuule)
  - Jihoon Son (https://github.com/jihoonson)

URL: #23402
## Summary

Contributes to #22312

Extends the JSONPath-like path used by `get_variant_field`/`extract_variant_field` to descend into array values via zero-based `[N]` index steps, in addition to the existing object-key descent. This enables extraction of array elements from Parquet VARIANT columns (e.g. `$.a[0]`, `$[0].field`).

Leading zeroes are allowed, whitespace characters are not.

Authors:
  - Vukasin Milovanovic (https://github.com/vuule)

Approvers:
  - Yunsong Wang (https://github.com/PointKernel)
  - Simon Eves (https://github.com/simoneves)
  - Abigale Kim (https://github.com/abigalekim)
  - Nghia Truong (https://github.com/ttnghia)

URL: #22895
Fix ORC root column statistics when an `orc_chunked_writer` receives multiple non-empty tables.

`persisted_statistics::persist` replaced `num_rows` on every write, so the root `numberOfValues` stored in the footer reflected only the final table. Accumulate the row count across writes instead, while retaining the existing early return for an empty current table.

This caused Spark ORC aggregate pushdown to return the number of output files instead of the row count for `COUNT` on a top-level struct written by the RAPIDS Accelerator. Related issue: NVIDIA/cudf-spark#15186.

Validation:

- Before the fix, `OrcChunkedWriterTest.RootStatisticsAccumulateRows` failed with root `number_of_values = 1`, expected `6`.
- After the fix, the targeted test passed.
- Full `ORC_TEST`: `197 tests from 36 test suites`, `197 passed`, `4 disabled`.

Authors:
  - Allen Xu (https://github.com/wjxiz1992)

Approvers:
  - Chong Gao (https://github.com/res-life)
  - Vukasin Milovanovic (https://github.com/vuule)
  - Muhammad Haseeb (https://github.com/mhaseeb123)

URL: #23118
These two nightly jobs were scheduled on the same (slow) runner and made it to ~95% before being timed out:

- https://github.com/rapidsai/cudf/actions/runs/29991014913/job/89153660965
- https://github.com/rapidsai/cudf/actions/runs/29991014913/job/89153660991

I've bumped the timeout slightly more.

Authors:
  - Tom Augspurger (https://github.com/TomAugspurger)

Approvers:
  - Lawrence Mitchell (https://github.com/wence-)
  - James Lamb (https://github.com/jameslamb)

URL: #23410
#23370)

Split out of #23255 (3/6), superseding it. **Depends on #23365 (MultiIndex column fidelity)** — 14 of the 28 un-xfailed pandas-tests need both fixes, so this PR's pandas-tests job goes green once #23365 merges.

- Resolve `level` positionally: integer column-level *names* no longer collide with level *positions* (pandas' `Index.get_level_values` resolves integers by name first, so frames with integer level names returned data from the wrong level).
- Validate out-of-bounds integer levels (`IndexError`) and duplicated level names (`ValueError`) with pandas' messages; negative out-of-bounds levels previously wrapped around silently.
- Build the stacked level keys from the column MultiIndex's own levels/codes so per-level dtypes survive: int64 levels with missing entries no longer upcast to float64, and categorical levels stay categorical through the pylibcudf `tile` step (which only sees codes).
- Emit stacked keys in appearance order, matching pandas. This replaces the argsort-based reordering, which misaligned column data for non-involution column permutations (e.g. a 3-cycle) and NaN keys; pandas legacy stack sorts multi-level keys by level *codes*, not values.
- Attach pandas-faithful levels/codes to the result index eagerly (the original index contributes its own levels/codes; flat indexes and the tiled level get appearance-order factorization) so a later `unstack` restores the original row/column order; the legacy `dropna` path preserves them by masking codes instead of gathering the index.

Fixes 28 pandas-tests; their xfail entries are removed. Three classic categorical unstack params are un-xfailed (fixed by this change together with #23365). Attribution verified per node id against isolated builds: 14 pass with only this change, 14 need this plus #23365.

Authors:
  - GALI PREM SAGAR (https://github.com/galipremsagar)

Approvers:
  - Matthew Murray (https://github.com/Matt711)

URL: #23370
Rather than asking for a fitting number of blocks for an size, just require
the user to provide the size of the filter directly. Since it must be a
multiple of the storage type, also offer an aligned_size utility that takes
an input and makes that happen.

Additionally, share the new cuco parametric filter policy across cudf and
cudf-streaming.

Authors:
  - Lawrence Mitchell (https://github.com/wence-)
  - Vyas Ramasubramani (https://github.com/vyasr)
  - Tom Augspurger (https://github.com/TomAugspurger)

Approvers:
  - Tom Augspurger (https://github.com/TomAugspurger)
  - Muhammad Haseeb (https://github.com/mhaseeb123)
  - Yunsong Wang (https://github.com/PointKernel)

URL: #23067
This changes the cudf-polars default configuration to disable the join filter pushdown rewrite added in
#22996. It can be re-enabled through an env var with CUDF_POLARS__EXECUTOR__JOIN_FILTER_PUSHDOWN=1, or through python by passing
`join_filter_pushdown=JoinFilterPushdownOptions()`

I'm proposing to disable this for the 26.08 release based on some slowdowns in our pds-h benchmarks at smaller scales (SF-1K on a single H100 GPU).

<img width="1694" height="391" alt="image" src="https://github.com/user-attachments/assets/67766d4c-6d35-4afc-9751-29a98344943b" />

Eventually, I think that the join filter pushdown optimization should be on by default. But I'd like to understand a bit more about the slowdowns observed in that benchmark before turning it on by default.

Authors:
  - Tom Augspurger (https://github.com/TomAugspurger)

Approvers:
  - Vyas Ramasubramani (https://github.com/vyasr)

URL: #23407
Split out of #23255 (4/6). **Depends on #23365 (fidelity), the stack PR (#23370), and #23366 (groupby agg)** — 8 of the 29 un-xfailed pandas-tests need those fixes too, so this PR's pandas-tests job goes green once they merge.

- Order result rows/columns by the removed level's codes (level order preserved, missing keys first) instead of sorted values with nulls last, by encoding the integer code columns instead of the level values.
- Propagate the source frame's column-axis level names into the result instead of hardcoding `None`; also fixes the `ValueError: Length of names must match number of levels` crash when unstacking MultiIndex-column frames.
- Promote integer source columns to float64 when the reshape introduces missing cells (pandas' block semantics), gated on `mode.pandas_compatible`; `pivot_table`/`crosstab` opt out via a module-private `_unstack` parameter when `fill_value` fills the cells afterwards.
- Preserve unused categories of the removed level in the result's column levels (pandas GH 17845); also fixes a libcudf `Column sizes don't match` crash for indexes with unused categorical categories.
- Validate the level on flat-index frames (`KeyError`) and duplicated index names (`ValueError`) like pandas; `pivot` with `values=` drops the original columns-axis names.

Fixes 29 pandas-tests; their xfail entries are removed, three remaining `test_stack_unstack.py` entries get real failure reasons, and two classic categorical unstack params are un-xfailed. Attribution verified per node id against isolated builds: 21 pass with only this change, 4 need the stack PR, 2 need stack+fidelity, 2 need the groupby-agg PR.

Authors:
  - GALI PREM SAGAR (https://github.com/galipremsagar)

Approvers:
  - Matthew Roeschke (https://github.com/mroeschke)

URL: #23368
Teach the join filter pushdown planner to estimate the source-scan
cost needed to build candidate domains. Candidate selection now prefers
cheaper domain producers before smaller estimated output rows, and rejects
pushdown when the domain-build cost is too large relative to the target
being reduced.

Also prevent a single-source domain from being stacked onto a target source
that is already below the filtered side of a semi join. This heuristic does
a better job of keeping profitable domain choices while avoiding cases
where pushing down a filter would add an additional high-cardinality source
onto a join target that is already significantly filtered.

Additionally, extends trace metadata with estimated target, domain, and
constraint costs.

Material results of this change running NDSH SF30K on 8xNVL4 nodes are (previous results come from the change in #22996):
* **Q9 improved runtime: 11.77s lukewarm, 7.45s hot** (previously 47.12s lukewarm, 32.68s hot)
* Q5 unchaned: 9.55s lukewarm, 5.31s hot (previously 9.35s lukewarm, 5.14s hot)
* **NDSH SF30K for all 22 queries: 118.87s lukewarm, 111.63s hot**

Authors:
  - Peter Andreas Entschev (https://github.com/pentschev)
  - Lawrence Mitchell (https://github.com/wence-)

Approvers:
  - Gil Forsyth (https://github.com/gforsyth)
  - Tom Augspurger (https://github.com/TomAugspurger)

URL: #22997
)

First of all, I apologize for making a PR targeting the 26.08 branch. I
understand the code freeze has taken effect since yesterday, but wish
this change can still be shipped in the 26.08 release.

## Description

This PR adds the JNI bridge for the recent change in
#23402 to support the retention
filter for the deletion vector. Previously, it was assumed that deletion
vectors represent only the rows deleted. With
#23402 and this change, now Java
applications can pass the correct filter type for deletion vectors.

## Checklist
- [x] I am familiar with the [Contributing
Guidelines](https://github.com/rapidsai/cudf/blob/HEAD/CONTRIBUTING.md).
- [x] New or existing tests cover these changes.
- [x] The documentation is up to date with these changes.
@gforsyth
gforsyth merged commit a596c3e into main Jul 27, 2026
84 of 85 checks passed
@github-project-automation github-project-automation Bot moved this from In Progress to Done in cuDF Python Jul 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CMake CMake build issue cudf.pandas Issues specific to cudf.pandas cudf-polars Issues specific to cudf-polars Java Affects Java cuDF API. libcudf Affects libcudf (C++/CUDA) code. Python Affects Python cuDF API.

Projects

None yet

Development

Successfully merging this pull request may close these issues.