Skip to content

Migrate stream APIs from rmm::cuda_stream_view to cuda::stream_ref - #23929

Merged
rapids-bot[bot] merged 13 commits into
NVIDIA:release/26.10from
bdice:cuda-stream-ref
Sep 14, 2026
Merged

rapids-bot[bot] merged 13 commits into
NVIDIA:release/26.10from
bdice:cuda-stream-ref

Conversation

@bdice

@bdice bdice commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Track the coordinated migration of stream APIs and call sites from rmm::cuda_stream_view to CCCL's cuda::stream_ref. This propagates cuda::stream_ref through RMM containers and memory resources, RAFT resource and handle APIs, downstream C++ interfaces, Python/Cython bindings, benchmarks, tests, and documentation.

This updates cuDF C++ and Cython stream accessors, building on the default-stream work merged in #23770. It continues work from #23636.

Depends on rapidsai/rmm#2372.

Tracked in rapidsai/build-planning#318.

Migrations

  • Pass cuda::stream_ref through stream pools, resource accessors, conditionals, and downstream APIs without converting to rmm::cuda_stream_view
  • Use cuda::stream_ref constructions for default/legacy/per-thread streams
    • rmm::cuda_stream_default ➡️ cuda::stream_ref{cudaStream_t{cudaStreamDefault}}
    • rmm::cuda_stream_legacy ➡️ cuda::stream_ref{cudaStreamLegacy}
    • rmm::cuda_stream_per_thread ➡️ cuda::stream_ref{cudaStreamPerThread}
  • Use .get() when calling an API that requires a raw cudaStream_t, including CUDA runtime, library, CUB, and legacy API boundaries (previously rmm::cuda_stream_view used value())
  • Use .sync() when synchronizing a cuda::stream_ref (previously rmm::cuda_stream_view used synchronize())
  • Update Cython declarations and call sites to pass stream references directly where supported

CUDA context initialization

Includes the context fix from #24147 so it lands together with the stream migration. cuda::stream_ref::sync() calls the CUDA Driver API, which does not implicitly establish a current context on fresh execution threads. Empty-column/metadata operations can therefore fail with CUDA_ERROR_INVALID_CONTEXT in Dask-cuDF and cuStreamz.

pylibcudf.utils._get_stream() now calls _ensure_cuda_context(), which uses cuda.bindings.cyruntime.cudaFree(NULL) to establish a current context when needed. RMM is unchanged, initialization does not occur at import time, and no profiler-header dependency is needed. Runtime cudaStream_t objects are accepted directly, including older bindings versions without __cuda_stream__ support.

The runtime-only _get_stream() measured 126 ns per warm call, 7.11 µs for first use on a fresh thread, and 192 ms for first-process CUDA initialization. It returned while GPU work remained pending in all four tested stream modes; no forced GPU synchronization was observed. The current implementation releases the GIL on every call, which can introduce scheduling delays under Python-thread contention. See updated benchmark methodology, comparisons, and validation limitations.

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 Sep 1, 2026

Copy link
Copy Markdown

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@github-actions github-actions Bot added libcudf Affects libcudf (C++/CUDA) code. Python Affects Python cuDF API. Java Affects Java cuDF API. pylibcudf Issues specific to the pylibcudf package labels Sep 1, 2026
@bdice bdice changed the title Adapt stream accessors to cuda::stream_ref Migrate stream APIs from rmm::cuda_stream_view to cuda::stream_ref Sep 2, 2026
@bdice
bdice marked this pull request as ready for review September 2, 2026 22:55
@bdice
bdice requested review from a team as code owners September 2, 2026 22:55
@coderabbitai

coderabbitai Bot commented Sep 2, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

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: 17c978e4-c38a-4210-865e-ef5e5b097c33

📥 Commits

Reviewing files that changed from the base of the PR and between e656dd8 and ceb5f2f.

📒 Files selected for processing (2)
  • cpp/examples/versions.cmake
  • cpp/tests/join/streaming_hash_join_tests.cpp

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


📝 Summary

Summary by CodeRabbit

  • Refactor

    • Updated internal CUDA stream handling across parquet processing, streaming joins, partitioning, table conversion, and bloom filter operations.
    • Preserved existing remapping, partitioning, joining, and filtering behavior while aligning components with current stream interfaces.
    • Updated related validation coverage to use the streamlined stream integration.
  • Chores

    • Updated copyright attribution in the versions configuration.
  • User Impact

    • No user-facing API or functionality changes.

Walkthrough

The pull request updates CUDA stream usage across native code, Python streaming bindings, and streaming join tests. It also updates the SPDX attribution in cpp/examples/versions.cmake.

Changes

CUDA stream migration

Layer / File(s) Summary
Native stream references
cpp/src/io/parquet/reader_impl_dict_transcode.cu, cpp/libcudf_streaming/src/bloom_filter.cpp, cpp/examples/versions.cmake
Native code passes current CUDA stream references directly. The SPDX attribution includes “& AFFILIATES.”
Python stream views
python/cudf_streaming/cudf_streaming/partition_utils.pyx, python/cudf_streaming/cudf_streaming/table_chunk.pyx
Python streaming operations pass stream.view() directly instead of reconstructing stream references from raw values.
Streaming join test call sites
cpp/tests/join/streaming_hash_join_tests.cpp
Streaming hash join tests pass CUDA streams directly to the constructor and insertion operations.

