Skip to content

Fix lazy quantifier priority handling in Glushkov regex engine - #23291

Closed
wjxiz1992 wants to merge 26 commits into
NVIDIA:mainfrom
wjxiz1992:codex/23287-glushkov-lazy
Closed

Fix lazy quantifier priority handling in Glushkov regex engine#23291
wjxiz1992 wants to merge 26 commits into
NVIDIA:mainfrom
wjxiz1992:codex/23287-glushkov-lazy

Conversation

@wjxiz1992

Copy link
Copy Markdown
Contributor

Description

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.

Checklist

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

Signed-off-by: Allen Xu <allxu@nvidia.com>
@copy-pr-bot

copy-pr-bot Bot commented Jul 16, 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 Jul 16, 2026
@wjxiz1992 wjxiz1992 added bug Something isn't working non-breaking Non-breaking change labels Jul 16, 2026
@wjxiz1992
wjxiz1992 marked this pull request as ready for review July 16, 2026 08:45
@wjxiz1992
wjxiz1992 requested a review from a team as a code owner July 16, 2026 08:46
@wjxiz1992
wjxiz1992 requested review from bdice, Copilot and igorpeshansky and removed request for Copilot July 16, 2026 08:46
@wjxiz1992 wjxiz1992 added the 3 - Ready for Review Ready for review by team label Jul 16, 2026
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR updates cuDF to the 26.10 release, adds direct joins and Java artifact builds, changes CI timeout handling, and modifies regex, join, streaming, IO, dataframe, groupby, proxy, and rolling-expression behavior with corresponding tests.

Changes

Release and CI integration

