diff --git a/cuda_core/cuda/core/_linker.pyi b/cuda_core/cuda/core/_linker.pyi index 37e05fc7fe..42b08313f7 100644 --- a/cuda_core/cuda/core/_linker.pyi +++ b/cuda_core/cuda/core/_linker.pyi @@ -112,8 +112,7 @@ class LinkerOptions: Since the linker may choose to use nvJitLink or the driver APIs as the linking backend, not all options are applicable. When the system's installed nvJitLink is too old (<12.3), - not installed, or older than the CUDA driver major version, the driver APIs (cuLink) - will be used instead. + or not installed, the driver APIs (cuLink) will be used instead. Attributes ---------- diff --git a/cuda_core/cuda/core/_linker.pyx b/cuda_core/cuda/core/_linker.pyx index 172b176c84..753fa28b0d 100644 --- a/cuda_core/cuda/core/_linker.pyx +++ b/cuda_core/cuda/core/_linker.pyx @@ -39,7 +39,6 @@ from cuda.core._utils.cuda_utils import ( driver, is_sequence, ) -from cuda.core._utils.version import driver_version from cuda.core.typing import CompilerBackendType, ObjectCodeFormatType if TYPE_CHECKING: @@ -218,8 +217,7 @@ class LinkerOptions: Since the linker may choose to use nvJitLink or the driver APIs as the linking backend, not all options are applicable. When the system's installed nvJitLink is too old (<12.3), - not installed, or older than the CUDA driver major version, the driver APIs (cuLink) - will be used instead. + or not installed, the driver APIs (cuLink) will be used instead. Attributes ---------- @@ -696,22 +694,12 @@ def _decide_nvjitlink_or_driver() -> bool: from cuda.bindings._internal import nvjitlink if _nvjitlink_has_version_symbol(nvjitlink): - nvjitlink_version = nvjitlink_module.version() - driver_major = driver_version()[0] - if driver_major <= nvjitlink_version[0]: - _use_nvjitlink_backend = True - return False # Use nvjitlink - - warn_txt = ( - f"CUDA driver major version {driver_major} is newer than " - f"nvJitLink major version {nvjitlink_version[0]}; therefore " - f"{warn_txt_common} nvJitLink." - ) - else: - warn_txt = ( - f"{'nvJitLink*.dll' if sys.platform == 'win32' else 'libnvJitLink.so*'} is too old (<12.3)." - f" Therefore cuda.bindings.nvjitlink is not usable and {warn_txt_common} nvJitLink." - ) + _use_nvjitlink_backend = True + return False # Use nvjitlink + warn_txt = ( + f"{'nvJitLink*.dll' if sys.platform == 'win32' else 'libnvJitLink.so*'} is too old (<12.3)." + f" Therefore cuda.bindings.nvjitlink is not usable and {warn_txt_common} nvJitLink." + ) warn(warn_txt, stacklevel=2, category=RuntimeWarning) _use_nvjitlink_backend = False diff --git a/cuda_core/tests/test_optional_dependency_imports.py b/cuda_core/tests/test_optional_dependency_imports.py index 6759fd3cfa..02edcc9839 100644 --- a/cuda_core/tests/test_optional_dependency_imports.py +++ b/cuda_core/tests/test_optional_dependency_imports.py @@ -7,14 +7,6 @@ from cuda.core import _linker, _program -class FakeNvJitLinkModule: - def __init__(self, version): - self._version = version - - def version(self): - return self._version - - @pytest.fixture(autouse=True) def restore_optional_import_state(): saved_nvvm_module = _program._nvvm_module @@ -111,43 +103,3 @@ def fake__optional_cuda_import(modname, probe_function=None): assert use_driver_backend is True assert _linker._use_nvjitlink_backend is False - - -@pytest.mark.agent_authored(model="gpt-5") -@pytest.mark.parametrize( - ("driver_version", "nvjitlink_version"), - [ - ((12, 8, 0), (12, 9)), - ((12, 9, 0), (13, 0)), - ], -) -def test_decide_nvjitlink_or_driver_uses_nvjitlink_when_driver_is_not_newer( - monkeypatch, driver_version, nvjitlink_version -): - monkeypatch.setattr( - _linker, - "_optional_cuda_import", - lambda *_args, **_kwargs: FakeNvJitLinkModule(nvjitlink_version), - ) - monkeypatch.setattr(_linker, "_nvjitlink_has_version_symbol", lambda _nvjitlink: True) - monkeypatch.setattr(_linker, "driver_version", lambda: driver_version) - - assert _linker._decide_nvjitlink_or_driver() is False - assert _linker._use_nvjitlink_backend is True - - -@pytest.mark.agent_authored(model="gpt-5") -def test_decide_nvjitlink_or_driver_falls_back_when_driver_is_newer(monkeypatch): - monkeypatch.setattr( - _linker, - "_optional_cuda_import", - lambda *_args, **_kwargs: FakeNvJitLinkModule((12, 9)), - ) - monkeypatch.setattr(_linker, "_nvjitlink_has_version_symbol", lambda _nvjitlink: True) - monkeypatch.setattr(_linker, "driver_version", lambda: (13, 0, 0)) - - with pytest.warns(RuntimeWarning, match="is newer than nvJitLink major version"): - use_driver_backend = _linker._decide_nvjitlink_or_driver() - - assert use_driver_backend is True - assert _linker._use_nvjitlink_backend is False diff --git a/cuda_core/tests/test_program_cache.py b/cuda_core/tests/test_program_cache.py index 6b3f143a34..c305562dcb 100644 --- a/cuda_core/tests/test_program_cache.py +++ b/cuda_core/tests/test_program_cache.py @@ -375,6 +375,14 @@ def test_make_program_cache_key_ignores_name_expressions_for_non_nvrtc(code_type {"link_time_optimization": None}, id="lto_false_eq_none", ), + # ``time`` is a presence gate: the linker emits ``-time`` for any + # non-None value, so True / "path" produce the same flag. + pytest.param( + {"time": True}, + {"time": "timing.csv"}, + id="time_true_eq_path", + marks=pytest.mark.skipif(is_culink_backend, reason="-time is not supported in cuLink"), + ), # ``no_cache`` has an ``is True`` gate; False and None equivalent. pytest.param({"no_cache": False}, {"no_cache": None}, id="no_cache_false_eq_none"), ], @@ -393,18 +401,6 @@ def test_make_program_cache_key_ptx_linker_equivalent_options_hash_same(a, b, mo assert k_a == k_b -@pytest.mark.skipif(is_culink_backend, reason="test requires nvJitLink backend") -@pytest.mark.agent_authored(model="gpt-5") -def test_make_program_cache_key_ptx_nvjitlink_time_values_hash_same(monkeypatch): - """nvJitLink emits ``-time`` for any non-None value.""" - from cuda.core.utils import _program_cache - - monkeypatch.setattr(_program_cache._keys, "_linker_backend_and_version", lambda _use_driver: ("nvJitLink", "12030")) - k_true = _make_key(code=".version 7.0", code_type="ptx", options=_opts(time=True)) - k_path = _make_key(code=".version 7.0", code_type="ptx", options=_opts(time="timing.csv")) - assert k_true == k_path - - @pytest.mark.parametrize( "field, a, b", [ @@ -1014,9 +1010,10 @@ def test_make_program_cache_key_rejects_side_effect_options_nvrtc(option_kw, ext pytest.param({"time": "whatever.csv"}, id="time_path"), ], ) -@pytest.mark.skipif(is_culink_backend, reason="test requires nvJitLink backend") +@pytest.mark.skipif(is_culink_backend, reason="-time is not supported in cuLink") def test_make_program_cache_key_accepts_side_effect_options_for_ptx(option_kw): - """nvJitLink ``-time`` writes only to its info log, not the filesystem.""" + """The side-effect guard is NVRTC-specific: PTX (linker) and NVVM must + not be blocked by options whose side effects only apply under NVRTC.""" _make_key(code=".version 7.0", code_type="ptx", options=_opts(**option_kw)) # no raise