Priority: ⬇️ Low

Estimated code review effort: 1 (Trivial) | ~5 minutes

Change: Refactor

Merge Risk: ⚪ Minimal · up to ceb5f

The stream-reference migration preserves the inspected native and Python API contracts, with no concrete build or runtime regression established.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 15 files. (1 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
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 the stream API migration and matches the stated pull request objectives.
Title check ✅ Passed The title clearly and concisely identifies the main change: migrating from rmm::cuda_stream_view to cuda::stream_ref.
Full details: Docstring Coverage

Explanation

Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 15 files. (1 skipped: 1 unsupported.)

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@bdice
bdice requested a review from a team as a code owner September 3, 2026 02:30
@bdice bdice added breaking Breaking change improvement Improvement / enhancement to an existing function labels Sep 3, 2026
@bdice
bdice force-pushed the cuda-stream-ref branch 2 times, most recently from a61eee2 to 56b7d90 Compare September 7, 2026 01:07
@bdice
bdice changed the base branch from main to release/26.10 September 8, 2026 19:59
@bdice bdice removed Python Affects Python cuDF API. CMake CMake build issue Java Affects Java cuDF API. pylibcudf Issues specific to the pylibcudf package labels Sep 13, 2026
@bdice

bdice commented Sep 13, 2026

Copy link
Copy Markdown
Contributor Author

/merge

Signed-off-by: Bradley Dice <bdice@bradleydice.com>
@github-actions github-actions Bot added the Python Affects Python cuDF API. label Sep 13, 2026
@github-actions github-actions Bot added the pylibcudf Issues specific to the pylibcudf package label Sep 13, 2026
@bdice
bdice requested a review from a team as a code owner September 13, 2026 19:56
@bdice
bdice requested a review from msarahan September 13, 2026 19:56
@bdice

bdice commented Sep 13, 2026

Copy link
Copy Markdown
Contributor Author

Notes on CUDA contexts

While switching everything from rmm::cuda_stream_view to cuda::stream_ref, I hit a small snag where some thread usage patterns in dask-cudf and custreamz don’t initialize a CUDA context. Because cuda::stream_ref uses CUDA driver APIs to synchronize instead of CUDA runtime APIs like in RMM, we no longer have context initialization happening automatically. I am putting that responsibility into pylibcudf’s _get_stream utility function because it’s a common path that returns a default stream that might have no associated CUDA context. The performance impact is minimal.

I already have a Python approval from earlier from @vyasr and I am going to merge this PR as-is because it is blocking downstream repos until the migration is complete. However, there are some follow-up discussions we need to have.

The current implementation of _ensure_cuda_context in ad4dd18 calls cudaFree(NULL) and releases the GIL. If we switched this to a CUDA driver API implementation, it would save some time, but it requires an added dependency on cuda-profiler-api headers to use cuda.bindings.cydriver Cython code. I don't have a packaging approval on this PR but I need to unblock CI downstream so I am not going to take that path right now. I will file a follow-up for that.

Warm implementation Median per call
Previous Driver API guard; initialization only when absent 34 ns
Current runtime-only implementation, releasing the GIL 126 ns

Comment on lines +85 to +88
if isinstance(stream, runtime.cudaStream_t):
return Stream._from_cudaStream_t(
<cudaStream_t><uintptr_t>int(stream), owner=stream
)

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.

This makes _get_stream accept runtime.cudaStream_t objects directly, because older versions of cuda-bindings that we support do not have __cuda_stream__ support in cuda.bindings.runtime.cudaStream_t.

Previously we used Cython wrappers around rmm::cuda_stream_view which has support for __cuda_stream__ and can be implicitly converted to cudaStream_t.

@bdice

bdice commented Sep 14, 2026

Copy link
Copy Markdown
Contributor Author

/merge

@rapids-bot
rapids-bot Bot merged commit 9d3e855 into NVIDIA:release/26.10 Sep 14, 2026
131 of 134 checks passed
@github-project-automation github-project-automation Bot moved this from Todo to Done in cuDF Python Sep 14, 2026
rapids-bot Bot pushed a commit that referenced this pull request Sep 14, 2026
Follow-up to the [CUDA context discussion in #23929](#23929 (comment)).

Use `cuCtxGetCurrent()` from `cuda.bindings.cydriver` in `_ensure_cuda_context()` to skip the CUDA Runtime call when a context is already current. This also avoids releasing and reacquiring the GIL on the warm path. The existing `cudaFree(NULL)` initialization, with the GIL released, remains for fresh threads or an uninitialized CUDA driver. Other driver errors are propagated.

This requires us to add `cuda-profiler-api` to pylibcudf's conda `host` requirements. CUDA 12 `cydriver` declarations include `cudaProfiler.h` even when importing only context APIs. This is only a build-time dependency; no profiling functionality is used.

A local microbenchmark of `_get_stream(None)` decreased from **166–220 ns** to **43–50 ns** per call.

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

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

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

Labels

breaking Breaking change improvement Improvement / enhancement to an existing function libcudf Affects libcudf (C++/CUDA) code. 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.

4 participants