Layer / File(s) Summary
26.10 release configuration
.devcontainer/*, VERSION, dependencies.yaml, conda/*, python/*/pyproject.toml
Version pins, container images, package dependencies, and PyArrow constraints are updated for 26.10.
CI and timeout orchestration
.github/workflows/*, ci/*
Shared workflows and images move to current revisions, Java build jobs are added, and tests use stack-trace-aware timeout handling with fail-fast behavior.
Java packaging pipeline
java/ci/*, java/pom.xml
Scripts build static libcudf, package CUDA/architecture-specific JARs, assemble a Maven repository, and document the workflow.

Runtime features and compatibility

Layer / File(s) Summary
Direct and cross joins
cpp/include/cudf/join/*, cpp/src/join/*, cpp/tests/join/*, python/cudf/cudf/core/join/*
Adds direct_inner_join; cross joins now preserve row counts for zero-column operands and reject row-count overflow.
C++ runtime and streaming updates
cpp/include/cudf/detail/*, cpp/include/cudf/io/*, cpp/libcudf_streaming/*, cpp/src/row_operator/*
Updates 128-bit atomics, option builders, CSV quoting, pinned-memory configuration, and nested-list null precedence.
Python and Polars semantics
python/cudf/cudf/core/*, python/cudf_polars/cudf_polars/*
Aligns reductions, indexes, dataframe metadata, groupby operations, proxy mirroring, and fixed-size rolling expressions with pandas or Polars behavior.
Regression and compatibility coverage
cpp/tests/*, python/cudf/cudf/tests/*, python/cudf/cudf_pandas_tests/*, python/cudf_polars/tests/*
Adds targeted tests for joins, decimal reductions, nullable semantics, groupby behavior, proxy restoration, and rolling functions while updating expected-failure mappings.

Glushkov lazy quantifier handling

Layer / File(s) Summary
Priority conflict detection
cpp/src/strings/regex/glushkov_regcomp.cpp, cpp/src/strings/regex/glushkov_regcomp.hpp
Rule 1 detects an ACCEPT followed by a later CHAR_POS, and the compiler documentation records this failure condition.
Lazy quantifier regression coverage
cpp/tests/strings/split_tests.cpp
Adds split_record_re coverage for lazy and greedy carriage-return quantifiers.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related issues

Possibly related PRs

Suggested labels: libcudf

Suggested reviewers: bdice, rjzamora, lingyany-nv

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR includes many unrelated version bumps, workflow/devcontainer updates, Java CI scripts, and other non-regex changes beyond the linked issue. Split the unrelated release, CI, dependency, and Java changes into separate PRs, leaving this one focused on the Glushkov regex fix and regression test.
Docstring Coverage ⚠️ Warning Docstring coverage is 70.83% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The regex change and split_record_re regression test satisfy #23287’s requirement to reject unsupported priority frontiers.
Title check ✅ Passed The title clearly summarizes the main Glushkov regex fix for lazy quantifier priority handling.
Description check ✅ Passed The description directly matches the changeset and explains the Glushkov fallback fix, test, and validation.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@davidwendt

Copy link
Copy Markdown
Contributor

/ok to test 588722c

@davidwendt

Copy link
Copy Markdown
Contributor

Comment thread cpp/tests/strings/split_tests.cpp Outdated
Comment thread cpp/src/strings/regex/glushkov_regcomp.cpp Outdated
Comment thread cpp/tests/strings/split_tests.cpp
@lingyany-nv

Copy link
Copy Markdown
Contributor

The fix looks good to me, thanks for fixing this

Signed-off-by: Allen Xu <allxu@nvidia.com>
Copilot AI review requested due to automatic review settings July 17, 2026 07:01

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes an eligibility-check gap in the Glushkov regex fast path where certain Thompson-priority frontiers (notably involving ACCEPT preceding a later character-consuming transition) could cause lazy quantifiers to behave greedily, and adds a regression test to ensure correct split_record_re delimiter behavior.

Changes:

  • Tightens Glushkov priority-conflict detection to reject frontiers where ACCEPT is followed by a later CHAR_POS, forcing fallback to the Thompson engine.
  • Documents the additional “priority frontier not representable by Glushkov bit ordering” rejection case.
  • Adds a regression test covering split_record_re with a reluctant \r+? delimiter and a contrasting greedy \r+ case.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
cpp/tests/strings/split_tests.cpp Adds SplitRecordRegexLazyQuantifier regression to validate split behavior differs between \r+? and \r+.
cpp/src/strings/regex/glushkov_regcomp.hpp Updates eligibility documentation to mention Thompson-priority frontier conflicts.
cpp/src/strings/regex/glushkov_regcomp.cpp Updates frontier_has_priority_conflict Rule 1 to reject ACCEPT followed by later CHAR_POS in Thompson priority order.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +281 to +283
* Rule 1 – END before later char: an ACCEPT item appears before a CHAR_POS
* item in Thompson priority order → the accepted path has higher
* priority than a continuation that Glushkov cannot kill correctly.

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.

Added.

@wjxiz1992

Copy link
Copy Markdown
Contributor Author

/ok to test c8151f0

@wjxiz1992

Copy link
Copy Markdown
Contributor Author

blocked by main branch 26.10 ABI conflict.

paul-aiyedun and others added 5 commits July 21, 2026 17:11
* Split the JAR build into three composable stages (static libcudf build, per-classifier JAR packaging, and Maven-repo gather) so each stage is independently runnable in CI and locally.

* Link against a static libcudf built from source per CUDA version rather than a conda shared libcudf.

* Emit the Maven classifier based on the host architecture the build runs on, introducing a new `-arm64` suffix to distinguish aarch64 JARs from their x86_64 counterparts.

* Add `test_java_build_local.sh` as a one-command local reproducer of the full CI matrix for the host arch, with per-step timings and GPU compute-capability auto-detection.

Contributes to NVIDIA#22204

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

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

URL: NVIDIA#23261
…imeout (NVIDIA#23332)

## Description
Timing out an individual test is actually not useful since it is not
safe
to cancel a test at an arbitrary point in execution: that might leave a
collective dangling.

Moreover, many of the Polars tests run quite close to the, arbitrarily
chosen, timeout limit on CI runners if they are heavily loaded.

Since the signal we actually want is the state of a hanging process,
instead just add a test-suite level timeout with a utility to print the
state of the hanging processes.

closes NVIDIA#22948

## 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.
…sts (NVIDIA#23364)

Split out of NVIDIA#23255 (1/6).

`NumericalColumn.as_numerical_column` short-circuits casts between equivalent dtypes (same pylibcudf type, e.g. `float64` → `Float64`), but implemented the shortcut by assigning the target dtype onto `self._dtype` in place. The column object is shared with the caller's Series/DataFrame, so the *source* object silently changed dtype as a side effect of the cast. This returns a fresh column over the same pylibcudf data instead (`nans_to_nulls` first for float → masked casts), and adds a classic regression test.

Fixes 5 pandas-tests (`test_stack_nullable_dtype[*]`, `test_loc_set_nan_in_categorical_series[Float64]`, `test_assert_series_equal_extension_dtype_mismatch`, `test_assert_frame_equal_extension_dtype_mismatch`); their xfail entries are removed. Attribution verified by running the node ids against an isolated build containing only this fix (they pass) and a clean build (they fail).

Independent of the other NVIDIA#23255 split PRs; can merge in any order.

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

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

URL: NVIDIA#23364
…IA#23001)

Split out of NVIDIA#22927 per review.

## Problem

A class-level attribute write on a cudf.pandas proxy type — e.g. `monkeypatch.setattr(pd.ExcelFile, "parse", fn)` — was only applied to the proxy class. Code that runs under `disable_module_accelerator()` (such as the pandas fallback path of `pd.read_excel`) resolves attributes from the *real* class, so a patch applied only to the proxy was invisible to it.

## Fix

Add `_FastSlowProxyMeta.__setattr__`/`__delattr__` to mirror runtime class-level patches onto the underlying "slow" (real) type:

- `__setattr__` mirrors the assignment after translating the assigned value into "slow" space. A plain value is forwarded as-is. Re-assigning the proxy's *pristine* attribute for a name (which is exactly what `monkeypatch.setattr` / `mock.patch.object` save and re-assign on undo) translates to the slow type's pristine attribute for that name — restored if the slow type had one of its own, or removed if it didn't (leaving any inherited implementation visible). Proxy machinery (e.g. a saved `pd.ExcelFile.parse`, a `_MethodProxy`) unwraps to the slow object it delegates to.
- `__delattr__` mirrors a deletion as a deletion. Nothing is restored on delete.

The pristine state is a per-type map `name -> (pristine proxy attribute, pristine slow class-dict entry)` snapshotted once, when `make_*_proxy_type` finishes building the type (the same point mirroring is enabled via `_fsproxy_mirror_slow_overrides`). It is a fixed translation table, not runtime patch tracking: there is no stash of "what to put back", and undo works for any code that follows the standard save/patch/re-assign pattern (pytest `monkeypatch`, `unittest.mock.patch.object`, manual saves) because the saved value itself identifies the pristine state. The translation is what makes mirroring safe at all — the values readable off a proxy type live in proxy space, and forwarding e.g. the saved `columns` property or `eval`/`query` functions verbatim onto `pandas.DataFrame` would install cudf machinery on the real class (for `columns` this infinitely recurses on the fallback path).

cudf.pandas's own custom methods (`DataFrame.eval`/`query`) are installed via the new `_setattr_fsproxy_no_mirror` helper, which registers them as part of the proxy's pristine state without forwarding them to pandas.

## Tests

Adds unit tests in `cudf_pandas_tests/test_fast_slow_proxy.py` covering: set/delete mirroring, monkeypatch round-trips (new attr, existing attr, nested, `delattr`), `mock.patch.object` (which saves the raw descriptor without resolving it), properties, plain data attributes, `staticmethod`/`classmethod` descriptor preservation, methods the slow type only inherits, and the no-mirror helper; plus an end-to-end test in `test_cudf_pandas.py` that patches/unpatches `DataFrame.columns`/`eval` and `Series.str` and checks real pandas is restored and functional.

Removes 14 now-passing xfails from the pandas-tests plugin (13× `read_excel` engine-selection tests that monkeypatch the engine, plus a monkeypatch-registered custom accessor). The attribution of these 14 to the proxy fix (vs the Excel-reader fixes remaining in NVIDIA#22927) was verified locally by running each removed xfail with the proxy fix in isolation.

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

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

URL: NVIDIA#23001
This is an empty commit to trigger a build. This is needed after the RMM
ABI break in rapidsai/rmm#2462.
@davidwendt
davidwendt changed the base branch from main to release/26.08 July 21, 2026 21:12
@davidwendt
davidwendt requested review from a team as code owners July 21, 2026 21:12
@davidwendt
davidwendt requested a review from rjzamora July 21, 2026 21:12
@davidwendt
davidwendt requested review from a team as code owners July 21, 2026 21:12
@github-actions github-actions Bot added Python Affects Python cuDF API. CMake CMake build issue Java Affects Java cuDF API. cudf.pandas Issues specific to cudf.pandas cudf-polars Issues specific to cudf-polars pylibcudf Issues specific to the pylibcudf package labels Jul 21, 2026
@GPUtester GPUtester moved this to In Progress in cuDF Python Jul 21, 2026
@davidwendt
davidwendt changed the base branch from release/26.08 to main July 21, 2026 21:13
@davidwendt

Copy link
Copy Markdown
Contributor

Close in favor of #23381 since I failed the rebase on release/26.08.

@davidwendt davidwendt closed this Jul 21, 2026
@github-project-automation github-project-automation Bot moved this from In Progress to Done in cuDF Python Jul 21, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (3)
.github/workflows/build.yaml (1)

475-544: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Consider bounding java-build/java-gather runtime.

These new jobs build static libcudf from scratch across 4 matrix combinations without a timeout-minutes, unlike jobs routed through custom-job.yaml (which typically applies a default). A hang in the from-source build would consume the GitHub default (360 min) per matrix leg before failing.

⏱️ Suggested addition
   java-build:
     needs: [telemetry-setup]
+    timeout-minutes: 120
     strategy:
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/build.yaml around lines 475 - 544, Add explicit
timeout-minutes limits to the java-build matrix job and java-gather job. Use a
suitable bound for the from-source libcudf builds and a shorter appropriate
bound for artifact assembly, ensuring hung jobs terminate without relying on
GitHub’s default timeout.
ci/timeout_with_stack.py (1)

292-298: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Prefer start_new_session=True over preexec_fn=os.setsid.

preexec_fn is documented as unsafe with threads and can deadlock the child before exec; start_new_session=True achieves the same setsid() effect without that risk, and is exactly what Ruff's PLW1509 rule recommends.

🛡️ Suggested fix
     process = subprocess.Popen(
         cmd,
-        preexec_fn=os.setsid,
+        start_new_session=True,
     )

As per coding guidelines, **/*.py changes should pass the configured Ruff linters, which include this exact rule.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ci/timeout_with_stack.py` around lines 292 - 298, Update the subprocess.Popen
call in the process-launching code to replace preexec_fn=os.setsid with
start_new_session=True, preserving creation of a new process session and group
while satisfying Ruff PLW1509. Remove the now-unneeded preexec_fn-specific
comments or adjust them to describe the new option.

Source: Coding guidelines

python/cudf/cudf/core/index.py (1)

811-907: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Dense dtype-reconciliation logic in Index.union — recommend dedicated test coverage.

The new dtype_ignored/promote_dtype interplay correctly handles the empty-RangeIndex/object-dtype pandas quirk (GH pandas-dev/pandas#60797) across all four return branches based on a manual trace, but the branch combinations (empty+ignorable vs. empty+non-ignorable, numeric promotion, same-kind datetime/timedelta unit promotion, tz-aware vs. tz-naive) are numerous and easy to regress silently. As per coding guidelines for python/**/*.{py,pyx}, this touches type-promotion rules that "match expected behavior" — worth adding focused parametrized tests for each dtype_ignored/promote_dtype combination if not already covered elsewhere in this PR.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@python/cudf/cudf/core/index.py` around lines 811 - 907, Add focused
parametrized tests for Index.union covering each dtype_ignored and promote_dtype
combination: empty RangeIndex/object-dtype versus non-empty operands, numeric
promotion, same-kind datetime/timedelta unit promotion, and timezone-aware
versus timezone-naive inputs. Assert both result values and dtypes across the
empty, equal, and non-empty union branches, preserving the expected
pandas-compatible behavior.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cpp/include/cudf/detail/utilities/device_atomics.cuh`:
- Around line 356-366: Update the documentation for the __int128_t atomic
addition near its architecture-specific version gate to accurately describe all
CUDA versions excluded from the native Hopper/Blackwell path, including CUDA
13.0, 13.1, and 13.2. Keep the wording synchronized with the existing
preprocessor condition rather than changing the implementation.

In `@java/ci/README.md`:
- Around line 47-51: Declare the language on both directory-tree output fences
in java/ci/README.md: change the opening fences at lines 47-51 and 75-80 to use
the text language.
- Around line 43-50: Replace release-specific artifact names and paths in
java/ci/README.md lines 43-50 and 75-79 with version-neutral `<version>`
placeholders. Update both the classifier JAR/POM example and the Maven
repository path/filenames consistently, preserving the documented directory
structure.

In `@python/cudf/cudf/tests/groupby/test_ffill.py`:
- Around line 66-85: Update test_groupby_fill_limit to parameterize only valid
limits [1, 2, None] for result comparisons, and add a separate test covering
limit values 0 and -1 that asserts both pandas and cuDF groupby fill methods
raise ValueError. Preserve coverage for both ffill and bfill and the existing
value cases.

---

Nitpick comments:
In @.github/workflows/build.yaml:
- Around line 475-544: Add explicit timeout-minutes limits to the java-build
matrix job and java-gather job. Use a suitable bound for the from-source libcudf
builds and a shorter appropriate bound for artifact assembly, ensuring hung jobs
terminate without relying on GitHub’s default timeout.

In `@ci/timeout_with_stack.py`:
- Around line 292-298: Update the subprocess.Popen call in the process-launching
code to replace preexec_fn=os.setsid with start_new_session=True, preserving
creation of a new process session and group while satisfying Ruff PLW1509.
Remove the now-unneeded preexec_fn-specific comments or adjust them to describe
the new option.

In `@python/cudf/cudf/core/index.py`:
- Around line 811-907: Add focused parametrized tests for Index.union covering
each dtype_ignored and promote_dtype combination: empty RangeIndex/object-dtype
versus non-empty operands, numeric promotion, same-kind datetime/timedelta unit
promotion, and timezone-aware versus timezone-naive inputs. Assert both result
values and dtypes across the empty, equal, and non-empty union branches,
preserving the expected pandas-compatible behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: fdb5a662-90f7-4dfc-b88d-8278831d6fea

📥 Commits

Reviewing files that changed from the base of the PR and between 0baa8ee and 0d69ccf.

📒 Files selected for processing (106)
  • .devcontainer/cuda12.9-conda/devcontainer.json
  • .devcontainer/cuda12.9-pip/devcontainer.json
  • .devcontainer/cuda13.3-conda/devcontainer.json
  • .devcontainer/cuda13.3-pip/devcontainer.json
  • .github/workflows/build.yaml
  • .github/workflows/compute-sanitizer-run.yaml
  • .github/workflows/pandas-tests.yaml
  • .github/workflows/pr.yaml
  • .github/workflows/test.yaml
  • .pre-commit-config.yaml
  • VERSION
  • ci/run_cudf_polars_polars_tests.sh
  • ci/run_cudf_polars_pytests.sh
  • ci/test_cuml_compat.sh
  • ci/test_narwhals.sh
  • ci/test_wheel_cudf_polars.sh
  • ci/timeout_with_stack.py
  • conda/environments/all_cuda-129_arch-aarch64.yaml
  • conda/environments/all_cuda-129_arch-x86_64.yaml
  • conda/environments/all_cuda-133_arch-aarch64.yaml
  • conda/environments/all_cuda-133_arch-x86_64.yaml
  • conda/recipes/cudf/recipe.yaml
  • conda/recipes/pylibcudf/recipe.yaml
  • cpp/CMakeLists.txt
  • cpp/benchmarks/CMakeLists.txt
  • cpp/benchmarks/join/direct_join.cu
  • cpp/include/cudf/detail/utilities/device_atomics.cuh
  • cpp/include/cudf/io/avro.hpp
  • cpp/include/cudf/io/csv.hpp
  • cpp/include/cudf/io/json.hpp
  • cpp/include/cudf/io/orc.hpp
  • cpp/include/cudf/join/direct_join.hpp
  • cpp/include/cudf/join/join.hpp
  • cpp/libcudf_streaming/benchmarks/bench_shuffle.cpp
  • cpp/libcudf_streaming/benchmarks/streaming/bench_streaming_shuffle.cpp
  • cpp/libcudf_streaming/benchmarks/streaming/ndsh/utils.cpp
  • cpp/libcudf_streaming/tests/streaming/base_streaming_fixture.hpp
  • cpp/libcudf_streaming/tests/streaming/test_table_chunk.cpp
  • cpp/libcudf_streaming/tests/test_shuffler.cpp
  • cpp/src/join/cross_join.cu
  • cpp/src/join/direct_join.cu
  • cpp/src/row_operator/row_operators.cu
  • cpp/tests/CMakeLists.txt
  • cpp/tests/groupby/sum_tests.cpp
  • cpp/tests/join/cross_join_tests.cpp
  • cpp/tests/join/direct_join_tests.cpp
  • cpp/tests/streams/join_test.cpp
  • dependencies.yaml
  • java/ci/README.md
  • java/ci/argparse.sh
  • java/ci/assemble_maven_repo.sh
  • java/ci/build_cudf_java_jar.sh
  • java/ci/build_cudf_java_jar_in_container.sh
  • java/ci/build_static_libcudf.sh
  • java/ci/build_static_libcudf_in_container.sh
  • java/ci/test_java_build_local.sh
  • java/pom.xml
  • python/cudf/benchmarks/internal/bench_fast_slow_proxy.py
  • python/cudf/cudf/VERSION
  • python/cudf/cudf/core/column/column.py
  • python/cudf/cudf/core/column/numerical.py
  • python/cudf/cudf/core/column/string.py
  • python/cudf/cudf/core/dataframe.py
  • python/cudf/cudf/core/groupby/groupby.py
  • python/cudf/cudf/core/index.py
  • python/cudf/cudf/core/indexed_frame.py
  • python/cudf/cudf/core/join/join.py
  • python/cudf/cudf/core/series.py
  • python/cudf/cudf/pandas/_wrappers/pandas.py
  • python/cudf/cudf/pandas/fast_slow_proxy.py
  • python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py
  • python/cudf/cudf/tests/dataframe/methods/test_reductions.py
  • python/cudf/cudf/tests/dataframe/methods/test_rename.py
  • python/cudf/cudf/tests/dataframe/test_constructors.py
  • python/cudf/cudf/tests/groupby/test_agg.py
  • python/cudf/cudf/tests/groupby/test_apply.py
  • python/cudf/cudf/tests/groupby/test_ffill.py
  • python/cudf/cudf/tests/groupby/test_pct_change.py
  • python/cudf/cudf/tests/groupby/test_transform.py
  • python/cudf/cudf/tests/reshape/test_merge.py
  • python/cudf/cudf/tests/series/methods/test_astype.py
  • python/cudf/cudf/tests/series/methods/test_mode.py
  • python/cudf/cudf/tests/series/methods/test_reductions.py
  • python/cudf/cudf/utils/dtypes.py
  • python/cudf/cudf_pandas_tests/test_cudf_pandas.py
  • python/cudf/cudf_pandas_tests/test_fast_slow_proxy.py
  • python/cudf/cudf_pandas_tests/third_party_integration_tests/dependencies.yaml
  • python/cudf/pyproject.toml
  • python/cudf_kafka/pyproject.toml
  • python/cudf_polars/cudf_polars/dsl/expr.py
  • python/cudf_polars/cudf_polars/dsl/expressions/rolling.py
  • python/cudf_polars/cudf_polars/dsl/translate.py
  • python/cudf_polars/cudf_polars/engine/core.py
  • python/cudf_polars/pyproject.toml
  • python/cudf_polars/tests/conftest.py
  • python/cudf_polars/tests/expressions/test_fixed_rolling.py
  • python/cudf_polars/tests/expressions/test_rolling.py
  • python/cudf_polars/tests/streaming/test_scan.py
  • python/cudf_polars/tests/streaming/test_select.py
  • python/cudf_polars/tests/streaming/test_sort.py
  • python/cudf_streaming/pyproject.toml
  • python/custreamz/pyproject.toml
  • python/dask_cudf/pyproject.toml
  • python/libcudf/pyproject.toml
  • python/libcudf_streaming/pyproject.toml
  • python/pylibcudf/pyproject.toml
💤 Files with no reviewable changes (4)
  • ci/test_cuml_compat.sh
  • python/cudf_polars/tests/streaming/test_sort.py
  • python/cudf_polars/tests/expressions/test_rolling.py
  • python/cudf_polars/tests/streaming/test_scan.py

Comment on lines 356 to 366
/**
* @brief Atomic addition for __int128_t with architecture-specific optimization
*
* Uses native 128-bit CAS on Hopper+ GPUs (compute capability 9.0+) for optimal
* performance. Falls back to two 64-bit atomic CAS operations with carry propagation
* on older GPU architectures.
* Uses native 128-bit CAS on Hopper+ GPUs for optimal performance, except for CUDA 13.0 on
* Blackwell. Other configurations fall back to two 64-bit atomic additions with carry
* propagation.
*
* @param address Pointer to the __int128_t value
* @param val Value to add
* @return The old value before addition
*/

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Docstring doesn't match the actual version gate.

The doc says the native path is skipped "except for CUDA 13.0 on Blackwell," but the #if condition on lines 371-372 excludes the native path for __CUDACC_VER_MAJOR__ == 13 && __CUDACC_VER_MINOR__ < 3, i.e. CUDA 13.0, 13.1, and 13.2. Update the comment to match the code (or vice versa) so a future contributor narrowing/widening the gate doesn't work from stale documentation.

📝 Proposed doc fix
- * Uses native 128-bit CAS on Hopper+ GPUs for optimal performance, except for CUDA 13.0 on
+ * Uses native 128-bit CAS on Hopper+ GPUs for optimal performance, except for CUDA 13.0-13.2 on
  * Blackwell. Other configurations fall back to two 64-bit atomic additions with carry
  * propagation.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
* @brief Atomic addition for __int128_t with architecture-specific optimization
*
* Uses native 128-bit CAS on Hopper+ GPUs (compute capability 9.0+) for optimal
* performance. Falls back to two 64-bit atomic CAS operations with carry propagation
* on older GPU architectures.
* Uses native 128-bit CAS on Hopper+ GPUs for optimal performance, except for CUDA 13.0 on
* Blackwell. Other configurations fall back to two 64-bit atomic additions with carry
* propagation.
*
* @param address Pointer to the __int128_t value
* @param val Value to add
* @return The old value before addition
*/
/**
* `@brief` Atomic addition for __int128_t with architecture-specific optimization
*
* Uses native 128-bit CAS on Hopper+ GPUs for optimal performance, except for CUDA 13.0-13.2 on
* Blackwell. Other configurations fall back to two 64-bit atomic additions with carry
* propagation.
*
* `@param` address Pointer to the __int128_t value
* `@param` val Value to add
* `@return` The old value before addition
*/
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cpp/include/cudf/detail/utilities/device_atomics.cuh` around lines 356 - 366,
Update the documentation for the __int128_t atomic addition near its
architecture-specific version gate to accurately describe all CUDA versions
excluded from the native Hopper/Blackwell path, including CUDA 13.0, 13.1, and
13.2. Keep the wording synchronized with the existing preprocessor condition
rather than changing the implementation.

