From 8b8b95c3261c3e90d97d4a5fe3fc5a5c2117ec73 Mon Sep 17 00:00:00 2001 From: brandon-b-miller Date: Tue, 17 Feb 2026 07:53:41 -0800 Subject: [PATCH 1/2] find libdevice via pathfinder --- numba_cuda/numba/cuda/cuda_paths.py | 95 ++++--------------- .../cuda/tests/nocuda/test_library_lookup.py | 48 ---------- 2 files changed, 18 insertions(+), 125 deletions(-) diff --git a/numba_cuda/numba/cuda/cuda_paths.py b/numba_cuda/numba/cuda/cuda_paths.py index 0b7f031d3..9c3e4133c 100644 --- a/numba_cuda/numba/cuda/cuda_paths.py +++ b/numba_cuda/numba/cuda/cuda_paths.py @@ -82,29 +82,27 @@ def _find_valid_path(options): return "", None -def _get_libdevice_path_decision(): - options = _build_options( - [ - ("Conda environment", get_libdevice_conda_path), - ("NVIDIA NVCC Wheel", get_libdevice_wheel_path), - ( - "CUDA_HOME", - lambda: get_cuda_home("nvvm", "libdevice", "libdevice.10.bc"), - ), - ( - "System", - lambda: get_system_ctk("nvvm", "libdevice", "libdevice.10.bc"), - ), - ] - ) - return _find_first_valid_lazy(options) +# Map cuda-pathfinder found_via to numba-cuda path source labels +_LIBDEVICE_FOUND_VIA_TO_LABEL = { + "site-packages": "NVIDIA NVCC Wheel", + "conda": "Conda environment", + "CUDA_HOME": "CUDA_HOME", +} def _get_libdevice_path(): - by, out = _get_libdevice_path_decision() - if not out: - return _env_path_tuple(by, None) - return _env_path_tuple(by, out) + """Get libdevice path and source using cuda-pathfinder's locate_bitcode_lib.""" + located = pathfinder.locate_bitcode_lib("device") + if located is not None: + by = _LIBDEVICE_FOUND_VIA_TO_LABEL.get( + located.found_via, located.found_via + ) + return _env_path_tuple(by, located.abs_path) + # Fallback: system CTK (pathfinder does not search /usr/local/cuda) + system_path = get_system_ctk("nvvm", "libdevice", "libdevice.10.bc") + if system_path and os.path.isfile(system_path): + return _env_path_tuple("System", system_path) + return _env_path_tuple("", None) def _cuda_static_libdir(): @@ -253,26 +251,6 @@ def get_conda_ctk_libdir(): return os.path.dirname(max(paths)) -def get_libdevice_conda_path(): - """Return path to directory containing the libdevice bitcode library.""" - is_conda_env = os.path.isdir(os.path.join(sys.prefix, "conda-meta")) - if not is_conda_env: - return None - - # Linux: nvvm/libdevice/libdevice.10.bc - # Windows: Library/nvvm/libdevice/libdevice.10.bc - libdevice_path = os.path.join( - sys.prefix, - "Library" if IS_WIN32 else "", - "nvvm", - "libdevice", - "libdevice.10.bc", - ) - if os.path.isfile(libdevice_path): - return libdevice_path - return None - - def get_wheel_static_libdir(): cuda_module_static_lib_dir = None # CUDA 12 @@ -432,43 +410,6 @@ def get_cuda_paths(): return d -def get_libdevice_wheel_path(): - libdevice_path = None - # CUDA 12 - nvvm_distribution = _get_distribution("nvidia-cuda-nvcc-cu12") - if nvvm_distribution is not None: - site_packages_path = nvvm_distribution.locate_file("") - libdevice_path = os.path.join( - site_packages_path, - "nvidia", - "cuda_nvcc", - "nvvm", - "libdevice", - "libdevice.10.bc", - ) - - # CUDA 13 - if libdevice_path is None: - nvvm_distribution = _get_distribution("nvidia-nvvm") - if ( - nvvm_distribution is not None - and nvvm_distribution.version.startswith("13.") - ): - site_packages_path = nvvm_distribution.locate_file("") - libdevice_path = os.path.join( - site_packages_path, - "nvidia", - "cu13", - "nvvm", - "libdevice", - "libdevice.10.bc", - ) - - if libdevice_path and os.path.isfile(libdevice_path): - return libdevice_path - return None - - def get_current_cuda_target_name(): """Determine conda's CTK target folder based on system and machine arch. diff --git a/numba_cuda/numba/cuda/tests/nocuda/test_library_lookup.py b/numba_cuda/numba/cuda/tests/nocuda/test_library_lookup.py index 83f9de5cf..be54e0ab5 100644 --- a/numba_cuda/numba/cuda/tests/nocuda/test_library_lookup.py +++ b/numba_cuda/numba/cuda/tests/nocuda/test_library_lookup.py @@ -16,9 +16,7 @@ skip_unless_conda_cudatoolkit, ) from numba.cuda.cuda_paths import ( - _get_libdevice_path_decision, _get_cudalib_dir_path_decision, - get_system_ctk, get_system_ctk_libdir, _find_cuda_home_from_lib_path, ) @@ -88,52 +86,6 @@ def check_lib_lookup(qout, qin): status = False -@skip_on_cudasim("Library detection unsupported in the simulator") -@unittest.skipUnless(has_mp_get_context, "mp.get_context not available") -@skip_unless_conda_cudatoolkit("test assumes conda installed cudatoolkit") -class TestLibDeviceLookUp(LibraryLookupBase): - def test_libdevice_path_decision(self): - # Check that the default is using conda environment - by, info, warns = self.remote_do(self.do_clear_envs) - if has_cuda: - self.assertEqual(by, "Conda environment") - else: - self.assertEqual(by, "") - self.assertIsNone(info) - self.assertFalse(warns) - # Check that CUDA_HOME works by removing conda-env - by, info, warns = self.remote_do(self.do_set_cuda_home) - self.assertEqual(by, "CUDA_HOME") - self.assertTrue( - info.startswith(os.path.join("mycudahome", "nvvm", "libdevice")) - ) - self.assertFalse(warns) - - if get_system_ctk("nvvm", "libdevice") is None: - # Fake remove conda environment so no cudatoolkit is available - by, info, warns = self.remote_do(self.do_clear_envs) - self.assertEqual(by, "") - self.assertIsNone(info) - self.assertFalse(warns) - else: - # Use system available cudatoolkit - by, info, warns = self.remote_do(self.do_clear_envs) - self.assertEqual(by, "System") - self.assertFalse(warns) - - @staticmethod - def do_clear_envs(): - remove_env("CUDA_HOME") - remove_env("CUDA_PATH") - return True, _get_libdevice_path_decision() - - @staticmethod - def do_set_cuda_home(): - os.environ["CUDA_HOME"] = os.path.join("mycudahome") - _fake_non_conda_env() - return True, _get_libdevice_path_decision() - - @skip_on_cudasim("Library detection unsupported in the simulator") @unittest.skipUnless(has_mp_get_context, "mp.get_context not available") @skip_unless_conda_cudatoolkit("test assumes conda installed cudatoolkit") From 71b8e742c8ecd19b47be7fede19eee95dead337f Mon Sep 17 00:00:00 2001 From: brandon-b-miller Date: Tue, 24 Feb 2026 08:50:41 -0800 Subject: [PATCH 2/2] pathfinder minimum --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index d9c2c5ab3..c985b0b7f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,13 +24,13 @@ dependencies = [ [project.optional-dependencies] cu12 = [ "cuda-bindings>=12.9.1,<13.0.0", - "cuda-pathfinder>=1.3.4,<2.0.0", + "cuda-pathfinder>=1.3.5,<2.0.0", # install nvcc for libNVVM "cuda-toolkit[cudart,nvcc,nvrtc,nvjitlink,cccl]==12.*", ] cu13 = [ "cuda-bindings==13.*", - "cuda-pathfinder>=1.3.4,<2.0.0", + "cuda-pathfinder>=1.3.5,<2.0.0", "cuda-toolkit[cudart,nvvm,nvrtc,nvjitlink,cccl]==13.*", ]