Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/release_checklist.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ body:
- label: File an internal nvbug to communicate test plan & release schedule with QA
- label: Ensure all pending PRs are reviewed, tested, and merged
- label: Check (or update if needed) the dependency requirements
- label: Sweep deprecations whose stated removal version has arrived (`grep -rn 'deprecated::' cuda_core/cuda`) and remove any that are due
- label: "Finalize the doc update, including release notes (\"Note: Touching docstrings/type annotations in code is OK during code freeze, apply your best judgement!\")"
- label: Update the docs for the new version
- label: Create a public release tag
Expand Down
21 changes: 21 additions & 0 deletions .github/RELEASE-core.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,27 @@ requirements are current.

---

## Sweep deprecations whose removal version has arrived

Deprecated APIs are marked in the source with a Sphinx `deprecated`
directive naming the version that introduced the deprecation, and their
docstrings state the version in which they will be removed. Find them all
with:

```console
$ grep -rn 'deprecated::' cuda_core/cuda
```

For each hit, check the stated removal version against the version being
released. If the release has reached or passed it, remove the API, its
runtime `DeprecationWarning`, and any tests asserting that warning.

This must happen *before* the release tag is cut. Removals are breaking
changes, so they are only permitted at a major-version boundary per the
[support policy](https://nvidia.github.io/cuda-python/cuda-core/latest/support.html).

---

## Finalize the doc update, including release notes

Review every PR included in the release. For each one, check whether new
Expand Down
12 changes: 12 additions & 0 deletions cuda_core/cuda/core/_linker.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,18 @@ class LinkerOptions:
no_cache : bool, optional
Do not cache the intermediate steps of nvJitLink.
Default: False.
numba_debug : bool, optional
Non-functional. ``numba_debug`` is an NVVM/NVRTC *compiler* option;
neither nvJitLink nor the driver's cuLink API recognizes it, so no
linking backend can honor it and the value is ignored.
Default: None.

.. deprecated:: 1.2.0
Setting this option emits a :class:`DeprecationWarning`. It has never
had an effect on any linking backend and will be removed in
``cuda.core`` 2.0.0. Use
:attr:`ProgramOptions.numba_debug` on an NVVM or NVRTC compilation
path instead.
Comment thread
rparolin marked this conversation as resolved.
"""
name: str | None = '<default linker>'
arch: str | None = None
Expand Down
27 changes: 27 additions & 0 deletions cuda_core/cuda/core/_linker.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,18 @@ class LinkerOptions:
no_cache : bool, optional
Do not cache the intermediate steps of nvJitLink.
Default: False.
numba_debug : bool, optional
Non-functional. ``numba_debug`` is an NVVM/NVRTC *compiler* option;
neither nvJitLink nor the driver's cuLink API recognizes it, so no
linking backend can honor it and the value is ignored.
Default: None.

.. deprecated:: 1.2.0
Setting this option emits a :class:`DeprecationWarning`. It has never
had an effect on any linking backend and will be removed in
``cuda.core`` 2.0.0. Use
:attr:`ProgramOptions.numba_debug` on an NVVM or NVRTC compilation
path instead.
Comment thread
rparolin marked this conversation as resolved.
"""

name: str | None = "<default linker>"
Expand Down Expand Up @@ -311,6 +323,21 @@ class LinkerOptions:
def __post_init__(self) -> None:
_lazy_init()
self._name = self.name.encode()
# No linking backend reads ``numba_debug``, so warn where the value is
# supplied rather than in the option builders -- the user learns once,
# at the call site that set it, instead of once per link. The gate is
# ``is not None`` (unlike the ignore-warning on the PTX compile path):
# it is the *field* that is going away, so any explicit value earns the
# notice, including ``False``.
if self.numba_debug is not None:
warn(
"numba_debug is not supported by any linking backend and is ignored. "
"LinkerOptions.numba_debug is deprecated and will be removed in "
"cuda.core 2.0.0; use ProgramOptions.numba_debug on an NVVM or NVRTC "
"compilation path instead.",
DeprecationWarning,
stacklevel=3,
)

def _prepare_nvjitlink_options(self, as_bytes: bool = False) -> list[bytes] | list[str]:
options = []
Expand Down
7 changes: 5 additions & 2 deletions cuda_core/cuda/core/_program.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -316,8 +316,11 @@ class ProgramOptions:
numba_debug : bool, optional
Emit the debug information layout expected by Numba. Recognized only by
newer toolkits; compilers that do not support it reject the option with
an error.
Default: False
an error. Applies only to the NVVM and NVRTC compilation backends --
``code_type="ptx"`` is processed by the linker, which cannot honor it,
so enabling this option there emits a :class:`UserWarning` and the
option is ignored.
Default: None
"""
name: str | None = 'default_program'
arch: str | None = None
Expand Down
23 changes: 20 additions & 3 deletions cuda_core/cuda/core/_program.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -469,8 +469,11 @@ class ProgramOptions:
numba_debug : bool, optional
Emit the debug information layout expected by Numba. Recognized only by
newer toolkits; compilers that do not support it reject the option with
an error.
Default: False
an error. Applies only to the NVVM and NVRTC compilation backends --
``code_type="ptx"`` is processed by the linker, which cannot honor it,
so enabling this option there emits a :class:`UserWarning` and the
option is ignored.
Default: None
"""

name: str | None = "default_program"
Expand Down Expand Up @@ -732,6 +735,21 @@ cpdef bint _can_load_generated_ptx() except? -1:

cdef inline object _translate_program_options(object options):
"""Translate ProgramOptions to LinkerOptions for PTX compilation."""
# ``numba_debug`` is an NVVM/NVRTC compiler option that no linking backend can
# honor. It used to be forwarded into ``LinkerOptions`` and dropped without a
# word; warn instead, and do not forward -- forwarding would only trigger the
# deprecation warning on a field the user never touched. ``UserWarning``, not
# ``DeprecationWarning``: ``ProgramOptions.numba_debug`` is not deprecated, it
# is fully supported on NVVM and NVRTC and merely inapplicable here. The gate
# is truthiness, matching ``_prepare_nvvm_options_impl``: only an enabled
# ``numba_debug`` asks for something this path cannot deliver.
if options.numba_debug:
warn(
"numba_debug is ignored for code_type='ptx', which is processed by the linker; "
"it applies only to the NVVM and NVRTC compilation backends.",
UserWarning,
stacklevel=4,
)
return LinkerOptions(
name=options.name,
arch=options.arch,
Expand All @@ -747,7 +765,6 @@ cdef inline object _translate_program_options(object options):
split_compile=options.split_compile,
ptxas_options=options.ptxas_options,
no_cache=options.no_cache,
numba_debug = options.numba_debug
)


Expand Down
5 changes: 5 additions & 0 deletions cuda_core/cuda/core/utils/_program_cache/_keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,11 @@ def validate(self, options: ProgramOptions, target_type: str, extra_digest: byte
raise ValueError(
"extra_sources is only valid for code_type='nvvm'; Program() rejects it for code_type='ptx'."
)
# ``numba_debug`` is deliberately not rejected here and is absent from
# ``_LINKER_FIELD_GATES``: for PTX inputs the linker ignores it (with a
# warning from ``_translate_program_options``), so it cannot change the
# generated code and must not perturb the key. Two PTX compiles that
# differ only in ``numba_debug`` are the same compile.
# PTX compiles go through the Linker. When the driver (cuLink)
# backend is selected (nvJitLink unavailable), ``Program.compile``
# rejects a subset of options that nvJitLink would accept; reject
Expand Down
25 changes: 25 additions & 0 deletions cuda_core/docs/source/release/1.2.0-notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,34 @@ Fixes and enhancements
still reports ``NVVM_ERROR_INVALID_OPTION``.
(closes `#2570 <https://github.com/NVIDIA/cuda-python/issues/2570>`__)

- ``Program(ptx, "ptx", ProgramOptions(numba_debug=True))`` now warns that the
option is ignored instead of discarding it silently. ``numba_debug`` is an
NVVM/NVRTC *compiler* option: nvJitLink rejects it with
``ERROR_UNRECOGNIZED_OPTION`` under every spelling, and the driver's
``cuLink`` API has no corresponding ``CUjit_option``, so no linking backend
can honor it. PTX inputs are handed to the linker, and the option used to be
forwarded into ``LinkerOptions`` and then dropped without a diagnostic. The
warning is a :class:`UserWarning`, not a :class:`DeprecationWarning` --
``ProgramOptions.numba_debug`` is not deprecated and remains fully supported
on the NVVM and NVRTC compilation paths, where it takes effect; it is simply
inapplicable to a linking backend. The gate is truthiness, matching how the
NVVM path gates emission, so ``numba_debug=False`` asks for nothing and is
not worth a warning.
(closes `#2640 <https://github.com/NVIDIA/cuda-python/issues/2640>`__)

Deprecation Notices
-------------------

- ``LinkerOptions.numba_debug`` is deprecated and will be removed in
``cuda.core`` 2.0.0. It was exposed in ``cuda-core`` 1.1.0 but no linking
backend ever read it, so setting it has never had any effect;
``numba_debug`` is an NVVM/NVRTC compiler option with no linker equivalent.
Setting it now emits a :class:`DeprecationWarning` and the value continues
to be ignored. Removal waits for the next major version because the
:doc:`support policy <../support>` confines breaking API changes to
major-version boundaries. Use :attr:`ProgramOptions.numba_debug` on an NVVM
or NVRTC compilation path instead.

- Support for using ``cuda-core`` with Python 3.10 is deprecated and will be
removed in a future version. Python 3.10 reaches end of life in October 2026
per the `CPython support cycle <https://devguide.python.org/versions/>`_.
36 changes: 36 additions & 0 deletions cuda_core/tests/test_linker.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# SPDX-License-Identifier: Apache-2.0

import inspect
import warnings

import pytest

Expand Down Expand Up @@ -436,6 +437,41 @@ def test_prepare_driver_options_unsupported_raises(driver_binding, kwargs, match
opts._prepare_driver_options()


@pytest.mark.agent_authored(model="claude-opus-5")
@pytest.mark.parametrize("value", [True, False])
def test_numba_debug_warns_and_is_ignored(value):
"""No linking backend reads ``numba_debug``, so it is ignored -- but not
silently, which was the bug in #2640.

The gate is ``is not None``, not truthiness: it is the field itself that is
deprecated, so ``numba_debug=False`` earns the notice too even though it
asks for nothing.
"""
with pytest.warns(DeprecationWarning, match="numba_debug is not supported by any linking backend"):
opts = LinkerOptions(arch="sm_80", debug=True, numba_debug=value)
# Warned, not rejected, and the rest of the option set is untouched.
assert opts._prepare_nvjitlink_options(as_bytes=True) == [b"-arch=sm_80", b"-g"]


@pytest.mark.agent_authored(model="claude-opus-5")
def test_numba_debug_unset_does_not_warn():
"""The deprecation notice fires only when the field is explicitly set."""
with warnings.catch_warnings():
warnings.simplefilter("error", DeprecationWarning)
options = LinkerOptions(arch="sm_80", debug=True)._prepare_nvjitlink_options(as_bytes=True)
assert options == [b"-arch=sm_80", b"-g"]


@pytest.mark.agent_authored(model="claude-opus-5")
def test_numba_debug_ignored_by_driver_backend_too(driver_binding):
"""The cuLink driver API has no CUjit_option for numba_debug either, so it
is ignored there as well rather than reaching the driver."""
with pytest.warns(DeprecationWarning, match="numba_debug"):
opts = LinkerOptions(arch="sm_80", numba_debug=True)
formatted_options, option_keys = opts._prepare_driver_options()
assert not any("NUMBA" in str(key) for key in option_keys)


def test_linker_empty_object_codes_raises():
"""Linker with no ObjectCode raises ValueError."""
with pytest.raises(ValueError, match="At least one ObjectCode object must be provided"):
Expand Down
34 changes: 32 additions & 2 deletions cuda_core/tests/test_program.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,8 +316,10 @@ def test_cpp_program_pch_status_none_without_pch(init_cuda):
ProgramOptions(prec_div=True),
ProgramOptions(prec_sqrt=True),
ProgramOptions(fma=True),
# Plumb-through; no-op at link time. See #1287.
ProgramOptions(debug=True, numba_debug=True),
# ``numba_debug`` is deliberately absent: it was listed here as a link-time
# no-op (#1287), but no linker backend accepts it, so it was dropped
# silently (#2640). The PTX path now warns; see
# test_ptx_program_numba_debug_warns_and_is_ignored.
]
if not is_culink_backend:
options += [
Expand Down Expand Up @@ -870,6 +872,34 @@ def test_ptx_program_extra_sources_unsupported(ptx_code_object):
Program(ptx_code_object.code.decode(), "ptx", options)


@pytest.mark.agent_authored(model="claude-opus-5")
def test_ptx_program_numba_debug_warns_and_is_ignored(init_cuda, ptx_code_object):
"""PTX inputs go to the linker, which cannot honor numba_debug (#2640).

It used to be forwarded into ``LinkerOptions`` and dropped without a word,
so the compile appeared to succeed with the option applied. It is still
ignored -- no linker can do anything with it -- but no longer silently.

``UserWarning``, not ``DeprecationWarning``: ``ProgramOptions.numba_debug``
is not deprecated, it is supported on NVVM/NVRTC and merely inapplicable to
this backend.
"""
with pytest.warns(UserWarning, match="numba_debug is ignored for code_type='ptx'"):
program = Program(ptx_code_object.code.decode(), "ptx", ProgramOptions(numba_debug=True))
assert program.compile("cubin") is not None


@pytest.mark.agent_authored(model="claude-opus-5")
@pytest.mark.parametrize("value", [None, False])
def test_ptx_program_numba_debug_unset_or_false_does_not_warn(init_cuda, ptx_code_object, value):
"""The gate is truthiness: only an enabled ``numba_debug`` asks for
something the PTX path cannot deliver, so ``False`` is not worth a warning."""
with warnings.catch_warnings():
warnings.simplefilter("error", UserWarning)
program = Program(ptx_code_object.code.decode(), "ptx", ProgramOptions(numba_debug=value))
assert program.compile("cubin") is not None


def test_ptx_program_handle_is_linker_handle(init_cuda, ptx_code_object):
"""Program.handle for the PTX backend delegates to the linker handle."""
program = Program(ptx_code_object.code.decode(), "ptx")
Expand Down
14 changes: 14 additions & 0 deletions cuda_core/tests/test_program_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,20 @@ def test_make_program_cache_key_rejects_extra_sources_outside_nvvm(code_type, co
)


@pytest.mark.agent_authored(model="claude-opus-5")
@pytest.mark.parametrize("value", [True, False])
def test_make_program_cache_key_ignores_numba_debug_for_ptx(value):
"""``numba_debug`` cannot change PTX-path output -- no linker backend reads
it -- so it must not perturb the cache key (#2640).

If it did, two compiles producing byte-identical cubins would miss each
other in the cache.
"""
baseline = _make_key(code=".version 7.0", code_type="ptx", target_type="cubin", options=_opts())
with_flag = _make_key(code=".version 7.0", code_type="ptx", target_type="cubin", options=_opts(numba_debug=value))
assert with_flag == baseline


@pytest.mark.parametrize(
"kwargs, exc_type, match",
[
Expand Down
Loading