Comment thread java/ci/README.md
Comment on lines +43 to +50
This compiles the JNI layer against the static libcudf from Step 1 and emits a
single classifier JAR (e.g. `cudf-26.08.0-SNAPSHOT-cuda12.jar`) plus its POM
into a classifier-named subdirectory under `--output-dir`:

```
/tmp/jars/cuda12/
cudf-26.08.0-SNAPSHOT-cuda12.jar
cudf-26.08.0-SNAPSHOT.pom

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Replace release-specific artifact examples with version-neutral paths.

The new recommended workflow documents 26.08.0-SNAPSHOT, while this release cohort updates configuration to 26.10. Use <version> consistently so the instructions do not become stale each release.

  • java/ci/README.md#L43-L50: replace the hard-coded JAR and POM examples.
  • java/ci/README.md#L75-L79: replace the hard-coded Maven repository path and filenames.
🧰 Tools
🪛 markdownlint-cli2 (0.23.0)

[warning] 47-47: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

📍 Affects 1 file
  • java/ci/README.md#L43-L50 (this comment)
  • java/ci/README.md#L75-L79
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@java/ci/README.md` around lines 43 - 50, Replace release-specific artifact
names and paths in java/ci/README.md lines 43-50 and 75-79 with version-neutral
`<version>` placeholders. Update both the classifier JAR/POM example and the
Maven repository path/filenames consistently, preserving the documented
directory structure.

