Title: cuda.core: reject stream=None — require explicit stream everywhere · Issue #2001 · NVIDIA/cuda-python · GitHub
Open Graph Title: cuda.core: reject stream=None — require explicit stream everywhere · Issue #2001 · NVIDIA/cuda-python
X Title: cuda.core: reject stream=None — require explicit stream everywhere · Issue #2001 · NVIDIA/cuda-python
Description: Summary Several cuda.core APIs accept stream=None and silently fall back to default_stream() (or NULL). This makes the stream choice implicit and environment-dependent (CUDA_PYTHON_CUDA_PER_THREAD_DEFAULT_STREAM), which is error-prone. U...
Open Graph Description: Summary Several cuda.core APIs accept stream=None and silently fall back to default_stream() (or NULL). This makes the stream choice implicit and environment-dependent (CUDA_PYTHON_CUDA_PER_THREAD_...
X Description: Summary Several cuda.core APIs accept stream=None and silently fall back to default_stream() (or NULL). This makes the stream choice implicit and environment-dependent (CUDA_PYTHON_CUDA_PER_THREAD_...
Opengraph URL: https://github.com/NVIDIA/cuda-python/issues/2001
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"cuda.core: reject stream=None — require explicit stream everywhere","articleBody":"## Summary\n\nSeveral `cuda.core` APIs accept `stream=None` and silently fall back to `default_stream()` (or NULL). This makes the stream choice implicit and environment-dependent (`CUDA_PYTHON_CUDA_PER_THREAD_DEFAULT_STREAM`), which is error-prone. Users should always pass a stream explicitly — including `device.default_stream` when they want the default.\n\n## Design rule\n\n`stream` should be a **keyword-only argument with no default value** (`*, stream: Stream`), so callers must always pass a stream explicitly.\n\nAPIs that already follow this convention:\n- `Buffer.copy_to(dst=None, *, stream: Stream | GraphBuilder)`\n- `Buffer.copy_from(src, *, stream: Stream | GraphBuilder)`\n- `Buffer.fill(value, *, stream: Stream | GraphBuilder)`\n\n## APIs that need to change\n\n### `stream=None` → `default_stream()` (implicit fallback, remove it)\n\n- `MemoryPool.allocate()` / `deallocate()`\n- `GraphMemoryResource.allocate()` / `deallocate()`\n- `GraphicsResource.map()`\n- `LegacyPinnedMemoryResource.allocate()`\n- `_SynchronousMemoryResource.allocate()`\n- `Device.allocate()` (delegates to the above)\n\n### `stream=None` → NULL / legacy default (same issue)\n\n- `Kernel.max_potential_cluster_size(config, stream=None)`\n- `Kernel.max_active_clusters(config, stream=None)`\n\n### `stream` should become keyword-only\n\n- `GraphBuilder.launch(self, stream: Stream)` — currently positional, should be `(self, *, stream: Stream)`\n\n## APIs that are fine (no change needed)\n\n- `launch(stream, config, kernel, *args)` — stream is the 1st positional arg by design\n- `Buffer.close(stream=None)` — None means \"reuse the original stream\", by design\n- `GraphicsResource.unmap(stream=None)` / `close(stream=None)` — same, reuses the mapping stream\n\n## Proposed implementation\n\n1. Have `Stream_accept()` raise `TypeError` when `stream is None`, so the check is centralized and cannot be forgotten.\n2. Remove the `= None` default from every affected API signature.\n3. Make `stream` keyword-only where it isn't already (except `launch()` where it's intentionally positional).\n\n## Prior art: CCCL's cccl-runtime\n\nCCCL's modern CUDA runtime (libcudacxx, `cuda::` namespace) follows the same explicit-stream principle:\n\n> The CUDA default (NULL) stream is not exposed as a first-class runtime object because it is tied to implicit per-device state and encourages hidden dependencies.\n>\n> — `docs/libcudacxx/runtime/cudart_interactions.rst`\n\nConcretely:\n- `cuda::launch(stream, config, kernel, args...)` requires an explicit `stream_ref` as the first parameter, with no default.\n- The `cuda::mr::resource` concept requires `allocate(cuda::stream_ref, ...)` / `deallocate(cuda::stream_ref, ...)` — no fallback to a default stream.\n- `cuda::stream_ref` deletes constructors from `int` and `nullptr`, and deprecates the parameterless (default stream) constructor.\n","author":{"url":"https://github.com/leofang","@type":"Person","name":"leofang"},"datePublished":"2026-05-01T01:11:53Z","url":"https://github.com/NVIDIA/cuda-python/issues/2001"}
| react-profiling | 0 |
| react-import-map | react,react-dom,react-dom/client,react-dom/profiling,react-is,react-reconciler,react/compiler-runtime,react/jsx-dev-runtime,react/jsx-runtime,scheduler@d5750093facf |
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:8fb10605-7e95-2df4-582f-e7e5afd7df83 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | EA20:23C977:4AE4F9:676BCD:6AF84316 |
| html-safe-nonce | 3e88081ba71765aa45003cf547623a8bca3ce30f5c41de39ca6d490cea53c2d6 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJFQTIwOjIzQzk3Nzo0QUU0Rjk6Njc2QkNEOjZBRjg0MzE2IiwidmlzaXRvcl9pZCI6IjkwOTAwNzU2NjcwMzM3Njg3MjciLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ== |
| visitor-hmac | 92cdc91898f4a251495e0c556b599fe0a4ea4062b02ac393874f87f2e66d6696 |
| hovercard-subject-tag | issue:4362245429 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/NVIDIA/cuda-python/2001/issue_layout |
| twitter:image | https://opengraph.githubassets.com/9e7052743c84da53d9dfc38947c5650887bb5c479fe1d87c0c8a329aa1b640d8/NVIDIA/cuda-python/issues/2001 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/9e7052743c84da53d9dfc38947c5650887bb5c479fe1d87c0c8a329aa1b640d8/NVIDIA/cuda-python/issues/2001 |
| og:image:alt | Summary Several cuda.core APIs accept stream=None and silently fall back to default_stream() (or NULL). This makes the stream choice implicit and environment-dependent (CUDA_PYTHON_CUDA_PER_THREAD_... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | leofang |
| hostname | github.com |
| expected-hostname | github.com |
| None | 5713ecd83001b2f55c3509fb7a292bf7d66d0f167c7ae87a9f7eaec5a52bf8db |
| turbo-cache-control | no-preview |
| go-import | github.com/NVIDIA/cuda-python git https://github.com/NVIDIA/cuda-python.git |
| octolytics-dimension-user_id | 1728152 |
| octolytics-dimension-user_login | NVIDIA |
| octolytics-dimension-repository_id | 381173759 |
| octolytics-dimension-repository_nwo | NVIDIA/cuda-python |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 381173759 |
| octolytics-dimension-repository_network_root_nwo | NVIDIA/cuda-python |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 653be32ff5c755082a4db662491bfbbcfc9112c1 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
| react-app-name | issues |
Links:
Viewport: width=device-width