Comment thread java/ci/README.md
Comment on lines +47 to +51
```
/tmp/jars/cuda12/
cudf-26.08.0-SNAPSHOT-cuda12.jar
cudf-26.08.0-SNAPSHOT.pom
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Declare a language for the directory-tree fences.

markdownlint reports MD040 for both output examples; label them text.

  • java/ci/README.md#L47-L51: change the opening fence to ```text.
  • java/ci/README.md#L75-L80: change the opening fence to ```text.
🧰 Tools
🪛 markdownlint-cli2 (0.23.0)

[warning] 47-47: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

📍 Affects 1 file
  • java/ci/README.md#L47-L51 (this comment)
  • java/ci/README.md#L75-L80
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@java/ci/README.md` around lines 47 - 51, Declare the language on both
directory-tree output fences in java/ci/README.md: change the opening fences at
lines 47-51 and 75-80 to use the text language.

Source: Linters/SAST tools

Comment on lines +66 to +85
@pytest.mark.parametrize("method", ["ffill", "bfill"])
@pytest.mark.parametrize("limit", [0, 1, 2, -1, None])
@pytest.mark.parametrize(
"values",
[
[1.0, None, None, None, 2.0, None, None],
["x", None, None, None, "y", None, None],
],
)
def test_groupby_fill_limit(method, limit, values):
# interleaved keys: limit counts group-relative positions
keys = ["a", "b"] * 7
data = {"key": keys, "val": [v for v in values for _ in range(2)]}
pdf = pd.DataFrame(data)
gdf = cudf.DataFrame(data)

expect = getattr(pdf.groupby("key"), method)(limit=limit)
got = getattr(gdf.groupby("key"), method)(limit=limit)

assert_groupby_results_equal(expect, got)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Separate invalid limits from result-comparison cases.

limit=0 and limit=-1 cause pandas fill operations to raise ValueError, so Line 82 aborts those parametrizations before cuDF is compared. Keep [1, 2, None] here and add a separate exception-parity test for invalid limits. Pandas 3.0 validates that a limit must be greater than zero. (raw.githubusercontent.com)

Proposed fix
-@pytest.mark.parametrize("limit", [0, 1, 2, -1, None])
+@pytest.mark.parametrize("limit", [1, 2, None])
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@pytest.mark.parametrize("method", ["ffill", "bfill"])
@pytest.mark.parametrize("limit", [0, 1, 2, -1, None])
@pytest.mark.parametrize(
"values",
[
[1.0, None, None, None, 2.0, None, None],
["x", None, None, None, "y", None, None],
],
)
def test_groupby_fill_limit(method, limit, values):
# interleaved keys: limit counts group-relative positions
keys = ["a", "b"] * 7
data = {"key": keys, "val": [v for v in values for _ in range(2)]}
pdf = pd.DataFrame(data)
gdf = cudf.DataFrame(data)
expect = getattr(pdf.groupby("key"), method)(limit=limit)
got = getattr(gdf.groupby("key"), method)(limit=limit)
assert_groupby_results_equal(expect, got)
`@pytest.mark.parametrize`("method", ["ffill", "bfill"])
`@pytest.mark.parametrize`("limit", [1, 2, None])
`@pytest.mark.parametrize`(
"values",
[
[1.0, None, None, None, 2.0, None, None],
["x", None, None, None, "y", None, None],
],
)
def test_groupby_fill_limit(method, limit, values):
# interleaved keys: limit counts group-relative positions
keys = ["a", "b"] * 7
data = {"key": keys, "val": [v for v in values for _ in range(2)]}
pdf = pd.DataFrame(data)
gdf = cudf.DataFrame(data)
expect = getattr(pdf.groupby("key"), method)(limit=limit)
got = getattr(gdf.groupby("key"), method)(limit=limit)
assert_groupby_results_equal(expect, got)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@python/cudf/cudf/tests/groupby/test_ffill.py` around lines 66 - 85, Update
test_groupby_fill_limit to parameterize only valid limits [1, 2, None] for
result comparisons, and add a separate test covering limit values 0 and -1 that
asserts both pandas and cuDF groupby fill methods raise ValueError. Preserve
coverage for both ffill and bfill and the existing value cases.

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

Labels

3 - Ready for Review Ready for review by team bug Something isn't working 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. non-breaking Non-breaking change pylibcudf Issues specific to the pylibcudf package Python Affects Python cuDF API.

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[BUG] Glushkov regex fast path treats a lazy quantifier as greedy in split_re