From fbdebfaf3939b92d14a7346d675bb519a1959c3b Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 22 Jun 2025 11:09:33 -0700 Subject: [PATCH 01/78] Move files WITHOUT trying to make anything work. --- .../cuda/bindings/_path_finder/README.md | 57 +------------------ .../cuda/path_finder/_dynamic_libs/README.md | 56 ++++++++++++++++++ .../find_nvidia_dynamic_library.py | 38 ++++++++++--- .../_dynamic_libs}/find_sub_dirs.py | 4 +- .../_dynamic_libs}/load_dl_common.py | 0 .../_dynamic_libs}/load_dl_linux.py | 4 +- .../_dynamic_libs}/load_dl_windows.py | 21 +++++-- .../load_nvidia_dynamic_library.py | 4 +- .../_dynamic_libs}/supported_libs.py | 8 ++- .../cuda/path_finder/nvidia_dynamic_libs.py | 2 + 10 files changed, 122 insertions(+), 72 deletions(-) create mode 100644 cuda_path_finder/cuda/path_finder/_dynamic_libs/README.md rename {cuda_bindings/cuda/bindings/_path_finder => cuda_path_finder/cuda/path_finder/_dynamic_libs}/find_nvidia_dynamic_library.py (82%) rename {cuda_bindings/cuda/bindings/_path_finder => cuda_path_finder/cuda/path_finder/_dynamic_libs}/find_sub_dirs.py (93%) rename {cuda_bindings/cuda/bindings/_path_finder => cuda_path_finder/cuda/path_finder/_dynamic_libs}/load_dl_common.py (100%) rename {cuda_bindings/cuda/bindings/_path_finder => cuda_path_finder/cuda/path_finder/_dynamic_libs}/load_dl_linux.py (96%) rename {cuda_bindings/cuda/bindings/_path_finder => cuda_path_finder/cuda/path_finder/_dynamic_libs}/load_dl_windows.py (85%) rename {cuda_bindings/cuda/bindings/_path_finder => cuda_path_finder/cuda/path_finder/_dynamic_libs}/load_nvidia_dynamic_library.py (98%) rename {cuda_bindings/cuda/bindings/_path_finder => cuda_path_finder/cuda/path_finder/_dynamic_libs}/supported_libs.py (97%) create mode 100644 cuda_path_finder/cuda/path_finder/nvidia_dynamic_libs.py diff --git a/cuda_bindings/cuda/bindings/_path_finder/README.md b/cuda_bindings/cuda/bindings/_path_finder/README.md index 1e115f2ed..0f33016cc 100644 --- a/cuda_bindings/cuda/bindings/_path_finder/README.md +++ b/cuda_bindings/cuda/bindings/_path_finder/README.md @@ -1,56 +1,5 @@ -# `cuda.bindings.path_finder` Module +# The `cuda.bindings.path_finder` module was moved! -## Public API (Work in Progress) +## New location -Currently exposes two primary interfaces: - -``` -cuda.bindings.path_finder._SUPPORTED_LIBNAMES # ('nvJitLink', 'nvrtc', 'nvvm') -cuda.bindings.path_finder._load_nvidia_dynamic_library(libname: str) -> LoadedDL -``` - -**Note:** -These APIs are prefixed with an underscore because they are considered -experimental while undergoing active development, although already -reasonably well-tested through CI pipelines. - -## Library Loading Search Priority - -The `load_nvidia_dynamic_library()` function implements a hierarchical search -strategy for locating NVIDIA shared libraries: - -0. **Check if a library was loaded into the process already by some other means.** - - If yes, there is no alternative to skipping the rest of the search logic. - The absolute path of the already loaded library will be returned, along - with the handle to the library. - -1. **NVIDIA Python wheels** - - Scans all site-packages to find libraries installed via NVIDIA Python wheels. - -2. **OS default mechanisms / Conda environments** - - Falls back to native loader: - - `dlopen()` on Linux - - `LoadLibraryW()` on Windows - - Conda installations are expected to be discovered: - - Linux: Via `$ORIGIN/../lib` on `RPATH` (of the `python` binary; - note that this preempts `LD_LIBRARY_PATH` and `/etc/ld.so.conf.d/`) - - Windows: Via `%CONDA_PREFIX%\Library\bin` on system `PATH` - - CTK installations with system config updates are expected to be discovered: - - Linux: Via `/etc/ld.so.conf.d/*cuda*.conf` - - Windows: Via `C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\vX.Y\bin` on system `PATH` - -3. **Environment variables** - - Relies on `CUDA_HOME` or `CUDA_PATH` environment variables if set - (in that order). - -Note that the search is done on a per-library basis. There is no centralized -mechanism that ensures all libraries are found in the same way. - -## Maintenance Requirements - -These key components must be updated for new CUDA Toolkit releases: - -- `supported_libs.SUPPORTED_LIBNAMES` -- `supported_libs.SUPPORTED_WINDOWS_DLLS` -- `supported_libs.SUPPORTED_LINUX_SONAMES` -- `supported_libs.EXPECTED_LIB_SYMBOLS` +`cuda.path_finder` diff --git a/cuda_path_finder/cuda/path_finder/_dynamic_libs/README.md b/cuda_path_finder/cuda/path_finder/_dynamic_libs/README.md new file mode 100644 index 000000000..1e115f2ed --- /dev/null +++ b/cuda_path_finder/cuda/path_finder/_dynamic_libs/README.md @@ -0,0 +1,56 @@ +# `cuda.bindings.path_finder` Module + +## Public API (Work in Progress) + +Currently exposes two primary interfaces: + +``` +cuda.bindings.path_finder._SUPPORTED_LIBNAMES # ('nvJitLink', 'nvrtc', 'nvvm') +cuda.bindings.path_finder._load_nvidia_dynamic_library(libname: str) -> LoadedDL +``` + +**Note:** +These APIs are prefixed with an underscore because they are considered +experimental while undergoing active development, although already +reasonably well-tested through CI pipelines. + +## Library Loading Search Priority + +The `load_nvidia_dynamic_library()` function implements a hierarchical search +strategy for locating NVIDIA shared libraries: + +0. **Check if a library was loaded into the process already by some other means.** + - If yes, there is no alternative to skipping the rest of the search logic. + The absolute path of the already loaded library will be returned, along + with the handle to the library. + +1. **NVIDIA Python wheels** + - Scans all site-packages to find libraries installed via NVIDIA Python wheels. + +2. **OS default mechanisms / Conda environments** + - Falls back to native loader: + - `dlopen()` on Linux + - `LoadLibraryW()` on Windows + - Conda installations are expected to be discovered: + - Linux: Via `$ORIGIN/../lib` on `RPATH` (of the `python` binary; + note that this preempts `LD_LIBRARY_PATH` and `/etc/ld.so.conf.d/`) + - Windows: Via `%CONDA_PREFIX%\Library\bin` on system `PATH` + - CTK installations with system config updates are expected to be discovered: + - Linux: Via `/etc/ld.so.conf.d/*cuda*.conf` + - Windows: Via `C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\vX.Y\bin` on system `PATH` + +3. **Environment variables** + - Relies on `CUDA_HOME` or `CUDA_PATH` environment variables if set + (in that order). + +Note that the search is done on a per-library basis. There is no centralized +mechanism that ensures all libraries are found in the same way. + +## Maintenance Requirements + +These key components must be updated for new CUDA Toolkit releases: + +- `supported_libs.SUPPORTED_LIBNAMES` +- `supported_libs.SUPPORTED_WINDOWS_DLLS` +- `supported_libs.SUPPORTED_LINUX_SONAMES` +- `supported_libs.EXPECTED_LIB_SYMBOLS` diff --git a/cuda_bindings/cuda/bindings/_path_finder/find_nvidia_dynamic_library.py b/cuda_path_finder/cuda/path_finder/_dynamic_libs/find_nvidia_dynamic_library.py similarity index 82% rename from cuda_bindings/cuda/bindings/_path_finder/find_nvidia_dynamic_library.py rename to cuda_path_finder/cuda/path_finder/_dynamic_libs/find_nvidia_dynamic_library.py index 9835b72d0..8c8106cdc 100644 --- a/cuda_bindings/cuda/bindings/_path_finder/find_nvidia_dynamic_library.py +++ b/cuda_path_finder/cuda/path_finder/_dynamic_libs/find_nvidia_dynamic_library.py @@ -18,7 +18,11 @@ def _no_such_file_in_sub_dirs(sub_dirs, file_wild, error_messages, attachments): def _find_so_using_nvidia_lib_dirs(libname, so_basename, error_messages, attachments): - nvidia_sub_dirs = ("nvidia", "*", "nvvm", "lib64") if libname == "nvvm" else ("nvidia", "*", "lib") + nvidia_sub_dirs = ( + ("nvidia", "*", "nvvm", "lib64") + if libname == "nvvm" + else ("nvidia", "*", "lib") + ) file_wild = so_basename + "*" for lib_dir in find_sub_dirs_all_sitepackages(nvidia_sub_dirs): # First look for an exact match @@ -43,13 +47,19 @@ def _find_dll_under_dir(dirpath, file_wild): return None -def _find_dll_using_nvidia_bin_dirs(libname, lib_searched_for, error_messages, attachments): - nvidia_sub_dirs = ("nvidia", "*", "nvvm", "bin") if libname == "nvvm" else ("nvidia", "*", "bin") +def _find_dll_using_nvidia_bin_dirs( + libname, lib_searched_for, error_messages, attachments +): + nvidia_sub_dirs = ( + ("nvidia", "*", "nvvm", "bin") if libname == "nvvm" else ("nvidia", "*", "bin") + ) for bin_dir in find_sub_dirs_all_sitepackages(nvidia_sub_dirs): dll_name = _find_dll_under_dir(bin_dir, lib_searched_for) if dll_name is not None: return dll_name - _no_such_file_in_sub_dirs(nvidia_sub_dirs, lib_searched_for, error_messages, attachments) + _no_such_file_in_sub_dirs( + nvidia_sub_dirs, lib_searched_for, error_messages, attachments + ) return None @@ -119,13 +129,19 @@ def __init__(self, libname: str): self.lib_searched_for = f"{libname}*.dll" if self.abs_path is None: self.abs_path = _find_dll_using_nvidia_bin_dirs( - libname, self.lib_searched_for, self.error_messages, self.attachments + libname, + self.lib_searched_for, + self.error_messages, + self.attachments, ) else: self.lib_searched_for = f"lib{libname}.so" if self.abs_path is None: self.abs_path = _find_so_using_nvidia_lib_dirs( - libname, self.lib_searched_for, self.error_messages, self.attachments + libname, + self.lib_searched_for, + self.error_messages, + self.attachments, ) def retry_with_cuda_home_priority_last(self): @@ -133,11 +149,17 @@ def retry_with_cuda_home_priority_last(self): if cuda_home_lib_dir is not None: if IS_WINDOWS: self.abs_path = _find_dll_using_lib_dir( - cuda_home_lib_dir, self.libname, self.error_messages, self.attachments + cuda_home_lib_dir, + self.libname, + self.error_messages, + self.attachments, ) else: self.abs_path = _find_so_using_lib_dir( - cuda_home_lib_dir, self.lib_searched_for, self.error_messages, self.attachments + cuda_home_lib_dir, + self.lib_searched_for, + self.error_messages, + self.attachments, ) def raise_if_abs_path_is_None(self): diff --git a/cuda_bindings/cuda/bindings/_path_finder/find_sub_dirs.py b/cuda_path_finder/cuda/path_finder/_dynamic_libs/find_sub_dirs.py similarity index 93% rename from cuda_bindings/cuda/bindings/_path_finder/find_sub_dirs.py rename to cuda_path_finder/cuda/path_finder/_dynamic_libs/find_sub_dirs.py index 810132625..76f17d151 100644 --- a/cuda_bindings/cuda/bindings/_path_finder/find_sub_dirs.py +++ b/cuda_path_finder/cuda/path_finder/_dynamic_libs/find_sub_dirs.py @@ -49,4 +49,6 @@ def find_sub_dirs_sys_path(sub_dirs): def find_sub_dirs_all_sitepackages(sub_dirs): - return find_sub_dirs((site.getusersitepackages(),) + tuple(site.getsitepackages()), sub_dirs) + return find_sub_dirs( + (site.getusersitepackages(),) + tuple(site.getsitepackages()), sub_dirs + ) diff --git a/cuda_bindings/cuda/bindings/_path_finder/load_dl_common.py b/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_common.py similarity index 100% rename from cuda_bindings/cuda/bindings/_path_finder/load_dl_common.py rename to cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_common.py diff --git a/cuda_bindings/cuda/bindings/_path_finder/load_dl_linux.py b/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_linux.py similarity index 96% rename from cuda_bindings/cuda/bindings/_path_finder/load_dl_linux.py rename to cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_linux.py index b9f3839e1..2fb52f8c0 100644 --- a/cuda_bindings/cuda/bindings/_path_finder/load_dl_linux.py +++ b/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_linux.py @@ -78,7 +78,9 @@ def check_if_already_loaded_from_elsewhere(libname: str) -> Optional[LoadedDL]: except OSError: continue else: - return LoadedDL(handle._handle, abs_path_for_dynamic_library(libname, handle), True) + return LoadedDL( + handle._handle, abs_path_for_dynamic_library(libname, handle), True + ) return None diff --git a/cuda_bindings/cuda/bindings/_path_finder/load_dl_windows.py b/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_windows.py similarity index 85% rename from cuda_bindings/cuda/bindings/_path_finder/load_dl_windows.py rename to cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_windows.py index 0d13680a6..814b3c654 100644 --- a/cuda_bindings/cuda/bindings/_path_finder/load_dl_windows.py +++ b/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_windows.py @@ -30,7 +30,9 @@ def add_dll_directory(dll_abs_path: str) -> None: os.add_dll_directory(dirpath) # Update PATH as a fallback for dependent DLL resolution curr_path = os.environ.get("PATH") - os.environ["PATH"] = dirpath if curr_path is None else os.pathsep.join((curr_path, dirpath)) + os.environ["PATH"] = ( + dirpath if curr_path is None else os.pathsep.join((curr_path, dirpath)) + ) def abs_path_for_dynamic_library(libname: str, handle: pywintypes.HANDLE) -> str: @@ -38,7 +40,9 @@ def abs_path_for_dynamic_library(libname: str, handle: pywintypes.HANDLE) -> str try: return win32api.GetModuleFileName(handle) except Exception as e: - raise RuntimeError(f"GetModuleFileName failed for {libname!r} (exception type: {type(e)})") from e + raise RuntimeError( + f"GetModuleFileName failed for {libname!r} (exception type: {type(e)})" + ) from e def check_if_already_loaded_from_elsewhere(libname: str) -> Optional[LoadedDL]: @@ -85,7 +89,9 @@ def load_with_system_search(libname: str, _unused: str) -> Optional[LoadedDL]: except pywintypes.error: continue else: - return LoadedDL(handle, abs_path_for_dynamic_library(libname, handle), False) + return LoadedDL( + handle, abs_path_for_dynamic_library(libname, handle), False + ) return None @@ -103,12 +109,17 @@ def load_with_abs_path(libname: str, found_path: str) -> LoadedDL: Raises: RuntimeError: If the DLL cannot be loaded """ - from cuda.bindings._path_finder.supported_libs import LIBNAMES_REQUIRING_OS_ADD_DLL_DIRECTORY + from cuda.bindings._path_finder.supported_libs import ( + LIBNAMES_REQUIRING_OS_ADD_DLL_DIRECTORY, + ) if libname in LIBNAMES_REQUIRING_OS_ADD_DLL_DIRECTORY: add_dll_directory(found_path) - flags = WINBASE_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | WINBASE_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR + flags = ( + WINBASE_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS + | WINBASE_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR + ) try: handle = win32api.LoadLibraryEx(found_path, 0, flags) except pywintypes.error as e: diff --git a/cuda_bindings/cuda/bindings/_path_finder/load_nvidia_dynamic_library.py b/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_nvidia_dynamic_library.py similarity index 98% rename from cuda_bindings/cuda/bindings/_path_finder/load_nvidia_dynamic_library.py rename to cuda_path_finder/cuda/path_finder/_dynamic_libs/load_nvidia_dynamic_library.py index f8fe5ce4a..de7ac6522 100644 --- a/cuda_bindings/cuda/bindings/_path_finder/load_nvidia_dynamic_library.py +++ b/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_nvidia_dynamic_library.py @@ -3,7 +3,9 @@ import functools -from cuda.bindings._path_finder.find_nvidia_dynamic_library import _find_nvidia_dynamic_library +from cuda.bindings._path_finder.find_nvidia_dynamic_library import ( + _find_nvidia_dynamic_library, +) from cuda.bindings._path_finder.load_dl_common import LoadedDL, load_dependencies from cuda.bindings._path_finder.supported_libs import IS_WINDOWS diff --git a/cuda_bindings/cuda/bindings/_path_finder/supported_libs.py b/cuda_path_finder/cuda/path_finder/_dynamic_libs/supported_libs.py similarity index 97% rename from cuda_bindings/cuda/bindings/_path_finder/supported_libs.py rename to cuda_path_finder/cuda/path_finder/_dynamic_libs/supported_libs.py index 63bde282f..9225ad932 100644 --- a/cuda_bindings/cuda/bindings/_path_finder/supported_libs.py +++ b/cuda_path_finder/cuda/path_finder/_dynamic_libs/supported_libs.py @@ -55,11 +55,15 @@ # "cufile_rdma", # Requires libmlx5.so ) -PARTIALLY_SUPPORTED_LIBNAMES_LINUX = PARTIALLY_SUPPORTED_LIBNAMES_COMMON + PARTIALLY_SUPPORTED_LIBNAMES_LINUX_ONLY +PARTIALLY_SUPPORTED_LIBNAMES_LINUX = ( + PARTIALLY_SUPPORTED_LIBNAMES_COMMON + PARTIALLY_SUPPORTED_LIBNAMES_LINUX_ONLY +) PARTIALLY_SUPPORTED_LIBNAMES_WINDOWS_ONLY = () -PARTIALLY_SUPPORTED_LIBNAMES_WINDOWS = PARTIALLY_SUPPORTED_LIBNAMES_COMMON + PARTIALLY_SUPPORTED_LIBNAMES_WINDOWS_ONLY +PARTIALLY_SUPPORTED_LIBNAMES_WINDOWS = ( + PARTIALLY_SUPPORTED_LIBNAMES_COMMON + PARTIALLY_SUPPORTED_LIBNAMES_WINDOWS_ONLY +) PARTIALLY_SUPPORTED_LIBNAMES_ALL = ( PARTIALLY_SUPPORTED_LIBNAMES_COMMON diff --git a/cuda_path_finder/cuda/path_finder/nvidia_dynamic_libs.py b/cuda_path_finder/cuda/path_finder/nvidia_dynamic_libs.py new file mode 100644 index 000000000..71792e009 --- /dev/null +++ b/cuda_path_finder/cuda/path_finder/nvidia_dynamic_libs.py @@ -0,0 +1,2 @@ +# Copyright 2025 NVIDIA Corporation. All rights reserved. +# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE From 731256deb2d34195f4fa43e852f62f63fef0f03d Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 22 Jun 2025 11:43:38 -0700 Subject: [PATCH 02/78] =?UTF-8?q?First=20pass=20changing=20imports=20from?= =?UTF-8?q?=20cuda.bindings=20=E2=86=92=20cuda.path=5Ffinder=20WITHOUT=20t?= =?UTF-8?q?rying=20to=20make=20anything=20work.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cuda_bindings/cuda/bindings/path_finder.py | 7 ++--- .../cuda/path_finder/_dynamic_libs/README.md | 29 ++++++++----------- .../find_nvidia_dynamic_library.py | 7 +++-- .../_dynamic_libs/load_dl_common.py | 15 +++------- .../_dynamic_libs/load_dl_linux.py | 6 ++-- .../_dynamic_libs/load_dl_windows.py | 8 ++--- .../load_nvidia_dynamic_library.py | 18 ++++++------ ...orted_libs.py => supported_nvidia_libs.py} | 0 .../cuda/path_finder/nvidia_dynamic_libs.py | 7 +++++ 9 files changed, 46 insertions(+), 51 deletions(-) rename cuda_path_finder/cuda/path_finder/_dynamic_libs/{supported_libs.py => supported_nvidia_libs.py} (100%) diff --git a/cuda_bindings/cuda/bindings/path_finder.py b/cuda_bindings/cuda/bindings/path_finder.py index 28badd025..de88538e4 100644 --- a/cuda_bindings/cuda/bindings/path_finder.py +++ b/cuda_bindings/cuda/bindings/path_finder.py @@ -1,11 +1,8 @@ # Copyright 2024-2025 NVIDIA Corporation. All rights reserved. -# # SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE -from cuda.bindings._path_finder.load_nvidia_dynamic_library import ( - load_nvidia_dynamic_library as _load_nvidia_dynamic_library, -) -from cuda.bindings._path_finder.supported_libs import SUPPORTED_LIBNAMES as _SUPPORTED_LIBNAMES +from cuda.path_finder.nvidia_dynamic_libs import SUPPORTED_LIBNAMES as _SUPPORTED_LIBNAMES +from cuda.path_finder.nvidia_dynamic_libs import load_lib as _load_nvidia_dynamic_library __all__ = [ "_load_nvidia_dynamic_library", diff --git a/cuda_path_finder/cuda/path_finder/_dynamic_libs/README.md b/cuda_path_finder/cuda/path_finder/_dynamic_libs/README.md index 1e115f2ed..1b33b1421 100644 --- a/cuda_path_finder/cuda/path_finder/_dynamic_libs/README.md +++ b/cuda_path_finder/cuda/path_finder/_dynamic_libs/README.md @@ -1,23 +1,18 @@ -# `cuda.bindings.path_finder` Module +# `cuda.path_finder` Module ## Public API (Work in Progress) Currently exposes two primary interfaces: ``` -cuda.bindings.path_finder._SUPPORTED_LIBNAMES # ('nvJitLink', 'nvrtc', 'nvvm') -cuda.bindings.path_finder._load_nvidia_dynamic_library(libname: str) -> LoadedDL +cuda.path_finder.SUPPORTED_LIBNAMES # ('nvJitLink', 'nvrtc', 'nvvm') +cuda.path_finder.nvidia_dynamic_libs.load_lib(libname: str) -> LoadedDL ``` -**Note:** -These APIs are prefixed with an underscore because they are considered -experimental while undergoing active development, although already -reasonably well-tested through CI pipelines. +## Dynamic Library Loading Search Priority -## Library Loading Search Priority - -The `load_nvidia_dynamic_library()` function implements a hierarchical search -strategy for locating NVIDIA shared libraries: +The `cuda.path_finder.nvidia_dynamic_libs.load_lib` function implements a +hierarchical search strategy for locating NVIDIA shared libraries: 0. **Check if a library was loaded into the process already by some other means.** - If yes, there is no alternative to skipping the rest of the search logic. @@ -43,14 +38,14 @@ strategy for locating NVIDIA shared libraries: - Relies on `CUDA_HOME` or `CUDA_PATH` environment variables if set (in that order). -Note that the search is done on a per-library basis. There is no centralized -mechanism that ensures all libraries are found in the same way. +Note that the search is done on a per-library basis. Currently there is no +centralized mechanism that ensures all libraries are found in the same way. ## Maintenance Requirements These key components must be updated for new CUDA Toolkit releases: -- `supported_libs.SUPPORTED_LIBNAMES` -- `supported_libs.SUPPORTED_WINDOWS_DLLS` -- `supported_libs.SUPPORTED_LINUX_SONAMES` -- `supported_libs.EXPECTED_LIB_SYMBOLS` +- `supported_nvidia_libs.SUPPORTED_LIBNAMES` +- `supported_nvidia_libs.SUPPORTED_WINDOWS_DLLS` +- `supported_nvidia_libs.SUPPORTED_LINUX_SONAMES` +- `supported_nvidia_libs.EXPECTED_LIB_SYMBOLS` diff --git a/cuda_path_finder/cuda/path_finder/_dynamic_libs/find_nvidia_dynamic_library.py b/cuda_path_finder/cuda/path_finder/_dynamic_libs/find_nvidia_dynamic_library.py index 8c8106cdc..053be9937 100644 --- a/cuda_path_finder/cuda/path_finder/_dynamic_libs/find_nvidia_dynamic_library.py +++ b/cuda_path_finder/cuda/path_finder/_dynamic_libs/find_nvidia_dynamic_library.py @@ -5,8 +5,11 @@ import glob import os -from cuda.bindings._path_finder.find_sub_dirs import find_sub_dirs_all_sitepackages -from cuda.bindings._path_finder.supported_libs import IS_WINDOWS, is_suppressed_dll_file +from cuda.path_finder._dynamic_libs.find_sub_dirs import find_sub_dirs_all_sitepackages +from cuda.path_finder._dynamic_libs.supported_nvidia_libs import ( + IS_WINDOWS, + is_suppressed_dll_file, +) def _no_such_file_in_sub_dirs(sub_dirs, file_wild, error_messages, attachments): diff --git a/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_common.py b/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_common.py index 034b9d433..80a7547a4 100644 --- a/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_common.py +++ b/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_common.py @@ -4,7 +4,10 @@ from dataclasses import dataclass from typing import Callable, Optional -from cuda.bindings._path_finder.supported_libs import DIRECT_DEPENDENCIES, IS_WINDOWS +from cuda.path_finder._dynamic_libs.supported_nvidia_libs import ( + DIRECT_DEPENDENCIES, + IS_WINDOWS, +) if IS_WINDOWS: import pywintypes @@ -22,15 +25,5 @@ class LoadedDL: def load_dependencies(libname: str, load_func: Callable[[str], LoadedDL]) -> None: - """Load all dependencies for a given library. - - Args: - libname: The name of the library whose dependencies should be loaded - load_func: The function to use for loading libraries (e.g. load_nvidia_dynamic_library) - - Example: - >>> load_dependencies("cudart", load_nvidia_dynamic_library) - # This will load all dependencies of cudart using the provided loading function - """ for dep in DIRECT_DEPENDENCIES.get(libname, ()): load_func(dep) diff --git a/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_linux.py b/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_linux.py index 2fb52f8c0..9aa32b799 100644 --- a/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_linux.py +++ b/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_linux.py @@ -6,7 +6,7 @@ import os from typing import Optional -from cuda.bindings._path_finder.load_dl_common import LoadedDL +from cuda.path_finder._dynamic_libs.load_dl_common import LoadedDL CDLL_MODE = os.RTLD_NOW | os.RTLD_GLOBAL @@ -40,7 +40,7 @@ def abs_path_for_dynamic_library(libname: str, handle: ctypes.CDLL) -> Optional[ Raises: OSError: If dladdr fails to get information about the symbol """ - from cuda.bindings._path_finder.supported_libs import EXPECTED_LIB_SYMBOLS + from cuda.path_finder.supported_nvidia_libs import EXPECTED_LIB_SYMBOLS for symbol_name in EXPECTED_LIB_SYMBOLS[libname]: symbol = getattr(handle, symbol_name, None) @@ -70,7 +70,7 @@ def check_if_already_loaded_from_elsewhere(libname: str) -> Optional[LoadedDL]: >>> if loaded is not None: ... print(f"Library already loaded from {loaded.abs_path}") """ - from cuda.bindings._path_finder.supported_libs import SUPPORTED_LINUX_SONAMES + from cuda.path_finder.supported_nvidia_libs import SUPPORTED_LINUX_SONAMES for soname in SUPPORTED_LINUX_SONAMES.get(libname, ()): try: diff --git a/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_windows.py b/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_windows.py index 814b3c654..49fcc3b1f 100644 --- a/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_windows.py +++ b/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_windows.py @@ -6,7 +6,7 @@ import pywintypes import win32api -from cuda.bindings._path_finder.load_dl_common import LoadedDL +from cuda.path_finder._dynamic_libs.load_dl_common import LoadedDL # Mirrors WinBase.h (unfortunately not defined already elsewhere) WINBASE_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x00000100 @@ -59,7 +59,7 @@ def check_if_already_loaded_from_elsewhere(libname: str) -> Optional[LoadedDL]: >>> if loaded is not None: ... print(f"Library already loaded from {loaded.abs_path}") """ - from cuda.bindings._path_finder.supported_libs import SUPPORTED_WINDOWS_DLLS + from cuda.path_finder.supported_nvidia_libs import SUPPORTED_WINDOWS_DLLS for dll_name in SUPPORTED_WINDOWS_DLLS.get(libname, ()): try: @@ -81,7 +81,7 @@ def load_with_system_search(libname: str, _unused: str) -> Optional[LoadedDL]: Returns: A LoadedDL object if successful, None if the library cannot be loaded """ - from cuda.bindings._path_finder.supported_libs import SUPPORTED_WINDOWS_DLLS + from cuda.path_finder.supported_nvidia_libs import SUPPORTED_WINDOWS_DLLS for dll_name in SUPPORTED_WINDOWS_DLLS.get(libname, ()): try: @@ -109,7 +109,7 @@ def load_with_abs_path(libname: str, found_path: str) -> LoadedDL: Raises: RuntimeError: If the DLL cannot be loaded """ - from cuda.bindings._path_finder.supported_libs import ( + from cuda.path_finder.supported_nvidia_libs import ( LIBNAMES_REQUIRING_OS_ADD_DLL_DIRECTORY, ) diff --git a/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_nvidia_dynamic_library.py b/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_nvidia_dynamic_library.py index de7ac6522..1f5f7587b 100644 --- a/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_nvidia_dynamic_library.py +++ b/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_nvidia_dynamic_library.py @@ -3,27 +3,27 @@ import functools -from cuda.bindings._path_finder.find_nvidia_dynamic_library import ( +from cuda.path_finder._dynamic_libs.find_nvidia_dynamic_library import ( _find_nvidia_dynamic_library, ) -from cuda.bindings._path_finder.load_dl_common import LoadedDL, load_dependencies -from cuda.bindings._path_finder.supported_libs import IS_WINDOWS +from cuda.path_finder._dynamic_libs.load_dl_common import LoadedDL, load_dependencies +from cuda.path_finder._dynamic_libs.supported_nvidia_libs import IS_WINDOWS if IS_WINDOWS: - from cuda.bindings._path_finder.load_dl_windows import ( + from cuda.path_finder._dynamic_libs.load_dl_windows import ( check_if_already_loaded_from_elsewhere, load_with_abs_path, load_with_system_search, ) else: - from cuda.bindings._path_finder.load_dl_linux import ( + from cuda.path_finder._dynamic_libs.load_dl_linux import ( check_if_already_loaded_from_elsewhere, load_with_abs_path, load_with_system_search, ) -def _load_nvidia_dynamic_library_no_cache(libname: str) -> LoadedDL: +def _load_lib_no_cache(libname: str) -> LoadedDL: # Check whether the library is already loaded into the current process by # some other component. This check uses OS-level mechanisms (e.g., # dlopen on Linux, GetModuleHandle on Windows). @@ -32,7 +32,7 @@ def _load_nvidia_dynamic_library_no_cache(libname: str) -> LoadedDL: return loaded # Load dependencies first - load_dependencies(libname, load_nvidia_dynamic_library) + load_dependencies(libname, load_lib) # Find the library path found = _find_nvidia_dynamic_library(libname) @@ -48,7 +48,7 @@ def _load_nvidia_dynamic_library_no_cache(libname: str) -> LoadedDL: @functools.cache -def load_nvidia_dynamic_library(libname: str) -> LoadedDL: +def load_lib(libname: str) -> LoadedDL: """Load a NVIDIA dynamic library by name. Args: @@ -60,4 +60,4 @@ def load_nvidia_dynamic_library(libname: str) -> LoadedDL: Raises: RuntimeError: If the library cannot be found or loaded """ - return _load_nvidia_dynamic_library_no_cache(libname) + return _load_lib_no_cache(libname) diff --git a/cuda_path_finder/cuda/path_finder/_dynamic_libs/supported_libs.py b/cuda_path_finder/cuda/path_finder/_dynamic_libs/supported_nvidia_libs.py similarity index 100% rename from cuda_path_finder/cuda/path_finder/_dynamic_libs/supported_libs.py rename to cuda_path_finder/cuda/path_finder/_dynamic_libs/supported_nvidia_libs.py diff --git a/cuda_path_finder/cuda/path_finder/nvidia_dynamic_libs.py b/cuda_path_finder/cuda/path_finder/nvidia_dynamic_libs.py index 71792e009..5f8d25431 100644 --- a/cuda_path_finder/cuda/path_finder/nvidia_dynamic_libs.py +++ b/cuda_path_finder/cuda/path_finder/nvidia_dynamic_libs.py @@ -1,2 +1,9 @@ # Copyright 2025 NVIDIA Corporation. All rights reserved. # SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE + +from cuda.path_finder._dynamic_libs.load_nvidia_dynamic_library import ( + load_nvidia_dynamic_library as load_lib, +) +from cuda.path_finder._dynamic_libs.supported_nvidia_libs import SUPPORTED_LIBNAMES + +__all__ = ["load_lib", "SUPPORTED_LIBNAMES"] From 6e0ec6c260bff000ac6431f0821b21bb0a6f2d70 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 22 Jun 2025 11:46:51 -0700 Subject: [PATCH 03/78] Move README.md one level up. --- cuda_path_finder/cuda/path_finder/{_dynamic_libs => }/README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename cuda_path_finder/cuda/path_finder/{_dynamic_libs => }/README.md (100%) diff --git a/cuda_path_finder/cuda/path_finder/_dynamic_libs/README.md b/cuda_path_finder/cuda/path_finder/README.md similarity index 100% rename from cuda_path_finder/cuda/path_finder/_dynamic_libs/README.md rename to cuda_path_finder/cuda/path_finder/README.md From 07e138509fec00993fcb24bb43395a834520721a Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 22 Jun 2025 11:51:58 -0700 Subject: [PATCH 04/78] =?UTF-8?q?Move=20find=5Fsub=5Fdirs.py=20=E2=86=92?= =?UTF-8?q?=20../=5Futils/find=5Fsub=5Fdirs.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../path_finder/_dynamic_libs/find_nvidia_dynamic_library.py | 2 +- .../cuda/path_finder/{_dynamic_libs => _utils}/find_sub_dirs.py | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename cuda_path_finder/cuda/path_finder/{_dynamic_libs => _utils}/find_sub_dirs.py (100%) diff --git a/cuda_path_finder/cuda/path_finder/_dynamic_libs/find_nvidia_dynamic_library.py b/cuda_path_finder/cuda/path_finder/_dynamic_libs/find_nvidia_dynamic_library.py index 053be9937..b4273901e 100644 --- a/cuda_path_finder/cuda/path_finder/_dynamic_libs/find_nvidia_dynamic_library.py +++ b/cuda_path_finder/cuda/path_finder/_dynamic_libs/find_nvidia_dynamic_library.py @@ -5,11 +5,11 @@ import glob import os -from cuda.path_finder._dynamic_libs.find_sub_dirs import find_sub_dirs_all_sitepackages from cuda.path_finder._dynamic_libs.supported_nvidia_libs import ( IS_WINDOWS, is_suppressed_dll_file, ) +from cuda.path_finder._utils.find_sub_dirs import find_sub_dirs_all_sitepackages def _no_such_file_in_sub_dirs(sub_dirs, file_wild, error_messages, attachments): diff --git a/cuda_path_finder/cuda/path_finder/_dynamic_libs/find_sub_dirs.py b/cuda_path_finder/cuda/path_finder/_utils/find_sub_dirs.py similarity index 100% rename from cuda_path_finder/cuda/path_finder/_dynamic_libs/find_sub_dirs.py rename to cuda_path_finder/cuda/path_finder/_utils/find_sub_dirs.py From 68aa8d5a2fcc24fa2bfbff4a131936a72f532fb4 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 22 Jun 2025 11:57:25 -0700 Subject: [PATCH 05/78] Move files from cuda_bindings/tests to cuda_path_finder/tests WITHOUT trying to make anything work. --- .../tests/spawned_process_runner.py | 0 .../tests/test_nvidia_dynamic_libs_load_lib.py | 0 .../tests/test_spawned_process_runner.py | 0 .../tests/test_utils_find_sub_dirs.py | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename {cuda_bindings => cuda_path_finder}/tests/spawned_process_runner.py (100%) rename cuda_bindings/tests/test_path_finder_load.py => cuda_path_finder/tests/test_nvidia_dynamic_libs_load_lib.py (100%) rename {cuda_bindings => cuda_path_finder}/tests/test_spawned_process_runner.py (100%) rename cuda_bindings/tests/test_path_finder_find_sub_dirs.py => cuda_path_finder/tests/test_utils_find_sub_dirs.py (100%) diff --git a/cuda_bindings/tests/spawned_process_runner.py b/cuda_path_finder/tests/spawned_process_runner.py similarity index 100% rename from cuda_bindings/tests/spawned_process_runner.py rename to cuda_path_finder/tests/spawned_process_runner.py diff --git a/cuda_bindings/tests/test_path_finder_load.py b/cuda_path_finder/tests/test_nvidia_dynamic_libs_load_lib.py similarity index 100% rename from cuda_bindings/tests/test_path_finder_load.py rename to cuda_path_finder/tests/test_nvidia_dynamic_libs_load_lib.py diff --git a/cuda_bindings/tests/test_spawned_process_runner.py b/cuda_path_finder/tests/test_spawned_process_runner.py similarity index 100% rename from cuda_bindings/tests/test_spawned_process_runner.py rename to cuda_path_finder/tests/test_spawned_process_runner.py diff --git a/cuda_bindings/tests/test_path_finder_find_sub_dirs.py b/cuda_path_finder/tests/test_utils_find_sub_dirs.py similarity index 100% rename from cuda_bindings/tests/test_path_finder_find_sub_dirs.py rename to cuda_path_finder/tests/test_utils_find_sub_dirs.py From fafa9980db85df833d3a35bc5432f209f2a219c9 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 22 Jun 2025 12:11:32 -0700 Subject: [PATCH 06/78] First VERY ROUGH version of pyproject.toml --- cuda_path_finder/pyproject.toml | 87 +++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 cuda_path_finder/pyproject.toml diff --git a/cuda_path_finder/pyproject.toml b/cuda_path_finder/pyproject.toml new file mode 100644 index 000000000..eebab4b2f --- /dev/null +++ b/cuda_path_finder/pyproject.toml @@ -0,0 +1,87 @@ +# Copyright 2025 NVIDIA Corporation. All rights reserved. +# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE + +[project] +name = "cuda-path_finder" +description = "Path Finder for CUDA components (mainly libs, headers)" +authors = [{name = "NVIDIA Corporation", email = "cuda-python-conduct@nvidia.com"},] +license = "LicenseRef-NVIDIA-SOFTWARE-LICENSE" +classifiers = [ + "Intended Audience :: Developers", + "Topic :: Database", + "Topic :: Scientific/Engineering", + "Programming Language :: Python", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Environment :: GPU :: NVIDIA CUDA", +] +dynamic = [ + "version", + "readme", +] +dependencies = [ + "pywin32; sys_platform == 'win32'", +] + +[project.urls] +Repository = "https://github.com/NVIDIA/cuda-python" +Documentation = "https://nvidia.github.io/cuda-python/" + +[tool.setuptools.packages.find] +include = ["cuda*"] + +[tool.setuptools.dynamic] +version = { attr = "cuda.path_finder._version.__version__" } +readme = { file = ["DESCRIPTION.rst"], content-type = "text/x-rst" } + +[tool.ruff] +line-length = 120 + +[tool.ruff.format] +docstring-code-format = true + +exclude = ["cuda/path_finder/_version.py"] + +[tool.ruff.lint] +select = [ + # pycodestyle Error + "E", + # Pyflakes + "F", + # pycodestyle Warning + "W", + # pyupgrade + "UP", + # flake8-bugbear + "B", + # flake8-simplify + "SIM", + # isort + "I", +] + +ignore = [ + "UP006", + "UP007", + "E741", # ambiguous variable name such as I + "B007", # rename unsued loop variable to _name + "UP035" # UP006, UP007, UP035 complain about deprecated Typing. use, but disregard backward compatibility of python version +] + +[tool.ruff.lint.per-file-ignores] +"setup.py" = ["F401"] +"__init__.py" = ["F401"] + +"examples/**/*" = [ + "E722", + "E501" # line too long + ] + +"tests/**/*" = [ + "E722", + "UP022", + "E402", # module level import not at top of file + "F841"] # F841 complains about unused variables, but some assignments have side-effects that could be useful for tests (func calls for example) From 4eff7d288160becdd60dfcec09c1e5609ab1d352 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 22 Jun 2025 12:22:27 -0700 Subject: [PATCH 07/78] Change imports in tests/ WITHOUT trying to make anything work. --- .../find_nvidia_dynamic_library.py | 18 ++------- .../_dynamic_libs/load_dl_linux.py | 4 +- .../_dynamic_libs/load_dl_windows.py | 17 ++------- .../_dynamic_libs/supported_nvidia_libs.py | 8 +--- .../cuda/path_finder/_utils/find_sub_dirs.py | 4 +- .../test_nvidia_dynamic_libs_load_lib.py | 38 ++++++++++--------- .../tests/test_utils_find_sub_dirs.py | 2 +- 7 files changed, 33 insertions(+), 58 deletions(-) diff --git a/cuda_path_finder/cuda/path_finder/_dynamic_libs/find_nvidia_dynamic_library.py b/cuda_path_finder/cuda/path_finder/_dynamic_libs/find_nvidia_dynamic_library.py index b4273901e..1f872cf60 100644 --- a/cuda_path_finder/cuda/path_finder/_dynamic_libs/find_nvidia_dynamic_library.py +++ b/cuda_path_finder/cuda/path_finder/_dynamic_libs/find_nvidia_dynamic_library.py @@ -21,11 +21,7 @@ def _no_such_file_in_sub_dirs(sub_dirs, file_wild, error_messages, attachments): def _find_so_using_nvidia_lib_dirs(libname, so_basename, error_messages, attachments): - nvidia_sub_dirs = ( - ("nvidia", "*", "nvvm", "lib64") - if libname == "nvvm" - else ("nvidia", "*", "lib") - ) + nvidia_sub_dirs = ("nvidia", "*", "nvvm", "lib64") if libname == "nvvm" else ("nvidia", "*", "lib") file_wild = so_basename + "*" for lib_dir in find_sub_dirs_all_sitepackages(nvidia_sub_dirs): # First look for an exact match @@ -50,19 +46,13 @@ def _find_dll_under_dir(dirpath, file_wild): return None -def _find_dll_using_nvidia_bin_dirs( - libname, lib_searched_for, error_messages, attachments -): - nvidia_sub_dirs = ( - ("nvidia", "*", "nvvm", "bin") if libname == "nvvm" else ("nvidia", "*", "bin") - ) +def _find_dll_using_nvidia_bin_dirs(libname, lib_searched_for, error_messages, attachments): + nvidia_sub_dirs = ("nvidia", "*", "nvvm", "bin") if libname == "nvvm" else ("nvidia", "*", "bin") for bin_dir in find_sub_dirs_all_sitepackages(nvidia_sub_dirs): dll_name = _find_dll_under_dir(bin_dir, lib_searched_for) if dll_name is not None: return dll_name - _no_such_file_in_sub_dirs( - nvidia_sub_dirs, lib_searched_for, error_messages, attachments - ) + _no_such_file_in_sub_dirs(nvidia_sub_dirs, lib_searched_for, error_messages, attachments) return None diff --git a/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_linux.py b/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_linux.py index 9aa32b799..ae3940529 100644 --- a/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_linux.py +++ b/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_linux.py @@ -78,9 +78,7 @@ def check_if_already_loaded_from_elsewhere(libname: str) -> Optional[LoadedDL]: except OSError: continue else: - return LoadedDL( - handle._handle, abs_path_for_dynamic_library(libname, handle), True - ) + return LoadedDL(handle._handle, abs_path_for_dynamic_library(libname, handle), True) return None diff --git a/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_windows.py b/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_windows.py index 49fcc3b1f..12d5cd70f 100644 --- a/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_windows.py +++ b/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_windows.py @@ -30,9 +30,7 @@ def add_dll_directory(dll_abs_path: str) -> None: os.add_dll_directory(dirpath) # Update PATH as a fallback for dependent DLL resolution curr_path = os.environ.get("PATH") - os.environ["PATH"] = ( - dirpath if curr_path is None else os.pathsep.join((curr_path, dirpath)) - ) + os.environ["PATH"] = dirpath if curr_path is None else os.pathsep.join((curr_path, dirpath)) def abs_path_for_dynamic_library(libname: str, handle: pywintypes.HANDLE) -> str: @@ -40,9 +38,7 @@ def abs_path_for_dynamic_library(libname: str, handle: pywintypes.HANDLE) -> str try: return win32api.GetModuleFileName(handle) except Exception as e: - raise RuntimeError( - f"GetModuleFileName failed for {libname!r} (exception type: {type(e)})" - ) from e + raise RuntimeError(f"GetModuleFileName failed for {libname!r} (exception type: {type(e)})") from e def check_if_already_loaded_from_elsewhere(libname: str) -> Optional[LoadedDL]: @@ -89,9 +85,7 @@ def load_with_system_search(libname: str, _unused: str) -> Optional[LoadedDL]: except pywintypes.error: continue else: - return LoadedDL( - handle, abs_path_for_dynamic_library(libname, handle), False - ) + return LoadedDL(handle, abs_path_for_dynamic_library(libname, handle), False) return None @@ -116,10 +110,7 @@ def load_with_abs_path(libname: str, found_path: str) -> LoadedDL: if libname in LIBNAMES_REQUIRING_OS_ADD_DLL_DIRECTORY: add_dll_directory(found_path) - flags = ( - WINBASE_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS - | WINBASE_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR - ) + flags = WINBASE_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | WINBASE_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR try: handle = win32api.LoadLibraryEx(found_path, 0, flags) except pywintypes.error as e: diff --git a/cuda_path_finder/cuda/path_finder/_dynamic_libs/supported_nvidia_libs.py b/cuda_path_finder/cuda/path_finder/_dynamic_libs/supported_nvidia_libs.py index 9225ad932..63bde282f 100644 --- a/cuda_path_finder/cuda/path_finder/_dynamic_libs/supported_nvidia_libs.py +++ b/cuda_path_finder/cuda/path_finder/_dynamic_libs/supported_nvidia_libs.py @@ -55,15 +55,11 @@ # "cufile_rdma", # Requires libmlx5.so ) -PARTIALLY_SUPPORTED_LIBNAMES_LINUX = ( - PARTIALLY_SUPPORTED_LIBNAMES_COMMON + PARTIALLY_SUPPORTED_LIBNAMES_LINUX_ONLY -) +PARTIALLY_SUPPORTED_LIBNAMES_LINUX = PARTIALLY_SUPPORTED_LIBNAMES_COMMON + PARTIALLY_SUPPORTED_LIBNAMES_LINUX_ONLY PARTIALLY_SUPPORTED_LIBNAMES_WINDOWS_ONLY = () -PARTIALLY_SUPPORTED_LIBNAMES_WINDOWS = ( - PARTIALLY_SUPPORTED_LIBNAMES_COMMON + PARTIALLY_SUPPORTED_LIBNAMES_WINDOWS_ONLY -) +PARTIALLY_SUPPORTED_LIBNAMES_WINDOWS = PARTIALLY_SUPPORTED_LIBNAMES_COMMON + PARTIALLY_SUPPORTED_LIBNAMES_WINDOWS_ONLY PARTIALLY_SUPPORTED_LIBNAMES_ALL = ( PARTIALLY_SUPPORTED_LIBNAMES_COMMON diff --git a/cuda_path_finder/cuda/path_finder/_utils/find_sub_dirs.py b/cuda_path_finder/cuda/path_finder/_utils/find_sub_dirs.py index 76f17d151..810132625 100644 --- a/cuda_path_finder/cuda/path_finder/_utils/find_sub_dirs.py +++ b/cuda_path_finder/cuda/path_finder/_utils/find_sub_dirs.py @@ -49,6 +49,4 @@ def find_sub_dirs_sys_path(sub_dirs): def find_sub_dirs_all_sitepackages(sub_dirs): - return find_sub_dirs( - (site.getusersitepackages(),) + tuple(site.getsitepackages()), sub_dirs - ) + return find_sub_dirs((site.getusersitepackages(),) + tuple(site.getsitepackages()), sub_dirs) diff --git a/cuda_path_finder/tests/test_nvidia_dynamic_libs_load_lib.py b/cuda_path_finder/tests/test_nvidia_dynamic_libs_load_lib.py index c63c3d668..f1d5350d2 100644 --- a/cuda_path_finder/tests/test_nvidia_dynamic_libs_load_lib.py +++ b/cuda_path_finder/tests/test_nvidia_dynamic_libs_load_lib.py @@ -7,32 +7,34 @@ import pytest import spawned_process_runner -from cuda.bindings import path_finder -from cuda.bindings._path_finder import supported_libs - -ALL_LIBNAMES = path_finder._SUPPORTED_LIBNAMES + supported_libs.PARTIALLY_SUPPORTED_LIBNAMES_ALL -ALL_LIBNAMES_LINUX = path_finder._SUPPORTED_LIBNAMES + supported_libs.PARTIALLY_SUPPORTED_LIBNAMES_LINUX -ALL_LIBNAMES_WINDOWS = path_finder._SUPPORTED_LIBNAMES + supported_libs.PARTIALLY_SUPPORTED_LIBNAMES_WINDOWS -if os.environ.get("CUDA_BINDINGS_PATH_FINDER_TEST_ALL_LIBNAMES", False): +from cuda.path_finder import nvidia_dynamic_libs +from cuda.path_finder._dynamic_libs import supported_nvidia_libs + +ALL_LIBNAMES = nvidia_dynamic_libs.SUPPORTED_LIBNAMES + supported_nvidia_libs.PARTIALLY_SUPPORTED_LIBNAMES_ALL +ALL_LIBNAMES_LINUX = nvidia_dynamic_libs.SUPPORTED_LIBNAMES + supported_nvidia_libs.PARTIALLY_SUPPORTED_LIBNAMES_LINUX +ALL_LIBNAMES_WINDOWS = ( + nvidia_dynamic_libs.SUPPORTED_LIBNAMES + supported_nvidia_libs.PARTIALLY_SUPPORTED_LIBNAMES_WINDOWS +) +if os.environ.get("CUDA_PATH_FINDER_TEST_ALL_LIBNAMES", False): if sys.platform == "win32": TEST_FIND_OR_LOAD_LIBNAMES = ALL_LIBNAMES_WINDOWS else: TEST_FIND_OR_LOAD_LIBNAMES = ALL_LIBNAMES_LINUX else: - TEST_FIND_OR_LOAD_LIBNAMES = path_finder._SUPPORTED_LIBNAMES + TEST_FIND_OR_LOAD_LIBNAMES = nvidia_dynamic_libs.SUPPORTED_LIBNAMES def test_all_libnames_linux_sonames_consistency(): - assert tuple(sorted(ALL_LIBNAMES_LINUX)) == tuple(sorted(supported_libs.SUPPORTED_LINUX_SONAMES.keys())) + assert tuple(sorted(ALL_LIBNAMES_LINUX)) == tuple(sorted(supported_nvidia_libs.SUPPORTED_LINUX_SONAMES.keys())) def test_all_libnames_windows_dlls_consistency(): - assert tuple(sorted(ALL_LIBNAMES_WINDOWS)) == tuple(sorted(supported_libs.SUPPORTED_WINDOWS_DLLS.keys())) + assert tuple(sorted(ALL_LIBNAMES_WINDOWS)) == tuple(sorted(supported_nvidia_libs.SUPPORTED_WINDOWS_DLLS.keys())) @pytest.mark.parametrize("dict_name", ["SUPPORTED_LINUX_SONAMES", "SUPPORTED_WINDOWS_DLLS"]) def test_libname_dict_values_are_unique(dict_name): - libname_dict = getattr(supported_libs, dict_name) + libname_dict = getattr(supported_nvidia_libs, dict_name) libname_for_value = {} for libname, values in libname_dict.items(): for value in values: @@ -43,11 +45,11 @@ def test_libname_dict_values_are_unique(dict_name): def test_all_libnames_libnames_requiring_os_add_dll_directory_consistency(): - assert not (set(supported_libs.LIBNAMES_REQUIRING_OS_ADD_DLL_DIRECTORY) - set(ALL_LIBNAMES_WINDOWS)) + assert not (set(supported_nvidia_libs.LIBNAMES_REQUIRING_OS_ADD_DLL_DIRECTORY) - set(ALL_LIBNAMES_WINDOWS)) def test_all_libnames_expected_lib_symbols_consistency(): - assert tuple(sorted(ALL_LIBNAMES)) == tuple(sorted(supported_libs.EXPECTED_LIB_SYMBOLS.keys())) + assert tuple(sorted(ALL_LIBNAMES)) == tuple(sorted(supported_nvidia_libs.EXPECTED_LIB_SYMBOLS.keys())) def build_child_process_failed_for_libname_message(libname, result): @@ -61,18 +63,18 @@ def build_child_process_failed_for_libname_message(libname, result): def child_process_func(libname): import os - from cuda.bindings._path_finder.load_nvidia_dynamic_library import _load_nvidia_dynamic_library_no_cache - from cuda.bindings.path_finder import _load_nvidia_dynamic_library + from cuda.path_finder._dynamic_libs.load_nvidia_dynamic_library import load_lib_no_cache + from cuda.path_finder.nvidia_dynamic_libs import load_lib - loaded_dl_fresh = _load_nvidia_dynamic_library(libname) + loaded_dl_fresh = load_lib(libname) if loaded_dl_fresh.was_already_loaded_from_elsewhere: raise RuntimeError("loaded_dl_fresh.was_already_loaded_from_elsewhere") - loaded_dl_from_cache = _load_nvidia_dynamic_library(libname) + loaded_dl_from_cache = load_lib(libname) if loaded_dl_from_cache is not loaded_dl_fresh: raise RuntimeError("loaded_dl_from_cache is not loaded_dl_fresh") - loaded_dl_no_cache = _load_nvidia_dynamic_library_no_cache(libname) + loaded_dl_no_cache = load_lib_no_cache(libname) if not loaded_dl_no_cache.was_already_loaded_from_elsewhere: raise RuntimeError("loaded_dl_no_cache.was_already_loaded_from_elsewhere") if not os.path.samefile(loaded_dl_no_cache.abs_path, loaded_dl_fresh.abs_path): diff --git a/cuda_path_finder/tests/test_utils_find_sub_dirs.py b/cuda_path_finder/tests/test_utils_find_sub_dirs.py index 6b2644bff..17263f0e7 100644 --- a/cuda_path_finder/tests/test_utils_find_sub_dirs.py +++ b/cuda_path_finder/tests/test_utils_find_sub_dirs.py @@ -5,7 +5,7 @@ import pytest -from cuda.bindings._path_finder.find_sub_dirs import ( +from cuda.path_finder._utils import ( find_sub_dirs, find_sub_dirs_all_sitepackages, find_sub_dirs_sys_path, From db0f540fabc4d3004c4264940f67d32c3a43afba Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 22 Jun 2025 12:54:37 -0700 Subject: [PATCH 08/78] Clean up pyproject.toml (with the help of ChatGPT) WITHOUT trying to make anything work. --- cuda_path_finder/cuda/path_finder/_version.py | 4 ++ cuda_path_finder/pyproject.toml | 59 ++++--------------- 2 files changed, 16 insertions(+), 47 deletions(-) create mode 100644 cuda_path_finder/cuda/path_finder/_version.py diff --git a/cuda_path_finder/cuda/path_finder/_version.py b/cuda_path_finder/cuda/path_finder/_version.py new file mode 100644 index 000000000..cccb0e3ac --- /dev/null +++ b/cuda_path_finder/cuda/path_finder/_version.py @@ -0,0 +1,4 @@ +# Copyright 2025 NVIDIA Corporation. All rights reserved. +# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE + +__version__ = "0.0.1" diff --git a/cuda_path_finder/pyproject.toml b/cuda_path_finder/pyproject.toml index eebab4b2f..59670740a 100644 --- a/cuda_path_finder/pyproject.toml +++ b/cuda_path_finder/pyproject.toml @@ -2,49 +2,37 @@ # SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE [project] -name = "cuda-path_finder" +name = "cuda-path-finder" description = "Path Finder for CUDA components (mainly libs, headers)" -authors = [{name = "NVIDIA Corporation", email = "cuda-python-conduct@nvidia.com"},] -license = "LicenseRef-NVIDIA-SOFTWARE-LICENSE" -classifiers = [ - "Intended Audience :: Developers", - "Topic :: Database", - "Topic :: Scientific/Engineering", - "Programming Language :: Python", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3.13", - "Environment :: GPU :: NVIDIA CUDA", -] -dynamic = [ - "version", - "readme", -] +authors = [{ name = "NVIDIA Corporation", email = "cuda-python-conduct@nvidia.com" }] +license = { text = "LicenseRef-NVIDIA-SOFTWARE-LICENSE" } +requires-python = ">=3.9" dependencies = [ - "pywin32; sys_platform == 'win32'", + "pywin32; sys_platform == 'win32'", ] [project.urls] Repository = "https://github.com/NVIDIA/cuda-python" Documentation = "https://nvidia.github.io/cuda-python/" -[tool.setuptools.packages.find] -include = ["cuda*"] +[tool.setuptools] +packages = { find = { include = ["cuda*"] } } [tool.setuptools.dynamic] version = { attr = "cuda.path_finder._version.__version__" } readme = { file = ["DESCRIPTION.rst"], content-type = "text/x-rst" } +[build-system] +requires = ["setuptools>=64", "wheel"] +build-backend = "setuptools.build_meta" + [tool.ruff] line-length = 120 +preview = true [tool.ruff.format] docstring-code-format = true -exclude = ["cuda/path_finder/_version.py"] - [tool.ruff.lint] select = [ # pycodestyle Error @@ -62,26 +50,3 @@ select = [ # isort "I", ] - -ignore = [ - "UP006", - "UP007", - "E741", # ambiguous variable name such as I - "B007", # rename unsued loop variable to _name - "UP035" # UP006, UP007, UP035 complain about deprecated Typing. use, but disregard backward compatibility of python version -] - -[tool.ruff.lint.per-file-ignores] -"setup.py" = ["F401"] -"__init__.py" = ["F401"] - -"examples/**/*" = [ - "E722", - "E501" # line too long - ] - -"tests/**/*" = [ - "E722", - "UP022", - "E402", # module level import not at top of file - "F841"] # F841 complains about unused variables, but some assignments have side-effects that could be useful for tests (func calls for example) From 9fea2e70b50552d29bde43a1adadf0e321da48bc Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 22 Jun 2025 12:58:10 -0700 Subject: [PATCH 09/78] ruff automatic fix: Replace deprecated typing.Sequence with collections.abc.Sequence (Python 3.9+) --- cuda_path_finder/tests/spawned_process_runner.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cuda_path_finder/tests/spawned_process_runner.py b/cuda_path_finder/tests/spawned_process_runner.py index 3a13362fe..25362e982 100644 --- a/cuda_path_finder/tests/spawned_process_runner.py +++ b/cuda_path_finder/tests/spawned_process_runner.py @@ -5,9 +5,10 @@ import queue # for Empty import sys import traceback +from collections.abc import Sequence from dataclasses import dataclass from io import StringIO -from typing import Any, Callable, Optional, Sequence +from typing import Any, Callable, Optional PROCESS_KILLED = -9 PROCESS_NO_RESULT = -999 From c494ef2487b7d2b1fa5212731c55863695e9d2b6 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 22 Jun 2025 23:25:23 -0700 Subject: [PATCH 10/78] Add `dynamic = ["version"]` in pyproject.toml and cuda/path_finder/__init__.py (to make the dynamic version work). --- cuda_path_finder/cuda/path_finder/__init__.py | 0 cuda_path_finder/pyproject.toml | 1 + 2 files changed, 1 insertion(+) create mode 100644 cuda_path_finder/cuda/path_finder/__init__.py diff --git a/cuda_path_finder/cuda/path_finder/__init__.py b/cuda_path_finder/cuda/path_finder/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/cuda_path_finder/pyproject.toml b/cuda_path_finder/pyproject.toml index 59670740a..3361dd893 100644 --- a/cuda_path_finder/pyproject.toml +++ b/cuda_path_finder/pyproject.toml @@ -10,6 +10,7 @@ requires-python = ">=3.9" dependencies = [ "pywin32; sys_platform == 'win32'", ] +dynamic = ["version"] [project.urls] Repository = "https://github.com/NVIDIA/cuda-python" From 78b8c6dfadedebf5896573b5e5184a98320d8d36 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 22 Jun 2025 23:36:40 -0700 Subject: [PATCH 11/78] Modernize `[project] license` line. --- cuda_path_finder/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cuda_path_finder/pyproject.toml b/cuda_path_finder/pyproject.toml index 3361dd893..9573c9f8e 100644 --- a/cuda_path_finder/pyproject.toml +++ b/cuda_path_finder/pyproject.toml @@ -5,7 +5,7 @@ name = "cuda-path-finder" description = "Path Finder for CUDA components (mainly libs, headers)" authors = [{ name = "NVIDIA Corporation", email = "cuda-python-conduct@nvidia.com" }] -license = { text = "LicenseRef-NVIDIA-SOFTWARE-LICENSE" } +license = "LicenseRef-NVIDIA-SOFTWARE-LICENSE" requires-python = ">=3.9" dependencies = [ "pywin32; sys_platform == 'win32'", From 5690d96a1b845fbb69c453b97e59ba5788cccc6e Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 23 Jun 2025 10:58:02 -0700 Subject: [PATCH 12/78] =?UTF-8?q?Change=20dir/file=20names:=20path=5Ffinde?= =?UTF-8?q?r=20=E2=86=92=20pathfinder?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cuda/pathfinder}/README.md | 0 .../cuda/pathfinder}/__init__.py | 0 .../_dynamic_libs/find_nvidia_dynamic_library.py | 0 .../cuda/pathfinder}/_dynamic_libs/load_dl_common.py | 0 .../cuda/pathfinder}/_dynamic_libs/load_dl_linux.py | 0 .../cuda/pathfinder}/_dynamic_libs/load_dl_windows.py | 0 .../_dynamic_libs/load_nvidia_dynamic_library.py | 0 .../cuda/pathfinder}/_dynamic_libs/supported_nvidia_libs.py | 0 .../cuda/pathfinder}/_utils/find_sub_dirs.py | 0 .../cuda/pathfinder}/_version.py | 0 .../cuda/pathfinder}/nvidia_dynamic_libs.py | 0 {cuda_path_finder => cuda_pathfinder}/pyproject.toml | 6 +++--- .../tests/spawned_process_runner.py | 0 .../tests/test_nvidia_dynamic_libs_load_lib.py | 0 .../tests/test_spawned_process_runner.py | 0 .../tests/test_utils_find_sub_dirs.py | 0 16 files changed, 3 insertions(+), 3 deletions(-) rename {cuda_path_finder/cuda/path_finder => cuda_pathfinder/cuda/pathfinder}/README.md (100%) rename {cuda_path_finder/cuda/path_finder => cuda_pathfinder/cuda/pathfinder}/__init__.py (100%) rename {cuda_path_finder/cuda/path_finder => cuda_pathfinder/cuda/pathfinder}/_dynamic_libs/find_nvidia_dynamic_library.py (100%) rename {cuda_path_finder/cuda/path_finder => cuda_pathfinder/cuda/pathfinder}/_dynamic_libs/load_dl_common.py (100%) rename {cuda_path_finder/cuda/path_finder => cuda_pathfinder/cuda/pathfinder}/_dynamic_libs/load_dl_linux.py (100%) rename {cuda_path_finder/cuda/path_finder => cuda_pathfinder/cuda/pathfinder}/_dynamic_libs/load_dl_windows.py (100%) rename {cuda_path_finder/cuda/path_finder => cuda_pathfinder/cuda/pathfinder}/_dynamic_libs/load_nvidia_dynamic_library.py (100%) rename {cuda_path_finder/cuda/path_finder => cuda_pathfinder/cuda/pathfinder}/_dynamic_libs/supported_nvidia_libs.py (100%) rename {cuda_path_finder/cuda/path_finder => cuda_pathfinder/cuda/pathfinder}/_utils/find_sub_dirs.py (100%) rename {cuda_path_finder/cuda/path_finder => cuda_pathfinder/cuda/pathfinder}/_version.py (100%) rename {cuda_path_finder/cuda/path_finder => cuda_pathfinder/cuda/pathfinder}/nvidia_dynamic_libs.py (100%) rename {cuda_path_finder => cuda_pathfinder}/pyproject.toml (87%) rename {cuda_path_finder => cuda_pathfinder}/tests/spawned_process_runner.py (100%) rename {cuda_path_finder => cuda_pathfinder}/tests/test_nvidia_dynamic_libs_load_lib.py (100%) rename {cuda_path_finder => cuda_pathfinder}/tests/test_spawned_process_runner.py (100%) rename {cuda_path_finder => cuda_pathfinder}/tests/test_utils_find_sub_dirs.py (100%) diff --git a/cuda_path_finder/cuda/path_finder/README.md b/cuda_pathfinder/cuda/pathfinder/README.md similarity index 100% rename from cuda_path_finder/cuda/path_finder/README.md rename to cuda_pathfinder/cuda/pathfinder/README.md diff --git a/cuda_path_finder/cuda/path_finder/__init__.py b/cuda_pathfinder/cuda/pathfinder/__init__.py similarity index 100% rename from cuda_path_finder/cuda/path_finder/__init__.py rename to cuda_pathfinder/cuda/pathfinder/__init__.py diff --git a/cuda_path_finder/cuda/path_finder/_dynamic_libs/find_nvidia_dynamic_library.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_library.py similarity index 100% rename from cuda_path_finder/cuda/path_finder/_dynamic_libs/find_nvidia_dynamic_library.py rename to cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_library.py diff --git a/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_common.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py similarity index 100% rename from cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_common.py rename to cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py diff --git a/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_linux.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py similarity index 100% rename from cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_linux.py rename to cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py diff --git a/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_windows.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py similarity index 100% rename from cuda_path_finder/cuda/path_finder/_dynamic_libs/load_dl_windows.py rename to cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py diff --git a/cuda_path_finder/cuda/path_finder/_dynamic_libs/load_nvidia_dynamic_library.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_library.py similarity index 100% rename from cuda_path_finder/cuda/path_finder/_dynamic_libs/load_nvidia_dynamic_library.py rename to cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_library.py diff --git a/cuda_path_finder/cuda/path_finder/_dynamic_libs/supported_nvidia_libs.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py similarity index 100% rename from cuda_path_finder/cuda/path_finder/_dynamic_libs/supported_nvidia_libs.py rename to cuda_pathfinder/cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py diff --git a/cuda_path_finder/cuda/path_finder/_utils/find_sub_dirs.py b/cuda_pathfinder/cuda/pathfinder/_utils/find_sub_dirs.py similarity index 100% rename from cuda_path_finder/cuda/path_finder/_utils/find_sub_dirs.py rename to cuda_pathfinder/cuda/pathfinder/_utils/find_sub_dirs.py diff --git a/cuda_path_finder/cuda/path_finder/_version.py b/cuda_pathfinder/cuda/pathfinder/_version.py similarity index 100% rename from cuda_path_finder/cuda/path_finder/_version.py rename to cuda_pathfinder/cuda/pathfinder/_version.py diff --git a/cuda_path_finder/cuda/path_finder/nvidia_dynamic_libs.py b/cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py similarity index 100% rename from cuda_path_finder/cuda/path_finder/nvidia_dynamic_libs.py rename to cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py diff --git a/cuda_path_finder/pyproject.toml b/cuda_pathfinder/pyproject.toml similarity index 87% rename from cuda_path_finder/pyproject.toml rename to cuda_pathfinder/pyproject.toml index 9573c9f8e..a1662383b 100644 --- a/cuda_path_finder/pyproject.toml +++ b/cuda_pathfinder/pyproject.toml @@ -2,8 +2,8 @@ # SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE [project] -name = "cuda-path-finder" -description = "Path Finder for CUDA components (mainly libs, headers)" +name = "cuda-pathfinder" +description = "Pathfinder for CUDA components (mainly libs, headers)" authors = [{ name = "NVIDIA Corporation", email = "cuda-python-conduct@nvidia.com" }] license = "LicenseRef-NVIDIA-SOFTWARE-LICENSE" requires-python = ">=3.9" @@ -20,7 +20,7 @@ Documentation = "https://nvidia.github.io/cuda-python/" packages = { find = { include = ["cuda*"] } } [tool.setuptools.dynamic] -version = { attr = "cuda.path_finder._version.__version__" } +version = { attr = "cuda.pathfinder._version.__version__" } readme = { file = ["DESCRIPTION.rst"], content-type = "text/x-rst" } [build-system] diff --git a/cuda_path_finder/tests/spawned_process_runner.py b/cuda_pathfinder/tests/spawned_process_runner.py similarity index 100% rename from cuda_path_finder/tests/spawned_process_runner.py rename to cuda_pathfinder/tests/spawned_process_runner.py diff --git a/cuda_path_finder/tests/test_nvidia_dynamic_libs_load_lib.py b/cuda_pathfinder/tests/test_nvidia_dynamic_libs_load_lib.py similarity index 100% rename from cuda_path_finder/tests/test_nvidia_dynamic_libs_load_lib.py rename to cuda_pathfinder/tests/test_nvidia_dynamic_libs_load_lib.py diff --git a/cuda_path_finder/tests/test_spawned_process_runner.py b/cuda_pathfinder/tests/test_spawned_process_runner.py similarity index 100% rename from cuda_path_finder/tests/test_spawned_process_runner.py rename to cuda_pathfinder/tests/test_spawned_process_runner.py diff --git a/cuda_path_finder/tests/test_utils_find_sub_dirs.py b/cuda_pathfinder/tests/test_utils_find_sub_dirs.py similarity index 100% rename from cuda_path_finder/tests/test_utils_find_sub_dirs.py rename to cuda_pathfinder/tests/test_utils_find_sub_dirs.py From 81b9bd987743e9c74b87a9eb43f53bdef6135f17 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 23 Jun 2025 11:01:39 -0700 Subject: [PATCH 13/78] =?UTF-8?q?Change=20imports:=20path=5Ffinder=20?= =?UTF-8?q?=E2=86=92=20pathfinder?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cuda_bindings/cuda/bindings/_path_finder/README.md | 6 +----- cuda_bindings/cuda/bindings/path_finder.py | 4 ++-- cuda_pathfinder/cuda/pathfinder/README.md | 8 ++++---- .../_dynamic_libs/find_nvidia_dynamic_library.py | 4 ++-- .../cuda/pathfinder/_dynamic_libs/load_dl_common.py | 2 +- .../cuda/pathfinder/_dynamic_libs/load_dl_linux.py | 6 +++--- .../cuda/pathfinder/_dynamic_libs/load_dl_windows.py | 8 ++++---- .../_dynamic_libs/load_nvidia_dynamic_library.py | 10 +++++----- cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py | 4 ++-- .../tests/test_nvidia_dynamic_libs_load_lib.py | 10 +++++----- cuda_pathfinder/tests/test_spawned_process_runner.py | 2 +- cuda_pathfinder/tests/test_utils_find_sub_dirs.py | 2 +- 12 files changed, 31 insertions(+), 35 deletions(-) diff --git a/cuda_bindings/cuda/bindings/_path_finder/README.md b/cuda_bindings/cuda/bindings/_path_finder/README.md index 0f33016cc..d402c935c 100644 --- a/cuda_bindings/cuda/bindings/_path_finder/README.md +++ b/cuda_bindings/cuda/bindings/_path_finder/README.md @@ -1,5 +1 @@ -# The `cuda.bindings.path_finder` module was moved! - -## New location - -`cuda.path_finder` +# The `cuda.bindings.path_finder` module was moved → `cuda.pathfinder` diff --git a/cuda_bindings/cuda/bindings/path_finder.py b/cuda_bindings/cuda/bindings/path_finder.py index de88538e4..a71fd8d20 100644 --- a/cuda_bindings/cuda/bindings/path_finder.py +++ b/cuda_bindings/cuda/bindings/path_finder.py @@ -1,8 +1,8 @@ # Copyright 2024-2025 NVIDIA Corporation. All rights reserved. # SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE -from cuda.path_finder.nvidia_dynamic_libs import SUPPORTED_LIBNAMES as _SUPPORTED_LIBNAMES -from cuda.path_finder.nvidia_dynamic_libs import load_lib as _load_nvidia_dynamic_library +from cuda.pathfinder.nvidia_dynamic_libs import SUPPORTED_LIBNAMES as _SUPPORTED_LIBNAMES +from cuda.pathfinder.nvidia_dynamic_libs import load_lib as _load_nvidia_dynamic_library __all__ = [ "_load_nvidia_dynamic_library", diff --git a/cuda_pathfinder/cuda/pathfinder/README.md b/cuda_pathfinder/cuda/pathfinder/README.md index 1b33b1421..2619ce7ae 100644 --- a/cuda_pathfinder/cuda/pathfinder/README.md +++ b/cuda_pathfinder/cuda/pathfinder/README.md @@ -1,17 +1,17 @@ -# `cuda.path_finder` Module +# `cuda.pathfinder` Module ## Public API (Work in Progress) Currently exposes two primary interfaces: ``` -cuda.path_finder.SUPPORTED_LIBNAMES # ('nvJitLink', 'nvrtc', 'nvvm') -cuda.path_finder.nvidia_dynamic_libs.load_lib(libname: str) -> LoadedDL +cuda.pathfinder.SUPPORTED_LIBNAMES # ('nvJitLink', 'nvrtc', 'nvvm') +cuda.pathfinder.nvidia_dynamic_libs.load_lib(libname: str) -> LoadedDL ``` ## Dynamic Library Loading Search Priority -The `cuda.path_finder.nvidia_dynamic_libs.load_lib` function implements a +The `cuda.pathfinder.nvidia_dynamic_libs.load_lib` function implements a hierarchical search strategy for locating NVIDIA shared libraries: 0. **Check if a library was loaded into the process already by some other means.** diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_library.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_library.py index 1f872cf60..afb2bfe9e 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_library.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_library.py @@ -5,11 +5,11 @@ import glob import os -from cuda.path_finder._dynamic_libs.supported_nvidia_libs import ( +from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import ( IS_WINDOWS, is_suppressed_dll_file, ) -from cuda.path_finder._utils.find_sub_dirs import find_sub_dirs_all_sitepackages +from cuda.pathfinder._utils.find_sub_dirs import find_sub_dirs_all_sitepackages def _no_such_file_in_sub_dirs(sub_dirs, file_wild, error_messages, attachments): diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py index 80a7547a4..45bfdeeac 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py @@ -4,7 +4,7 @@ from dataclasses import dataclass from typing import Callable, Optional -from cuda.path_finder._dynamic_libs.supported_nvidia_libs import ( +from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import ( DIRECT_DEPENDENCIES, IS_WINDOWS, ) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py index ae3940529..745b898bb 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py @@ -6,7 +6,7 @@ import os from typing import Optional -from cuda.path_finder._dynamic_libs.load_dl_common import LoadedDL +from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL CDLL_MODE = os.RTLD_NOW | os.RTLD_GLOBAL @@ -40,7 +40,7 @@ def abs_path_for_dynamic_library(libname: str, handle: ctypes.CDLL) -> Optional[ Raises: OSError: If dladdr fails to get information about the symbol """ - from cuda.path_finder.supported_nvidia_libs import EXPECTED_LIB_SYMBOLS + from cuda.pathfinder.supported_nvidia_libs import EXPECTED_LIB_SYMBOLS for symbol_name in EXPECTED_LIB_SYMBOLS[libname]: symbol = getattr(handle, symbol_name, None) @@ -70,7 +70,7 @@ def check_if_already_loaded_from_elsewhere(libname: str) -> Optional[LoadedDL]: >>> if loaded is not None: ... print(f"Library already loaded from {loaded.abs_path}") """ - from cuda.path_finder.supported_nvidia_libs import SUPPORTED_LINUX_SONAMES + from cuda.pathfinder.supported_nvidia_libs import SUPPORTED_LINUX_SONAMES for soname in SUPPORTED_LINUX_SONAMES.get(libname, ()): try: diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py index 12d5cd70f..9dc3c086c 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py @@ -6,7 +6,7 @@ import pywintypes import win32api -from cuda.path_finder._dynamic_libs.load_dl_common import LoadedDL +from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL # Mirrors WinBase.h (unfortunately not defined already elsewhere) WINBASE_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x00000100 @@ -55,7 +55,7 @@ def check_if_already_loaded_from_elsewhere(libname: str) -> Optional[LoadedDL]: >>> if loaded is not None: ... print(f"Library already loaded from {loaded.abs_path}") """ - from cuda.path_finder.supported_nvidia_libs import SUPPORTED_WINDOWS_DLLS + from cuda.pathfinder.supported_nvidia_libs import SUPPORTED_WINDOWS_DLLS for dll_name in SUPPORTED_WINDOWS_DLLS.get(libname, ()): try: @@ -77,7 +77,7 @@ def load_with_system_search(libname: str, _unused: str) -> Optional[LoadedDL]: Returns: A LoadedDL object if successful, None if the library cannot be loaded """ - from cuda.path_finder.supported_nvidia_libs import SUPPORTED_WINDOWS_DLLS + from cuda.pathfinder.supported_nvidia_libs import SUPPORTED_WINDOWS_DLLS for dll_name in SUPPORTED_WINDOWS_DLLS.get(libname, ()): try: @@ -103,7 +103,7 @@ def load_with_abs_path(libname: str, found_path: str) -> LoadedDL: Raises: RuntimeError: If the DLL cannot be loaded """ - from cuda.path_finder.supported_nvidia_libs import ( + from cuda.pathfinder.supported_nvidia_libs import ( LIBNAMES_REQUIRING_OS_ADD_DLL_DIRECTORY, ) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_library.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_library.py index 1f5f7587b..a7186f4bf 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_library.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_library.py @@ -3,20 +3,20 @@ import functools -from cuda.path_finder._dynamic_libs.find_nvidia_dynamic_library import ( +from cuda.pathfinder._dynamic_libs.find_nvidia_dynamic_library import ( _find_nvidia_dynamic_library, ) -from cuda.path_finder._dynamic_libs.load_dl_common import LoadedDL, load_dependencies -from cuda.path_finder._dynamic_libs.supported_nvidia_libs import IS_WINDOWS +from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL, load_dependencies +from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import IS_WINDOWS if IS_WINDOWS: - from cuda.path_finder._dynamic_libs.load_dl_windows import ( + from cuda.pathfinder._dynamic_libs.load_dl_windows import ( check_if_already_loaded_from_elsewhere, load_with_abs_path, load_with_system_search, ) else: - from cuda.path_finder._dynamic_libs.load_dl_linux import ( + from cuda.pathfinder._dynamic_libs.load_dl_linux import ( check_if_already_loaded_from_elsewhere, load_with_abs_path, load_with_system_search, diff --git a/cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py b/cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py index 5f8d25431..c28598f66 100644 --- a/cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py +++ b/cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py @@ -1,9 +1,9 @@ # Copyright 2025 NVIDIA Corporation. All rights reserved. # SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE -from cuda.path_finder._dynamic_libs.load_nvidia_dynamic_library import ( +from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_library import ( load_nvidia_dynamic_library as load_lib, ) -from cuda.path_finder._dynamic_libs.supported_nvidia_libs import SUPPORTED_LIBNAMES +from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import SUPPORTED_LIBNAMES __all__ = ["load_lib", "SUPPORTED_LIBNAMES"] diff --git a/cuda_pathfinder/tests/test_nvidia_dynamic_libs_load_lib.py b/cuda_pathfinder/tests/test_nvidia_dynamic_libs_load_lib.py index f1d5350d2..4e2e5380e 100644 --- a/cuda_pathfinder/tests/test_nvidia_dynamic_libs_load_lib.py +++ b/cuda_pathfinder/tests/test_nvidia_dynamic_libs_load_lib.py @@ -7,15 +7,15 @@ import pytest import spawned_process_runner -from cuda.path_finder import nvidia_dynamic_libs -from cuda.path_finder._dynamic_libs import supported_nvidia_libs +from cuda.pathfinder import nvidia_dynamic_libs +from cuda.pathfinder._dynamic_libs import supported_nvidia_libs ALL_LIBNAMES = nvidia_dynamic_libs.SUPPORTED_LIBNAMES + supported_nvidia_libs.PARTIALLY_SUPPORTED_LIBNAMES_ALL ALL_LIBNAMES_LINUX = nvidia_dynamic_libs.SUPPORTED_LIBNAMES + supported_nvidia_libs.PARTIALLY_SUPPORTED_LIBNAMES_LINUX ALL_LIBNAMES_WINDOWS = ( nvidia_dynamic_libs.SUPPORTED_LIBNAMES + supported_nvidia_libs.PARTIALLY_SUPPORTED_LIBNAMES_WINDOWS ) -if os.environ.get("CUDA_PATH_FINDER_TEST_ALL_LIBNAMES", False): +if os.environ.get("CUDA_PATHFINDER_TEST_ALL_LIBNAMES", False): if sys.platform == "win32": TEST_FIND_OR_LOAD_LIBNAMES = ALL_LIBNAMES_WINDOWS else: @@ -63,8 +63,8 @@ def build_child_process_failed_for_libname_message(libname, result): def child_process_func(libname): import os - from cuda.path_finder._dynamic_libs.load_nvidia_dynamic_library import load_lib_no_cache - from cuda.path_finder.nvidia_dynamic_libs import load_lib + from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_library import load_lib_no_cache + from cuda.pathfinder.nvidia_dynamic_libs import load_lib loaded_dl_fresh = load_lib(libname) if loaded_dl_fresh.was_already_loaded_from_elsewhere: diff --git a/cuda_pathfinder/tests/test_spawned_process_runner.py b/cuda_pathfinder/tests/test_spawned_process_runner.py index 644ed8a83..5a3b7f725 100644 --- a/cuda_pathfinder/tests/test_spawned_process_runner.py +++ b/cuda_pathfinder/tests/test_spawned_process_runner.py @@ -1,7 +1,7 @@ # Copyright 2025 NVIDIA Corporation. All rights reserved. # SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE -# Note: This only covers what is not covered already in test_path_finder_load.py +# Note: This only covers what is not covered already in test_nvidia_dynamic_libs_load_lib.py import pytest from spawned_process_runner import run_in_spawned_child_process diff --git a/cuda_pathfinder/tests/test_utils_find_sub_dirs.py b/cuda_pathfinder/tests/test_utils_find_sub_dirs.py index 17263f0e7..9aa8a69a7 100644 --- a/cuda_pathfinder/tests/test_utils_find_sub_dirs.py +++ b/cuda_pathfinder/tests/test_utils_find_sub_dirs.py @@ -5,7 +5,7 @@ import pytest -from cuda.path_finder._utils import ( +from cuda.pathfinder._utils import ( find_sub_dirs, find_sub_dirs_all_sitepackages, find_sub_dirs_sys_path, From b9be5cbda53783b15fca81bc0269d0961cbfe1b6 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 23 Jun 2025 12:13:24 -0700 Subject: [PATCH 14/78] Fix up broken imports. --- .../cuda/pathfinder/_dynamic_libs/load_dl_linux.py | 4 ++-- .../cuda/pathfinder/_dynamic_libs/load_dl_windows.py | 6 +++--- cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py | 4 +--- {cuda_bindings => cuda_pathfinder}/tests/conftest.py | 0 cuda_pathfinder/tests/test_nvidia_dynamic_libs_load_lib.py | 4 ++-- cuda_pathfinder/tests/test_utils_find_sub_dirs.py | 2 +- 6 files changed, 9 insertions(+), 11 deletions(-) rename {cuda_bindings => cuda_pathfinder}/tests/conftest.py (100%) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py index 745b898bb..389817248 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py @@ -40,7 +40,7 @@ def abs_path_for_dynamic_library(libname: str, handle: ctypes.CDLL) -> Optional[ Raises: OSError: If dladdr fails to get information about the symbol """ - from cuda.pathfinder.supported_nvidia_libs import EXPECTED_LIB_SYMBOLS + from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import EXPECTED_LIB_SYMBOLS for symbol_name in EXPECTED_LIB_SYMBOLS[libname]: symbol = getattr(handle, symbol_name, None) @@ -70,7 +70,7 @@ def check_if_already_loaded_from_elsewhere(libname: str) -> Optional[LoadedDL]: >>> if loaded is not None: ... print(f"Library already loaded from {loaded.abs_path}") """ - from cuda.pathfinder.supported_nvidia_libs import SUPPORTED_LINUX_SONAMES + from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import SUPPORTED_LINUX_SONAMES for soname in SUPPORTED_LINUX_SONAMES.get(libname, ()): try: diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py index 9dc3c086c..1756dbd04 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py @@ -55,7 +55,7 @@ def check_if_already_loaded_from_elsewhere(libname: str) -> Optional[LoadedDL]: >>> if loaded is not None: ... print(f"Library already loaded from {loaded.abs_path}") """ - from cuda.pathfinder.supported_nvidia_libs import SUPPORTED_WINDOWS_DLLS + from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import SUPPORTED_WINDOWS_DLLS for dll_name in SUPPORTED_WINDOWS_DLLS.get(libname, ()): try: @@ -77,7 +77,7 @@ def load_with_system_search(libname: str, _unused: str) -> Optional[LoadedDL]: Returns: A LoadedDL object if successful, None if the library cannot be loaded """ - from cuda.pathfinder.supported_nvidia_libs import SUPPORTED_WINDOWS_DLLS + from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import SUPPORTED_WINDOWS_DLLS for dll_name in SUPPORTED_WINDOWS_DLLS.get(libname, ()): try: @@ -103,7 +103,7 @@ def load_with_abs_path(libname: str, found_path: str) -> LoadedDL: Raises: RuntimeError: If the DLL cannot be loaded """ - from cuda.pathfinder.supported_nvidia_libs import ( + from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import ( LIBNAMES_REQUIRING_OS_ADD_DLL_DIRECTORY, ) diff --git a/cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py b/cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py index c28598f66..28e0b2278 100644 --- a/cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py +++ b/cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py @@ -1,9 +1,7 @@ # Copyright 2025 NVIDIA Corporation. All rights reserved. # SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE -from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_library import ( - load_nvidia_dynamic_library as load_lib, -) +from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_library import load_lib from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import SUPPORTED_LIBNAMES __all__ = ["load_lib", "SUPPORTED_LIBNAMES"] diff --git a/cuda_bindings/tests/conftest.py b/cuda_pathfinder/tests/conftest.py similarity index 100% rename from cuda_bindings/tests/conftest.py rename to cuda_pathfinder/tests/conftest.py diff --git a/cuda_pathfinder/tests/test_nvidia_dynamic_libs_load_lib.py b/cuda_pathfinder/tests/test_nvidia_dynamic_libs_load_lib.py index 4e2e5380e..4c0337ef0 100644 --- a/cuda_pathfinder/tests/test_nvidia_dynamic_libs_load_lib.py +++ b/cuda_pathfinder/tests/test_nvidia_dynamic_libs_load_lib.py @@ -63,7 +63,7 @@ def build_child_process_failed_for_libname_message(libname, result): def child_process_func(libname): import os - from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_library import load_lib_no_cache + from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_library import _load_lib_no_cache from cuda.pathfinder.nvidia_dynamic_libs import load_lib loaded_dl_fresh = load_lib(libname) @@ -74,7 +74,7 @@ def child_process_func(libname): if loaded_dl_from_cache is not loaded_dl_fresh: raise RuntimeError("loaded_dl_from_cache is not loaded_dl_fresh") - loaded_dl_no_cache = load_lib_no_cache(libname) + loaded_dl_no_cache = _load_lib_no_cache(libname) if not loaded_dl_no_cache.was_already_loaded_from_elsewhere: raise RuntimeError("loaded_dl_no_cache.was_already_loaded_from_elsewhere") if not os.path.samefile(loaded_dl_no_cache.abs_path, loaded_dl_fresh.abs_path): diff --git a/cuda_pathfinder/tests/test_utils_find_sub_dirs.py b/cuda_pathfinder/tests/test_utils_find_sub_dirs.py index 9aa8a69a7..4c388d246 100644 --- a/cuda_pathfinder/tests/test_utils_find_sub_dirs.py +++ b/cuda_pathfinder/tests/test_utils_find_sub_dirs.py @@ -5,7 +5,7 @@ import pytest -from cuda.pathfinder._utils import ( +from cuda.pathfinder._utils.find_sub_dirs import ( find_sub_dirs, find_sub_dirs_all_sitepackages, find_sub_dirs_sys_path, From 79a8019e015038e35a1752ed03e8e89c6974c727 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 23 Jun 2025 16:41:24 -0700 Subject: [PATCH 15/78] add [project.optional-dependencies] test --- cuda_pathfinder/pyproject.toml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cuda_pathfinder/pyproject.toml b/cuda_pathfinder/pyproject.toml index a1662383b..f54ab5266 100644 --- a/cuda_pathfinder/pyproject.toml +++ b/cuda_pathfinder/pyproject.toml @@ -7,10 +7,15 @@ description = "Pathfinder for CUDA components (mainly libs, headers)" authors = [{ name = "NVIDIA Corporation", email = "cuda-python-conduct@nvidia.com" }] license = "LicenseRef-NVIDIA-SOFTWARE-LICENSE" requires-python = ">=3.9" +dynamic = ["version"] dependencies = [ "pywin32; sys_platform == 'win32'", ] -dynamic = ["version"] + +[project.optional-dependencies] +test = [ + "pytest>=6.2.4", +] [project.urls] Repository = "https://github.com/NVIDIA/cuda-python" From 975ba0b66a5ee7f7242738e53b338f9c113bbba3 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 24 Jun 2025 17:05:14 -0700 Subject: [PATCH 16/78] Adopt cuda_core license. --- cuda_pathfinder/LICENSE | 177 ++++++++++++++++++ .../find_nvidia_dynamic_library.py | 4 +- .../_dynamic_libs/load_dl_common.py | 4 +- .../pathfinder/_dynamic_libs/load_dl_linux.py | 4 +- .../_dynamic_libs/load_dl_windows.py | 4 +- .../load_nvidia_dynamic_library.py | 4 +- .../_dynamic_libs/supported_nvidia_libs.py | 4 +- .../cuda/pathfinder/_utils/find_sub_dirs.py | 4 +- cuda_pathfinder/cuda/pathfinder/_version.py | 4 +- .../cuda/pathfinder/nvidia_dynamic_libs.py | 4 +- cuda_pathfinder/pyproject.toml | 4 +- cuda_pathfinder/tests/conftest.py | 4 +- .../tests/spawned_process_runner.py | 4 +- .../test_nvidia_dynamic_libs_load_lib.py | 4 +- .../tests/test_spawned_process_runner.py | 4 +- .../tests/test_utils_find_sub_dirs.py | 4 +- 16 files changed, 207 insertions(+), 30 deletions(-) create mode 100644 cuda_pathfinder/LICENSE diff --git a/cuda_pathfinder/LICENSE b/cuda_pathfinder/LICENSE new file mode 100644 index 000000000..f433b1a53 --- /dev/null +++ b/cuda_pathfinder/LICENSE @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_library.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_library.py index afb2bfe9e..935aced4a 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_library.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_library.py @@ -1,5 +1,5 @@ -# Copyright 2024-2025 NVIDIA Corporation. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 import functools import glob diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py index 45bfdeeac..47891e394 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py @@ -1,5 +1,5 @@ -# Copyright 2025 NVIDIA Corporation. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 from dataclasses import dataclass from typing import Callable, Optional diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py index 389817248..9ab45d2ef 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py @@ -1,5 +1,5 @@ -# Copyright 2025 NVIDIA Corporation. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 import ctypes import ctypes.util diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py index 1756dbd04..ac24b9cec 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py @@ -1,5 +1,5 @@ -# Copyright 2025 NVIDIA Corporation. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 from typing import Optional diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_library.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_library.py index a7186f4bf..933ecf81c 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_library.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_library.py @@ -1,5 +1,5 @@ -# Copyright 2025 NVIDIA Corporation. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 import functools diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py index 63bde282f..3c2a84879 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py @@ -1,5 +1,5 @@ -# Copyright 2025 NVIDIA Corporation. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 # THIS FILE NEEDS TO BE REVIEWED/UPDATED FOR EACH CTK RELEASE diff --git a/cuda_pathfinder/cuda/pathfinder/_utils/find_sub_dirs.py b/cuda_pathfinder/cuda/pathfinder/_utils/find_sub_dirs.py index 810132625..8af8f24fd 100644 --- a/cuda_pathfinder/cuda/pathfinder/_utils/find_sub_dirs.py +++ b/cuda_pathfinder/cuda/pathfinder/_utils/find_sub_dirs.py @@ -1,5 +1,5 @@ -# Copyright 2024-2025 NVIDIA Corporation. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 import functools import os diff --git a/cuda_pathfinder/cuda/pathfinder/_version.py b/cuda_pathfinder/cuda/pathfinder/_version.py index cccb0e3ac..b3a477e15 100644 --- a/cuda_pathfinder/cuda/pathfinder/_version.py +++ b/cuda_pathfinder/cuda/pathfinder/_version.py @@ -1,4 +1,4 @@ -# Copyright 2025 NVIDIA Corporation. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 __version__ = "0.0.1" diff --git a/cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py b/cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py index 28e0b2278..ca49da152 100644 --- a/cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py +++ b/cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py @@ -1,5 +1,5 @@ -# Copyright 2025 NVIDIA Corporation. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_library import load_lib from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import SUPPORTED_LIBNAMES diff --git a/cuda_pathfinder/pyproject.toml b/cuda_pathfinder/pyproject.toml index f54ab5266..d3d9c0f9a 100644 --- a/cuda_pathfinder/pyproject.toml +++ b/cuda_pathfinder/pyproject.toml @@ -1,5 +1,5 @@ -# Copyright 2025 NVIDIA Corporation. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 [project] name = "cuda-pathfinder" diff --git a/cuda_pathfinder/tests/conftest.py b/cuda_pathfinder/tests/conftest.py index aa31f1376..1069de59b 100644 --- a/cuda_pathfinder/tests/conftest.py +++ b/cuda_pathfinder/tests/conftest.py @@ -1,5 +1,5 @@ -# Copyright 2025 NVIDIA Corporation. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 import pytest diff --git a/cuda_pathfinder/tests/spawned_process_runner.py b/cuda_pathfinder/tests/spawned_process_runner.py index 25362e982..dea460a26 100644 --- a/cuda_pathfinder/tests/spawned_process_runner.py +++ b/cuda_pathfinder/tests/spawned_process_runner.py @@ -1,5 +1,5 @@ -# Copyright 2025 NVIDIA Corporation. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 import multiprocessing import queue # for Empty diff --git a/cuda_pathfinder/tests/test_nvidia_dynamic_libs_load_lib.py b/cuda_pathfinder/tests/test_nvidia_dynamic_libs_load_lib.py index 4c0337ef0..7e1fa8df2 100644 --- a/cuda_pathfinder/tests/test_nvidia_dynamic_libs_load_lib.py +++ b/cuda_pathfinder/tests/test_nvidia_dynamic_libs_load_lib.py @@ -1,5 +1,5 @@ -# Copyright 2025 NVIDIA Corporation. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 import os import sys diff --git a/cuda_pathfinder/tests/test_spawned_process_runner.py b/cuda_pathfinder/tests/test_spawned_process_runner.py index 5a3b7f725..98303adb7 100644 --- a/cuda_pathfinder/tests/test_spawned_process_runner.py +++ b/cuda_pathfinder/tests/test_spawned_process_runner.py @@ -1,5 +1,5 @@ -# Copyright 2025 NVIDIA Corporation. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 # Note: This only covers what is not covered already in test_nvidia_dynamic_libs_load_lib.py diff --git a/cuda_pathfinder/tests/test_utils_find_sub_dirs.py b/cuda_pathfinder/tests/test_utils_find_sub_dirs.py index 4c388d246..80bab2529 100644 --- a/cuda_pathfinder/tests/test_utils_find_sub_dirs.py +++ b/cuda_pathfinder/tests/test_utils_find_sub_dirs.py @@ -1,5 +1,5 @@ -# Copyright 2025 NVIDIA Corporation. All rights reserved. -# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 import os From 3678fb4e8ab8fdbec00d95b6c9b6920fc83430b3 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 24 Jun 2025 23:32:28 -0700 Subject: [PATCH 17/78] =?UTF-8?q?cuda.pathfinder.nvidia=5Fdynamic=5Flibs.l?= =?UTF-8?q?oad=5Flib=20=E2=86=92=20cuda.pathfinder.load=5Fnvidia=5Fdynamic?= =?UTF-8?q?=5Flib?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cuda_bindings/cuda/bindings/path_finder.py | 4 ++-- cuda_pathfinder/cuda/pathfinder/__init__.py | 23 +++++++++++++++++++ ..._library.py => load_nvidia_dynamic_lib.py} | 11 --------- .../cuda/pathfinder/nvidia_dynamic_libs.py | 7 ------ ...lib.py => test_load_nvidia_dynamic_lib.py} | 23 ++++++++----------- 5 files changed, 35 insertions(+), 33 deletions(-) rename cuda_pathfinder/cuda/pathfinder/_dynamic_libs/{load_nvidia_dynamic_library.py => load_nvidia_dynamic_lib.py} (85%) delete mode 100644 cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py rename cuda_pathfinder/tests/{test_nvidia_dynamic_libs_load_lib.py => test_load_nvidia_dynamic_lib.py} (80%) diff --git a/cuda_bindings/cuda/bindings/path_finder.py b/cuda_bindings/cuda/bindings/path_finder.py index a71fd8d20..da129e6b4 100644 --- a/cuda_bindings/cuda/bindings/path_finder.py +++ b/cuda_bindings/cuda/bindings/path_finder.py @@ -1,8 +1,8 @@ # Copyright 2024-2025 NVIDIA Corporation. All rights reserved. # SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE -from cuda.pathfinder.nvidia_dynamic_libs import SUPPORTED_LIBNAMES as _SUPPORTED_LIBNAMES -from cuda.pathfinder.nvidia_dynamic_libs import load_lib as _load_nvidia_dynamic_library +from cuda.pathfinder import SUPPORTED_NVIDIA_LIBNAMES as _SUPPORTED_LIBNAMES +from cuda.pathfinder import load_nvidia_dynamic_lib as _load_nvidia_dynamic_library __all__ = [ "_load_nvidia_dynamic_library", diff --git a/cuda_pathfinder/cuda/pathfinder/__init__.py b/cuda_pathfinder/cuda/pathfinder/__init__.py index e69de29bb..86ac0320e 100644 --- a/cuda_pathfinder/cuda/pathfinder/__init__.py +++ b/cuda_pathfinder/cuda/pathfinder/__init__.py @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +from cuda.pathfinder._dynamic_libs import load_nvidia_dynamic_lib as _load_nvidia_dynamic_lib +from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL +from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import SUPPORTED_LIBNAMES as SUPPORTED_NVIDIA_LIBNAMES + +__all__ = ["SUPPORTED_NVIDIA_LIBNAMES", "load_nvidia_dynamic_lib"] + + +def load_nvidia_dynamic_lib(libname: str) -> LoadedDL: + """Load a NVIDIA dynamic library by name. + + Args: + libname: The name of the library to load (e.g. "cudart", "nvvm", etc.) + + Returns: + A LoadedDL object containing the library handle and path + + Raises: + RuntimeError: If the library cannot be found or loaded + """ + return _load_nvidia_dynamic_lib.load_lib(libname) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_library.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py similarity index 85% rename from cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_library.py rename to cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py index 933ecf81c..ecfc87f11 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_library.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py @@ -49,15 +49,4 @@ def _load_lib_no_cache(libname: str) -> LoadedDL: @functools.cache def load_lib(libname: str) -> LoadedDL: - """Load a NVIDIA dynamic library by name. - - Args: - libname: The name of the library to load (e.g. "cudart", "nvvm", etc.) - - Returns: - A LoadedDL object containing the library handle and path - - Raises: - RuntimeError: If the library cannot be found or loaded - """ return _load_lib_no_cache(libname) diff --git a/cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py b/cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py deleted file mode 100644 index ca49da152..000000000 --- a/cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 - -from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_library import load_lib -from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import SUPPORTED_LIBNAMES - -__all__ = ["load_lib", "SUPPORTED_LIBNAMES"] diff --git a/cuda_pathfinder/tests/test_nvidia_dynamic_libs_load_lib.py b/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py similarity index 80% rename from cuda_pathfinder/tests/test_nvidia_dynamic_libs_load_lib.py rename to cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py index 7e1fa8df2..c28e3fe44 100644 --- a/cuda_pathfinder/tests/test_nvidia_dynamic_libs_load_lib.py +++ b/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py @@ -7,21 +7,19 @@ import pytest import spawned_process_runner -from cuda.pathfinder import nvidia_dynamic_libs +from cuda.pathfinder import SUPPORTED_NVIDIA_LIBNAMES, load_nvidia_dynamic_lib from cuda.pathfinder._dynamic_libs import supported_nvidia_libs -ALL_LIBNAMES = nvidia_dynamic_libs.SUPPORTED_LIBNAMES + supported_nvidia_libs.PARTIALLY_SUPPORTED_LIBNAMES_ALL -ALL_LIBNAMES_LINUX = nvidia_dynamic_libs.SUPPORTED_LIBNAMES + supported_nvidia_libs.PARTIALLY_SUPPORTED_LIBNAMES_LINUX -ALL_LIBNAMES_WINDOWS = ( - nvidia_dynamic_libs.SUPPORTED_LIBNAMES + supported_nvidia_libs.PARTIALLY_SUPPORTED_LIBNAMES_WINDOWS -) -if os.environ.get("CUDA_PATHFINDER_TEST_ALL_LIBNAMES", False): +ALL_LIBNAMES = SUPPORTED_NVIDIA_LIBNAMES + supported_nvidia_libs.PARTIALLY_SUPPORTED_LIBNAMES_ALL +ALL_LIBNAMES_LINUX = SUPPORTED_NVIDIA_LIBNAMES + supported_nvidia_libs.PARTIALLY_SUPPORTED_LIBNAMES_LINUX +ALL_LIBNAMES_WINDOWS = SUPPORTED_NVIDIA_LIBNAMES + supported_nvidia_libs.PARTIALLY_SUPPORTED_LIBNAMES_WINDOWS +if os.environ.get("CUDA_PATHFINDER_TEST_ALL_NVIDIA_LIBNAMES", False): if sys.platform == "win32": TEST_FIND_OR_LOAD_LIBNAMES = ALL_LIBNAMES_WINDOWS else: TEST_FIND_OR_LOAD_LIBNAMES = ALL_LIBNAMES_LINUX else: - TEST_FIND_OR_LOAD_LIBNAMES = nvidia_dynamic_libs.SUPPORTED_LIBNAMES + TEST_FIND_OR_LOAD_LIBNAMES = SUPPORTED_NVIDIA_LIBNAMES def test_all_libnames_linux_sonames_consistency(): @@ -63,14 +61,13 @@ def build_child_process_failed_for_libname_message(libname, result): def child_process_func(libname): import os - from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_library import _load_lib_no_cache - from cuda.pathfinder.nvidia_dynamic_libs import load_lib + from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_lib import _load_lib_no_cache - loaded_dl_fresh = load_lib(libname) + loaded_dl_fresh = load_nvidia_dynamic_lib(libname) if loaded_dl_fresh.was_already_loaded_from_elsewhere: raise RuntimeError("loaded_dl_fresh.was_already_loaded_from_elsewhere") - loaded_dl_from_cache = load_lib(libname) + loaded_dl_from_cache = load_nvidia_dynamic_lib(libname) if loaded_dl_from_cache is not loaded_dl_fresh: raise RuntimeError("loaded_dl_from_cache is not loaded_dl_fresh") @@ -84,7 +81,7 @@ def child_process_func(libname): @pytest.mark.parametrize("libname", TEST_FIND_OR_LOAD_LIBNAMES) -def test_find_or_load_nvidia_dynamic_library(info_summary_append, libname): +def test_load_nvidia_dynamic_lib(info_summary_append, libname): # We intentionally run each dynamic library operation in a child process # to ensure isolation of global dynamic linking state (e.g., dlopen handles). # Without child processes, loading/unloading libraries during testing could From 58b2513675275843a0a4c66714c20eb1e89d94a3 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 1 Jul 2025 04:35:49 -0700 Subject: [PATCH 18/78] =?UTF-8?q?Revert=20"cuda.pathfinder.nvidia=5Fdynami?= =?UTF-8?q?c=5Flibs.load=5Flib=20=E2=86=92=20cuda.pathfinder.load=5Fnvidia?= =?UTF-8?q?=5Fdynamic=5Flib"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 3678fb4e8ab8fdbec00d95b6c9b6920fc83430b3. --- cuda_bindings/cuda/bindings/path_finder.py | 4 ++-- cuda_pathfinder/cuda/pathfinder/__init__.py | 23 ------------------- ..._lib.py => load_nvidia_dynamic_library.py} | 11 +++++++++ .../cuda/pathfinder/nvidia_dynamic_libs.py | 7 ++++++ ...y => test_nvidia_dynamic_libs_load_lib.py} | 23 +++++++++++-------- 5 files changed, 33 insertions(+), 35 deletions(-) rename cuda_pathfinder/cuda/pathfinder/_dynamic_libs/{load_nvidia_dynamic_lib.py => load_nvidia_dynamic_library.py} (85%) create mode 100644 cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py rename cuda_pathfinder/tests/{test_load_nvidia_dynamic_lib.py => test_nvidia_dynamic_libs_load_lib.py} (80%) diff --git a/cuda_bindings/cuda/bindings/path_finder.py b/cuda_bindings/cuda/bindings/path_finder.py index da129e6b4..a71fd8d20 100644 --- a/cuda_bindings/cuda/bindings/path_finder.py +++ b/cuda_bindings/cuda/bindings/path_finder.py @@ -1,8 +1,8 @@ # Copyright 2024-2025 NVIDIA Corporation. All rights reserved. # SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE -from cuda.pathfinder import SUPPORTED_NVIDIA_LIBNAMES as _SUPPORTED_LIBNAMES -from cuda.pathfinder import load_nvidia_dynamic_lib as _load_nvidia_dynamic_library +from cuda.pathfinder.nvidia_dynamic_libs import SUPPORTED_LIBNAMES as _SUPPORTED_LIBNAMES +from cuda.pathfinder.nvidia_dynamic_libs import load_lib as _load_nvidia_dynamic_library __all__ = [ "_load_nvidia_dynamic_library", diff --git a/cuda_pathfinder/cuda/pathfinder/__init__.py b/cuda_pathfinder/cuda/pathfinder/__init__.py index 86ac0320e..e69de29bb 100644 --- a/cuda_pathfinder/cuda/pathfinder/__init__.py +++ b/cuda_pathfinder/cuda/pathfinder/__init__.py @@ -1,23 +0,0 @@ -# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 - -from cuda.pathfinder._dynamic_libs import load_nvidia_dynamic_lib as _load_nvidia_dynamic_lib -from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL -from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import SUPPORTED_LIBNAMES as SUPPORTED_NVIDIA_LIBNAMES - -__all__ = ["SUPPORTED_NVIDIA_LIBNAMES", "load_nvidia_dynamic_lib"] - - -def load_nvidia_dynamic_lib(libname: str) -> LoadedDL: - """Load a NVIDIA dynamic library by name. - - Args: - libname: The name of the library to load (e.g. "cudart", "nvvm", etc.) - - Returns: - A LoadedDL object containing the library handle and path - - Raises: - RuntimeError: If the library cannot be found or loaded - """ - return _load_nvidia_dynamic_lib.load_lib(libname) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_library.py similarity index 85% rename from cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py rename to cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_library.py index ecfc87f11..933ecf81c 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_library.py @@ -49,4 +49,15 @@ def _load_lib_no_cache(libname: str) -> LoadedDL: @functools.cache def load_lib(libname: str) -> LoadedDL: + """Load a NVIDIA dynamic library by name. + + Args: + libname: The name of the library to load (e.g. "cudart", "nvvm", etc.) + + Returns: + A LoadedDL object containing the library handle and path + + Raises: + RuntimeError: If the library cannot be found or loaded + """ return _load_lib_no_cache(libname) diff --git a/cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py b/cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py new file mode 100644 index 000000000..ca49da152 --- /dev/null +++ b/cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py @@ -0,0 +1,7 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_library import load_lib +from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import SUPPORTED_LIBNAMES + +__all__ = ["load_lib", "SUPPORTED_LIBNAMES"] diff --git a/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py b/cuda_pathfinder/tests/test_nvidia_dynamic_libs_load_lib.py similarity index 80% rename from cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py rename to cuda_pathfinder/tests/test_nvidia_dynamic_libs_load_lib.py index c28e3fe44..7e1fa8df2 100644 --- a/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/tests/test_nvidia_dynamic_libs_load_lib.py @@ -7,19 +7,21 @@ import pytest import spawned_process_runner -from cuda.pathfinder import SUPPORTED_NVIDIA_LIBNAMES, load_nvidia_dynamic_lib +from cuda.pathfinder import nvidia_dynamic_libs from cuda.pathfinder._dynamic_libs import supported_nvidia_libs -ALL_LIBNAMES = SUPPORTED_NVIDIA_LIBNAMES + supported_nvidia_libs.PARTIALLY_SUPPORTED_LIBNAMES_ALL -ALL_LIBNAMES_LINUX = SUPPORTED_NVIDIA_LIBNAMES + supported_nvidia_libs.PARTIALLY_SUPPORTED_LIBNAMES_LINUX -ALL_LIBNAMES_WINDOWS = SUPPORTED_NVIDIA_LIBNAMES + supported_nvidia_libs.PARTIALLY_SUPPORTED_LIBNAMES_WINDOWS -if os.environ.get("CUDA_PATHFINDER_TEST_ALL_NVIDIA_LIBNAMES", False): +ALL_LIBNAMES = nvidia_dynamic_libs.SUPPORTED_LIBNAMES + supported_nvidia_libs.PARTIALLY_SUPPORTED_LIBNAMES_ALL +ALL_LIBNAMES_LINUX = nvidia_dynamic_libs.SUPPORTED_LIBNAMES + supported_nvidia_libs.PARTIALLY_SUPPORTED_LIBNAMES_LINUX +ALL_LIBNAMES_WINDOWS = ( + nvidia_dynamic_libs.SUPPORTED_LIBNAMES + supported_nvidia_libs.PARTIALLY_SUPPORTED_LIBNAMES_WINDOWS +) +if os.environ.get("CUDA_PATHFINDER_TEST_ALL_LIBNAMES", False): if sys.platform == "win32": TEST_FIND_OR_LOAD_LIBNAMES = ALL_LIBNAMES_WINDOWS else: TEST_FIND_OR_LOAD_LIBNAMES = ALL_LIBNAMES_LINUX else: - TEST_FIND_OR_LOAD_LIBNAMES = SUPPORTED_NVIDIA_LIBNAMES + TEST_FIND_OR_LOAD_LIBNAMES = nvidia_dynamic_libs.SUPPORTED_LIBNAMES def test_all_libnames_linux_sonames_consistency(): @@ -61,13 +63,14 @@ def build_child_process_failed_for_libname_message(libname, result): def child_process_func(libname): import os - from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_lib import _load_lib_no_cache + from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_library import _load_lib_no_cache + from cuda.pathfinder.nvidia_dynamic_libs import load_lib - loaded_dl_fresh = load_nvidia_dynamic_lib(libname) + loaded_dl_fresh = load_lib(libname) if loaded_dl_fresh.was_already_loaded_from_elsewhere: raise RuntimeError("loaded_dl_fresh.was_already_loaded_from_elsewhere") - loaded_dl_from_cache = load_nvidia_dynamic_lib(libname) + loaded_dl_from_cache = load_lib(libname) if loaded_dl_from_cache is not loaded_dl_fresh: raise RuntimeError("loaded_dl_from_cache is not loaded_dl_fresh") @@ -81,7 +84,7 @@ def child_process_func(libname): @pytest.mark.parametrize("libname", TEST_FIND_OR_LOAD_LIBNAMES) -def test_load_nvidia_dynamic_lib(info_summary_append, libname): +def test_find_or_load_nvidia_dynamic_library(info_summary_append, libname): # We intentionally run each dynamic library operation in a child process # to ensure isolation of global dynamic linking state (e.g., dlopen handles). # Without child processes, loading/unloading libraries during testing could From 050f857d0dc34bbf0a78b3bc740033291c9151eb Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 1 Jul 2025 04:46:27 -0700 Subject: [PATCH 19/78] Simple name changes for consistency: library -> lib --- ...nvidia_dynamic_library.py => find_nvidia_dynamic_lib.py} | 6 +++--- ...nvidia_dynamic_library.py => load_nvidia_dynamic_lib.py} | 6 ++---- cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py | 2 +- cuda_pathfinder/tests/test_nvidia_dynamic_libs_load_lib.py | 4 ++-- 4 files changed, 8 insertions(+), 10 deletions(-) rename cuda_pathfinder/cuda/pathfinder/_dynamic_libs/{find_nvidia_dynamic_library.py => find_nvidia_dynamic_lib.py} (97%) rename cuda_pathfinder/cuda/pathfinder/_dynamic_libs/{load_nvidia_dynamic_library.py => load_nvidia_dynamic_lib.py} (92%) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_library.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py similarity index 97% rename from cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_library.py rename to cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py index 935aced4a..9f07d6345 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_library.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py @@ -111,7 +111,7 @@ def _find_dll_using_lib_dir(lib_dir, libname, error_messages, attachments): return None -class _find_nvidia_dynamic_library: +class _find_nvidia_dynamic_lib: def __init__(self, libname: str): self.libname = libname self.error_messages = [] @@ -164,5 +164,5 @@ def raise_if_abs_path_is_None(self): @functools.cache -def find_nvidia_dynamic_library(libname: str) -> str: - return _find_nvidia_dynamic_library(libname).raise_if_abs_path_is_None() +def find_nvidia_dynamic_lib(libname: str) -> str: + return _find_nvidia_dynamic_lib(libname).raise_if_abs_path_is_None() diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_library.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py similarity index 92% rename from cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_library.py rename to cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py index 933ecf81c..dd40c13b9 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_library.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py @@ -3,9 +3,7 @@ import functools -from cuda.pathfinder._dynamic_libs.find_nvidia_dynamic_library import ( - _find_nvidia_dynamic_library, -) +from cuda.pathfinder._dynamic_libs.find_nvidia_dynamic_lib import _find_nvidia_dynamic_lib from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL, load_dependencies from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import IS_WINDOWS @@ -35,7 +33,7 @@ def _load_lib_no_cache(libname: str) -> LoadedDL: load_dependencies(libname, load_lib) # Find the library path - found = _find_nvidia_dynamic_library(libname) + found = _find_nvidia_dynamic_lib(libname) if found.abs_path is None: loaded = load_with_system_search(libname, found.lib_searched_for) if loaded is not None: diff --git a/cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py b/cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py index ca49da152..de999767b 100644 --- a/cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py +++ b/cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 -from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_library import load_lib +from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_lib import load_lib from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import SUPPORTED_LIBNAMES __all__ = ["load_lib", "SUPPORTED_LIBNAMES"] diff --git a/cuda_pathfinder/tests/test_nvidia_dynamic_libs_load_lib.py b/cuda_pathfinder/tests/test_nvidia_dynamic_libs_load_lib.py index 7e1fa8df2..d1996277d 100644 --- a/cuda_pathfinder/tests/test_nvidia_dynamic_libs_load_lib.py +++ b/cuda_pathfinder/tests/test_nvidia_dynamic_libs_load_lib.py @@ -63,7 +63,7 @@ def build_child_process_failed_for_libname_message(libname, result): def child_process_func(libname): import os - from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_library import _load_lib_no_cache + from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_lib import _load_lib_no_cache from cuda.pathfinder.nvidia_dynamic_libs import load_lib loaded_dl_fresh = load_lib(libname) @@ -84,7 +84,7 @@ def child_process_func(libname): @pytest.mark.parametrize("libname", TEST_FIND_OR_LOAD_LIBNAMES) -def test_find_or_load_nvidia_dynamic_library(info_summary_append, libname): +def test_find_or_load_nvidia_dynamic_lib(info_summary_append, libname): # We intentionally run each dynamic library operation in a child process # to ensure isolation of global dynamic linking state (e.g., dlopen handles). # Without child processes, loading/unloading libraries during testing could From 1933869587d044c41f2dc8ec7cf58b71634d2b42 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 1 Jul 2025 05:22:42 -0700 Subject: [PATCH 20/78] Implement consensus API --- cuda_pathfinder/cuda/pathfinder/README.md | 6 +++--- cuda_pathfinder/cuda/pathfinder/__init__.py | 6 ++++++ .../_dynamic_libs/load_nvidia_dynamic_lib.py | 4 ++-- .../cuda/pathfinder/nvidia_dynamic_libs.py | 7 ++++--- ...d_lib.py => test_load_nvidia_dynamic_lib.py} | 17 +++++++---------- 5 files changed, 22 insertions(+), 18 deletions(-) rename cuda_pathfinder/tests/{test_nvidia_dynamic_libs_load_lib.py => test_load_nvidia_dynamic_lib.py} (85%) diff --git a/cuda_pathfinder/cuda/pathfinder/README.md b/cuda_pathfinder/cuda/pathfinder/README.md index 2619ce7ae..a2cc16d58 100644 --- a/cuda_pathfinder/cuda/pathfinder/README.md +++ b/cuda_pathfinder/cuda/pathfinder/README.md @@ -5,13 +5,13 @@ Currently exposes two primary interfaces: ``` -cuda.pathfinder.SUPPORTED_LIBNAMES # ('nvJitLink', 'nvrtc', 'nvvm') -cuda.pathfinder.nvidia_dynamic_libs.load_lib(libname: str) -> LoadedDL +cuda.pathfinder.SUPPORTED_NVIDIA_LIBNAMES # ('nvJitLink', 'nvrtc', 'nvvm') +cuda.pathfinder.load_nvidia_dynamic_lib(libname: str) -> LoadedDL ``` ## Dynamic Library Loading Search Priority -The `cuda.pathfinder.nvidia_dynamic_libs.load_lib` function implements a +The `cuda.pathfinder.load_nvidia_dynamic_lib` function implements a hierarchical search strategy for locating NVIDIA shared libraries: 0. **Check if a library was loaded into the process already by some other means.** diff --git a/cuda_pathfinder/cuda/pathfinder/__init__.py b/cuda_pathfinder/cuda/pathfinder/__init__.py index e69de29bb..b1b1f2329 100644 --- a/cuda_pathfinder/cuda/pathfinder/__init__.py +++ b/cuda_pathfinder/cuda/pathfinder/__init__.py @@ -0,0 +1,6 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +from cuda.pathfinder.nvidia_dynamic_libs import SUPPORTED_NVIDIA_LIBNAMES, LoadedDL, load_nvidia_dynamic_lib + +__all__ = ["LoadedDL", "load_nvidia_dynamic_lib", "SUPPORTED_NVIDIA_LIBNAMES"] diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py index dd40c13b9..b6dc484e1 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py @@ -30,7 +30,7 @@ def _load_lib_no_cache(libname: str) -> LoadedDL: return loaded # Load dependencies first - load_dependencies(libname, load_lib) + load_dependencies(libname, load_nvidia_dynamic_lib) # Find the library path found = _find_nvidia_dynamic_lib(libname) @@ -46,7 +46,7 @@ def _load_lib_no_cache(libname: str) -> LoadedDL: @functools.cache -def load_lib(libname: str) -> LoadedDL: +def load_nvidia_dynamic_lib(libname: str) -> LoadedDL: """Load a NVIDIA dynamic library by name. Args: diff --git a/cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py b/cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py index de999767b..9997e252c 100644 --- a/cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py +++ b/cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py @@ -1,7 +1,8 @@ # SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 -from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_lib import load_lib -from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import SUPPORTED_LIBNAMES +from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL +from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_lib import load_nvidia_dynamic_lib +from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import SUPPORTED_LIBNAMES as SUPPORTED_NVIDIA_LIBNAMES -__all__ = ["load_lib", "SUPPORTED_LIBNAMES"] +__all__ = ["LoadedDL", "load_nvidia_dynamic_lib", "SUPPORTED_NVIDIA_LIBNAMES"] diff --git a/cuda_pathfinder/tests/test_nvidia_dynamic_libs_load_lib.py b/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py similarity index 85% rename from cuda_pathfinder/tests/test_nvidia_dynamic_libs_load_lib.py rename to cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py index d1996277d..90611817a 100644 --- a/cuda_pathfinder/tests/test_nvidia_dynamic_libs_load_lib.py +++ b/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py @@ -7,21 +7,19 @@ import pytest import spawned_process_runner -from cuda.pathfinder import nvidia_dynamic_libs +from cuda.pathfinder import SUPPORTED_NVIDIA_LIBNAMES, load_nvidia_dynamic_lib from cuda.pathfinder._dynamic_libs import supported_nvidia_libs -ALL_LIBNAMES = nvidia_dynamic_libs.SUPPORTED_LIBNAMES + supported_nvidia_libs.PARTIALLY_SUPPORTED_LIBNAMES_ALL -ALL_LIBNAMES_LINUX = nvidia_dynamic_libs.SUPPORTED_LIBNAMES + supported_nvidia_libs.PARTIALLY_SUPPORTED_LIBNAMES_LINUX -ALL_LIBNAMES_WINDOWS = ( - nvidia_dynamic_libs.SUPPORTED_LIBNAMES + supported_nvidia_libs.PARTIALLY_SUPPORTED_LIBNAMES_WINDOWS -) +ALL_LIBNAMES = SUPPORTED_NVIDIA_LIBNAMES + supported_nvidia_libs.PARTIALLY_SUPPORTED_LIBNAMES_ALL +ALL_LIBNAMES_LINUX = SUPPORTED_NVIDIA_LIBNAMES + supported_nvidia_libs.PARTIALLY_SUPPORTED_LIBNAMES_LINUX +ALL_LIBNAMES_WINDOWS = SUPPORTED_NVIDIA_LIBNAMES + supported_nvidia_libs.PARTIALLY_SUPPORTED_LIBNAMES_WINDOWS if os.environ.get("CUDA_PATHFINDER_TEST_ALL_LIBNAMES", False): if sys.platform == "win32": TEST_FIND_OR_LOAD_LIBNAMES = ALL_LIBNAMES_WINDOWS else: TEST_FIND_OR_LOAD_LIBNAMES = ALL_LIBNAMES_LINUX else: - TEST_FIND_OR_LOAD_LIBNAMES = nvidia_dynamic_libs.SUPPORTED_LIBNAMES + TEST_FIND_OR_LOAD_LIBNAMES = SUPPORTED_NVIDIA_LIBNAMES def test_all_libnames_linux_sonames_consistency(): @@ -64,13 +62,12 @@ def child_process_func(libname): import os from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_lib import _load_lib_no_cache - from cuda.pathfinder.nvidia_dynamic_libs import load_lib - loaded_dl_fresh = load_lib(libname) + loaded_dl_fresh = load_nvidia_dynamic_lib(libname) if loaded_dl_fresh.was_already_loaded_from_elsewhere: raise RuntimeError("loaded_dl_fresh.was_already_loaded_from_elsewhere") - loaded_dl_from_cache = load_lib(libname) + loaded_dl_from_cache = load_nvidia_dynamic_lib(libname) if loaded_dl_from_cache is not loaded_dl_fresh: raise RuntimeError("loaded_dl_from_cache is not loaded_dl_fresh") From 50f4f8eade53d8cfd4ce2cc53fc61be7fa023e82 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 1 Jul 2025 05:25:19 -0700 Subject: [PATCH 21/78] Use suggested version number 0.1.0 --- cuda_pathfinder/cuda/pathfinder/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cuda_pathfinder/cuda/pathfinder/_version.py b/cuda_pathfinder/cuda/pathfinder/_version.py index b3a477e15..d5829b003 100644 --- a/cuda_pathfinder/cuda/pathfinder/_version.py +++ b/cuda_pathfinder/cuda/pathfinder/_version.py @@ -1,4 +1,4 @@ # SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 -__version__ = "0.0.1" +__version__ = "0.1.0" From 787236c14e07e4173eced30d4066d821d6cbd016 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 1 Jul 2025 05:31:23 -0700 Subject: [PATCH 22/78] Fix oversight: `license =` line in pyproject.toml --- cuda_pathfinder/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cuda_pathfinder/pyproject.toml b/cuda_pathfinder/pyproject.toml index d3d9c0f9a..f033a4097 100644 --- a/cuda_pathfinder/pyproject.toml +++ b/cuda_pathfinder/pyproject.toml @@ -5,7 +5,7 @@ name = "cuda-pathfinder" description = "Pathfinder for CUDA components (mainly libs, headers)" authors = [{ name = "NVIDIA Corporation", email = "cuda-python-conduct@nvidia.com" }] -license = "LicenseRef-NVIDIA-SOFTWARE-LICENSE" +license = "Apache-2.0" requires-python = ">=3.9" dynamic = ["version"] dependencies = [ From 5b5078b8bf20a823e71065b492ebc0c69abd894f Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 1 Jul 2025 05:33:44 -0700 Subject: [PATCH 23/78] Simplify `description =` line in pyproject.toml --- cuda_pathfinder/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cuda_pathfinder/pyproject.toml b/cuda_pathfinder/pyproject.toml index f033a4097..a39932a13 100644 --- a/cuda_pathfinder/pyproject.toml +++ b/cuda_pathfinder/pyproject.toml @@ -3,7 +3,7 @@ [project] name = "cuda-pathfinder" -description = "Pathfinder for CUDA components (mainly libs, headers)" +description = "Pathfinder for CUDA components" authors = [{ name = "NVIDIA Corporation", email = "cuda-python-conduct@nvidia.com" }] license = "Apache-2.0" requires-python = ">=3.9" From 13e08ae6ce144ac0d595801314bc3cae71f68ec8 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 1 Jul 2025 05:43:42 -0700 Subject: [PATCH 24/78] Remove Maintenance Requirements from main README. Add the list of "Likely candidates for updates" to supported_nvidia_libs.py instead. --- cuda_pathfinder/cuda/pathfinder/README.md | 9 --------- .../pathfinder/_dynamic_libs/supported_nvidia_libs.py | 5 +++++ 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/cuda_pathfinder/cuda/pathfinder/README.md b/cuda_pathfinder/cuda/pathfinder/README.md index a2cc16d58..f071ccc2f 100644 --- a/cuda_pathfinder/cuda/pathfinder/README.md +++ b/cuda_pathfinder/cuda/pathfinder/README.md @@ -40,12 +40,3 @@ hierarchical search strategy for locating NVIDIA shared libraries: Note that the search is done on a per-library basis. Currently there is no centralized mechanism that ensures all libraries are found in the same way. - -## Maintenance Requirements - -These key components must be updated for new CUDA Toolkit releases: - -- `supported_nvidia_libs.SUPPORTED_LIBNAMES` -- `supported_nvidia_libs.SUPPORTED_WINDOWS_DLLS` -- `supported_nvidia_libs.SUPPORTED_LINUX_SONAMES` -- `supported_nvidia_libs.EXPECTED_LIB_SYMBOLS` diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py index 3c2a84879..7fde02f7b 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py @@ -2,6 +2,11 @@ # SPDX-License-Identifier: Apache-2.0 # THIS FILE NEEDS TO BE REVIEWED/UPDATED FOR EACH CTK RELEASE +# Likely candidates for updates are: +# SUPPORTED_LIBNAMES +# SUPPORTED_WINDOWS_DLLS +# SUPPORTED_LINUX_SONAMES +# EXPECTED_LIB_SYMBOLS import sys From 97f9dc8aaa65c1c3bc30d62accbe61eaffb8a31e Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 1 Jul 2025 08:16:48 -0700 Subject: [PATCH 25/78] Adjust cuda_bindings/cuda/bindings/path_finder.py to changes in cuda_pathfinder/ --- cuda_bindings/cuda/bindings/path_finder.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cuda_bindings/cuda/bindings/path_finder.py b/cuda_bindings/cuda/bindings/path_finder.py index a71fd8d20..da129e6b4 100644 --- a/cuda_bindings/cuda/bindings/path_finder.py +++ b/cuda_bindings/cuda/bindings/path_finder.py @@ -1,8 +1,8 @@ # Copyright 2024-2025 NVIDIA Corporation. All rights reserved. # SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE -from cuda.pathfinder.nvidia_dynamic_libs import SUPPORTED_LIBNAMES as _SUPPORTED_LIBNAMES -from cuda.pathfinder.nvidia_dynamic_libs import load_lib as _load_nvidia_dynamic_library +from cuda.pathfinder import SUPPORTED_NVIDIA_LIBNAMES as _SUPPORTED_LIBNAMES +from cuda.pathfinder import load_nvidia_dynamic_lib as _load_nvidia_dynamic_library __all__ = [ "_load_nvidia_dynamic_library", From e18cf057f0eed41f2eab1164f89ffb285a13daa0 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 1 Jul 2025 08:18:05 -0700 Subject: [PATCH 26/78] First guess at what changes are needed to include cuda_pathfinder in .github/workflows --- .github/workflows/build-wheel.yml | 34 ++++++++++++++++++++++++ .github/workflows/test-wheel-linux.yml | 18 +++++++++++-- .github/workflows/test-wheel-windows.yml | 8 ++++-- ci/tools/env-vars | 4 +++ cuda_bindings/pyproject.toml | 1 + 5 files changed, 61 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-wheel.yml b/.github/workflows/build-wheel.yml index 3bd427256..e0e7a2a06 100644 --- a/.github/workflows/build-wheel.yml +++ b/.github/workflows/build-wheel.yml @@ -70,6 +70,40 @@ jobs: run: | env + - name: Build cuda.pathfinder wheel + uses: pypa/cibuildwheel@5f22145df44122af0f5a201f93cf0207171beca7 # v3.0.0 + env: + CIBW_BUILD: ${{ env.CIBW_BUILD }} + CIBW_ARCHS_LINUX: "native" + CIBW_BUILD_VERBOSITY: 1 + CIBW_BEFORE_BUILD_WINDOWS: "pip install delvewheel" + CIBW_REPAIR_WHEEL_COMMAND_WINDOWS: "delvewheel repair --namespace-pkg cuda -w {dest_dir} {wheel}" + with: + package-dir: ./cuda_pathfinder/ + output-dir: ${{ env.CUDA_PATHFINDER_ARTIFACTS_DIR }} + + - name: List the cuda.pathfinder artifacts directory + run: | + if [[ "${{ inputs.host-platform }}" == win* ]]; then + export CHOWN=chown + else + export CHOWN="sudo chown" + fi + $CHOWN -R $(whoami) ${{ env.CUDA_PATHFINDER_ARTIFACTS_DIR }} + ls -lahR ${{ env.CUDA_PATHFINDER_ARTIFACTS_DIR }} + + - name: Check cuda.pathfinder wheel + run: | + pip install twine + twine check ${{ env.CUDA_PATHFINDER_ARTIFACTS_DIR }}/*.whl + + - name: Upload cuda.pathfinder build artifacts + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: ${{ env.CUDA_PATHFINDER_ARTIFACT_NAME }} + path: ${{ env.CUDA_PATHFINDER_ARTIFACTS_DIR }}/*.whl + if-no-files-found: error + - name: Build cuda.core wheel uses: pypa/cibuildwheel@5f22145df44122af0f5a201f93cf0207171beca7 # v3.0.0 env: diff --git a/.github/workflows/test-wheel-linux.yml b/.github/workflows/test-wheel-linux.yml index 59c1ae43b..481059d19 100644 --- a/.github/workflows/test-wheel-linux.yml +++ b/.github/workflows/test-wheel-linux.yml @@ -163,6 +163,13 @@ jobs: SHA: ${{ github.sha }} run: ./ci/tools/env-vars test + - name: Download cuda-pathfinder build artifacts + if: ${{ env.SKIP_CUDA_BINDINGS_TEST == '0'}} + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + name: ${{ env.CUDA_PATHFINDER_ARTIFACT_NAME }} + path: ${{ env.CUDA_PATHFINDER_ARTIFACTS_DIR }} + - name: Download cuda-python build artifacts if: ${{ env.SKIP_CUDA_BINDINGS_TEST == '0'}} uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 @@ -286,6 +293,13 @@ jobs: - name: Set up compute-sanitizer run: setup-sanitizer + - name: Run cuda.pathfinder tests + if: ${{ env.SKIP_CUDA_PATHFINDER_TEST == '0' }} + env: + CUDA_VER: ${{ matrix.CUDA_VER }} + LOCAL_CTK: ${{ matrix.LOCAL_CTK }} + run: run-tests pathfinder + - name: Run cuda.bindings tests if: ${{ env.SKIP_CUDA_BINDINGS_TEST == '0' }} env: @@ -302,7 +316,7 @@ jobs: - name: Ensure cuda-python installable run: | if [[ "${{ matrix.LOCAL_CTK }}" == 1 ]]; then - pip install cuda_python*.whl + pip install cuda_pathfinder*.whl cuda_python*.whl else - pip install $(ls cuda_python*.whl)[all] + pip install $(ls cuda_pathfinder*.whl) $(ls cuda_python*.whl)[all] fi diff --git a/.github/workflows/test-wheel-windows.yml b/.github/workflows/test-wheel-windows.yml index f5c6db6fc..86769d4a0 100644 --- a/.github/workflows/test-wheel-windows.yml +++ b/.github/workflows/test-wheel-windows.yml @@ -268,7 +268,11 @@ jobs: - name: Ensure cuda-python installable run: | if ('${{ matrix.LOCAL_CTK }}' -eq '1') { - pip install (Get-ChildItem -Filter cuda_python*.whl).FullName + $pathfinder = (Get-ChildItem -Filter cuda_pathfinder*.whl).FullName + $umbrella = (Get-ChildItem -Filter cuda_python*.whl).FullName + pip install $pathfinder $umbrella } else { - pip install "$((Get-ChildItem -Filter cuda_python*.whl).FullName)[all]" + $pathfinder = (Get-ChildItem -Filter cuda_pathfinder*.whl).FullName + $umbrella = (Get-ChildItem -Filter cuda_python*.whl).FullName + pip install "$pathfinder" "$umbrella[all]" } diff --git a/ci/tools/env-vars b/ci/tools/env-vars index 7211dc08f..94a7ed019 100755 --- a/ci/tools/env-vars +++ b/ci/tools/env-vars @@ -28,6 +28,10 @@ elif [[ "${HOST_PLATFORM}" == win* ]]; then fi echo "${TOOLS_PATH}" >> $GITHUB_PATH +CUDA_PATHFINDER_ARTIFACT_BASENAME="cuda-pathfinder-noarch" +echo "CUDA_PATHFINDER_ARTIFACT_BASENAME=${CUDA_PATHFINDER_ARTIFACT_BASENAME}" >> $GITHUB_ENV +echo "CUDA_PATHFINDER_ARTIFACT_NAME=${CUDA_PATHFINDER_ARTIFACT_BASENAME}-${SHA}" >> $GITHUB_ENV +echo "CUDA_PATHFINDER_ARTIFACTS_DIR=$(realpath "${REPO_DIR}/cuda_pathfinder/dist")" >> $GITHUB_ENV echo "CUDA_BINDINGS_PARALLEL_LEVEL=$(nproc)" >> $GITHUB_ENV CUDA_CORE_ARTIFACT_BASENAME="cuda-core-python${PYTHON_VERSION_FORMATTED}-${HOST_PLATFORM}" echo "CUDA_CORE_ARTIFACT_BASENAME=${CUDA_CORE_ARTIFACT_BASENAME}" >> $GITHUB_ENV diff --git a/cuda_bindings/pyproject.toml b/cuda_bindings/pyproject.toml index 42ea4bd96..50d0ba5b2 100644 --- a/cuda_bindings/pyproject.toml +++ b/cuda_bindings/pyproject.toml @@ -27,6 +27,7 @@ dynamic = [ "readme", ] dependencies = [ + "cuda-pathfinder", "pywin32; sys_platform == 'win32'", ] From 36491c88a7639a655a9d6c153a4b36a366a85c6f Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 2 Jul 2025 10:54:58 -0700 Subject: [PATCH 27/78] git mv nvidia_dynamic_libs.py __init__.py --- cuda_pathfinder/cuda/pathfinder/__init__.py | 4 +++- cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py | 8 -------- 2 files changed, 3 insertions(+), 9 deletions(-) delete mode 100644 cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py diff --git a/cuda_pathfinder/cuda/pathfinder/__init__.py b/cuda_pathfinder/cuda/pathfinder/__init__.py index b1b1f2329..9997e252c 100644 --- a/cuda_pathfinder/cuda/pathfinder/__init__.py +++ b/cuda_pathfinder/cuda/pathfinder/__init__.py @@ -1,6 +1,8 @@ # SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 -from cuda.pathfinder.nvidia_dynamic_libs import SUPPORTED_NVIDIA_LIBNAMES, LoadedDL, load_nvidia_dynamic_lib +from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL +from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_lib import load_nvidia_dynamic_lib +from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import SUPPORTED_LIBNAMES as SUPPORTED_NVIDIA_LIBNAMES __all__ = ["LoadedDL", "load_nvidia_dynamic_lib", "SUPPORTED_NVIDIA_LIBNAMES"] diff --git a/cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py b/cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py deleted file mode 100644 index 9997e252c..000000000 --- a/cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 - -from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL -from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_lib import load_nvidia_dynamic_lib -from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import SUPPORTED_LIBNAMES as SUPPORTED_NVIDIA_LIBNAMES - -__all__ = ["LoadedDL", "load_nvidia_dynamic_lib", "SUPPORTED_NVIDIA_LIBNAMES"] From c6187db3fd1dec0bc7d5a71f59095258ee795127 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 2 Jul 2025 11:38:30 -0700 Subject: [PATCH 28/78] Do not use `cibuildwheel` for a `noarch` package (`cuda-pathfinder`). Use `pip wheel` instead. https://github.com/NVIDIA/cuda-python/pull/723#discussion_r2178825558 --- .github/workflows/build-wheel.yml | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build-wheel.yml b/.github/workflows/build-wheel.yml index e0e7a2a06..af858a201 100644 --- a/.github/workflows/build-wheel.yml +++ b/.github/workflows/build-wheel.yml @@ -69,18 +69,15 @@ jobs: - name: Dump environment run: | env - - - name: Build cuda.pathfinder wheel - uses: pypa/cibuildwheel@5f22145df44122af0f5a201f93cf0207171beca7 # v3.0.0 - env: - CIBW_BUILD: ${{ env.CIBW_BUILD }} - CIBW_ARCHS_LINUX: "native" - CIBW_BUILD_VERBOSITY: 1 - CIBW_BEFORE_BUILD_WINDOWS: "pip install delvewheel" - CIBW_REPAIR_WHEEL_COMMAND_WINDOWS: "delvewheel repair --namespace-pkg cuda -w {dest_dir} {wheel}" - with: - package-dir: ./cuda_pathfinder/ - output-dir: ${{ env.CUDA_PATHFINDER_ARTIFACTS_DIR }} + + # We only need/want a single pure python wheel, pick linux-64 index 0. + - name: Build and check cuda.pathfinder wheel + if: ${{ strategy.job-index == 0 && inputs.host-platform == 'linux-64' }} + run: | + pushd cuda_pathfinder + pip wheel -v --no-deps . + twine check *.whl + popd - name: List the cuda.pathfinder artifacts directory run: | From 346e8b9d608e155f3ce067cd5a05b4df9b1bbcaf Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 2 Jul 2025 11:44:04 -0700 Subject: [PATCH 29/78] twine cleanup --- .github/workflows/build-wheel.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/build-wheel.yml b/.github/workflows/build-wheel.yml index af858a201..2f5e9249a 100644 --- a/.github/workflows/build-wheel.yml +++ b/.github/workflows/build-wheel.yml @@ -76,7 +76,6 @@ jobs: run: | pushd cuda_pathfinder pip wheel -v --no-deps . - twine check *.whl popd - name: List the cuda.pathfinder artifacts directory @@ -125,7 +124,6 @@ jobs: - name: Check cuda.core wheel run: | - pip install twine twine check ${{ env.CUDA_CORE_ARTIFACTS_DIR }}/*.whl - name: Upload cuda.core build artifacts From 9207966d6c23e5ba6bbc8cf17bd6ff2e66f2bc57 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 2 Jul 2025 12:10:15 -0700 Subject: [PATCH 30/78] Hard-wire cuda-pathfinder artifact name and path for simplicity, similar to the approach used for cuda-python. --- .github/workflows/build-wheel.yml | 16 ++++++++++------ .github/workflows/test-wheel-linux.yml | 4 ++-- ci/tools/env-vars | 4 ---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build-wheel.yml b/.github/workflows/build-wheel.yml index 2f5e9249a..265682c8d 100644 --- a/.github/workflows/build-wheel.yml +++ b/.github/workflows/build-wheel.yml @@ -70,6 +70,10 @@ jobs: run: | env + - name: Install twine + run: | + pip install twine + # We only need/want a single pure python wheel, pick linux-64 index 0. - name: Build and check cuda.pathfinder wheel if: ${{ strategy.job-index == 0 && inputs.host-platform == 'linux-64' }} @@ -85,19 +89,19 @@ jobs: else export CHOWN="sudo chown" fi - $CHOWN -R $(whoami) ${{ env.CUDA_PATHFINDER_ARTIFACTS_DIR }} - ls -lahR ${{ env.CUDA_PATHFINDER_ARTIFACTS_DIR }} + $CHOWN -R $(whoami) cuda_pathfinder/*.whl + ls -lahR cuda_pathfinder - name: Check cuda.pathfinder wheel run: | - pip install twine - twine check ${{ env.CUDA_PATHFINDER_ARTIFACTS_DIR }}/*.whl + twine check cuda_pathfinder/*.whl - name: Upload cuda.pathfinder build artifacts + if: ${{ strategy.job-index == 0 && inputs.host-platform == 'linux-64' }} uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: - name: ${{ env.CUDA_PATHFINDER_ARTIFACT_NAME }} - path: ${{ env.CUDA_PATHFINDER_ARTIFACTS_DIR }}/*.whl + name: cuda-pathfinder-wheel + path: cuda_pathfinder/*.whl if-no-files-found: error - name: Build cuda.core wheel diff --git a/.github/workflows/test-wheel-linux.yml b/.github/workflows/test-wheel-linux.yml index 481059d19..9b16b7a9a 100644 --- a/.github/workflows/test-wheel-linux.yml +++ b/.github/workflows/test-wheel-linux.yml @@ -167,8 +167,8 @@ jobs: if: ${{ env.SKIP_CUDA_BINDINGS_TEST == '0'}} uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: - name: ${{ env.CUDA_PATHFINDER_ARTIFACT_NAME }} - path: ${{ env.CUDA_PATHFINDER_ARTIFACTS_DIR }} + name: cuda-pathfinder-wheel + path: . - name: Download cuda-python build artifacts if: ${{ env.SKIP_CUDA_BINDINGS_TEST == '0'}} diff --git a/ci/tools/env-vars b/ci/tools/env-vars index 94a7ed019..7211dc08f 100755 --- a/ci/tools/env-vars +++ b/ci/tools/env-vars @@ -28,10 +28,6 @@ elif [[ "${HOST_PLATFORM}" == win* ]]; then fi echo "${TOOLS_PATH}" >> $GITHUB_PATH -CUDA_PATHFINDER_ARTIFACT_BASENAME="cuda-pathfinder-noarch" -echo "CUDA_PATHFINDER_ARTIFACT_BASENAME=${CUDA_PATHFINDER_ARTIFACT_BASENAME}" >> $GITHUB_ENV -echo "CUDA_PATHFINDER_ARTIFACT_NAME=${CUDA_PATHFINDER_ARTIFACT_BASENAME}-${SHA}" >> $GITHUB_ENV -echo "CUDA_PATHFINDER_ARTIFACTS_DIR=$(realpath "${REPO_DIR}/cuda_pathfinder/dist")" >> $GITHUB_ENV echo "CUDA_BINDINGS_PARALLEL_LEVEL=$(nproc)" >> $GITHUB_ENV CUDA_CORE_ARTIFACT_BASENAME="cuda-core-python${PYTHON_VERSION_FORMATTED}-${HOST_PLATFORM}" echo "CUDA_CORE_ARTIFACT_BASENAME=${CUDA_CORE_ARTIFACT_BASENAME}" >> $GITHUB_ENV From 3682f7db6675da7175cb694c11f968a15236d3ad Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 2 Jul 2025 12:14:39 -0700 Subject: [PATCH 31/78] Change to __version__ = "1.0.0" --- cuda_pathfinder/cuda/pathfinder/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cuda_pathfinder/cuda/pathfinder/_version.py b/cuda_pathfinder/cuda/pathfinder/_version.py index d5829b003..23e58fddb 100644 --- a/cuda_pathfinder/cuda/pathfinder/_version.py +++ b/cuda_pathfinder/cuda/pathfinder/_version.py @@ -1,4 +1,4 @@ # SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 -__version__ = "0.1.0" +__version__ = "1.0.0" From 7742c5c75d46ab4ee100380db7c68f1692aa682f Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 2 Jul 2025 12:22:25 -0700 Subject: [PATCH 32/78] Import __version__ in cuda/pathfinder/__init__.py --- cuda_pathfinder/cuda/pathfinder/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cuda_pathfinder/cuda/pathfinder/__init__.py b/cuda_pathfinder/cuda/pathfinder/__init__.py index 9997e252c..f8bb288b3 100644 --- a/cuda_pathfinder/cuda/pathfinder/__init__.py +++ b/cuda_pathfinder/cuda/pathfinder/__init__.py @@ -4,5 +4,6 @@ from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_lib import load_nvidia_dynamic_lib from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import SUPPORTED_LIBNAMES as SUPPORTED_NVIDIA_LIBNAMES +from cuda.pathfinder._version import __version__ -__all__ = ["LoadedDL", "load_nvidia_dynamic_lib", "SUPPORTED_NVIDIA_LIBNAMES"] +__all__ = ["LoadedDL", "load_nvidia_dynamic_lib", "SUPPORTED_NVIDIA_LIBNAMES", "__version__"] From 92c844180c2b4189ed51a69225e1b39c0bf0e1ca Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 2 Jul 2025 16:12:52 -0700 Subject: [PATCH 33/78] Add missing line in step `name: List the cuda.pathfinder artifacts directory` --- .github/workflows/build-wheel.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-wheel.yml b/.github/workflows/build-wheel.yml index 265682c8d..774e43e38 100644 --- a/.github/workflows/build-wheel.yml +++ b/.github/workflows/build-wheel.yml @@ -83,6 +83,7 @@ jobs: popd - name: List the cuda.pathfinder artifacts directory + if: ${{ strategy.job-index == 0 && inputs.host-platform == 'linux-64' }} run: | if [[ "${{ inputs.host-platform }}" == win* ]]; then export CHOWN=chown From a5b71906eaf5f4e1076525bbc365300a6a45d6e0 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 2 Jul 2025 16:22:09 -0700 Subject: [PATCH 34/78] `Install cuda.pathfinder` before ` Build cuda.bindings Cython tests` --- .github/workflows/build-wheel.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-wheel.yml b/.github/workflows/build-wheel.yml index 774e43e38..afe270a1f 100644 --- a/.github/workflows/build-wheel.yml +++ b/.github/workflows/build-wheel.yml @@ -57,7 +57,7 @@ jobs: - name: Set up MSVC if: ${{ startsWith(inputs.host-platform, 'win') }} uses: ilammy/msvc-dev-cmd@v1 # TODO: ask admin to allow pinning commits - + - name: Set environment variables env: CUDA_VER: ${{ inputs.cuda-version }} @@ -232,6 +232,10 @@ jobs: # For caching echo "PY_EXT_SUFFIX=$(python -c "import sysconfig; print(sysconfig.get_config_var('EXT_SUFFIX'))")" >> $GITHUB_ENV + - name: Install cuda.pathfinder (required for next step) + run: | + pip install cuda_pathfinder/*.whl + - name: Build cuda.bindings Cython tests run: | pip install $(ls ${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }}/*.whl)[test] From db0ea567ce7c6d13bd9a7231a27b9a3da810cdc6 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 2 Jul 2025 17:08:42 -0700 Subject: [PATCH 35/78] Add missing line in step `name: Check cuda.pathfinder wheel` --- .github/workflows/build-wheel.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-wheel.yml b/.github/workflows/build-wheel.yml index afe270a1f..0a6090a16 100644 --- a/.github/workflows/build-wheel.yml +++ b/.github/workflows/build-wheel.yml @@ -94,6 +94,7 @@ jobs: ls -lahR cuda_pathfinder - name: Check cuda.pathfinder wheel + if: ${{ strategy.job-index == 0 && inputs.host-platform == 'linux-64' }} run: | twine check cuda_pathfinder/*.whl From 9a9f1d756028886c170b82968b82a66e4f870363 Mon Sep 17 00:00:00 2001 From: Leo Fang Date: Wed, 2 Jul 2025 20:50:22 -0400 Subject: [PATCH 36/78] fix build workflow --- .github/workflows/build-wheel.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-wheel.yml b/.github/workflows/build-wheel.yml index 0a6090a16..59c5a683b 100644 --- a/.github/workflows/build-wheel.yml +++ b/.github/workflows/build-wheel.yml @@ -74,16 +74,14 @@ jobs: run: | pip install twine - # We only need/want a single pure python wheel, pick linux-64 index 0. + # To keep the build workflow simple, all matrix jobs will build a wheel for later use within this workflow. - name: Build and check cuda.pathfinder wheel - if: ${{ strategy.job-index == 0 && inputs.host-platform == 'linux-64' }} run: | pushd cuda_pathfinder pip wheel -v --no-deps . popd - name: List the cuda.pathfinder artifacts directory - if: ${{ strategy.job-index == 0 && inputs.host-platform == 'linux-64' }} run: | if [[ "${{ inputs.host-platform }}" == win* ]]; then export CHOWN=chown @@ -93,6 +91,8 @@ jobs: $CHOWN -R $(whoami) cuda_pathfinder/*.whl ls -lahR cuda_pathfinder + # We only need/want a single pure python wheel, pick linux-64 index 0. + # This is what we will use for testing & releasing. - name: Check cuda.pathfinder wheel if: ${{ strategy.job-index == 0 && inputs.host-platform == 'linux-64' }} run: | From 989db081c6eb437766a34cc6810cc09fa0e3d8f6 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Thu, 3 Jul 2025 09:47:53 -0700 Subject: [PATCH 37/78] Remove `__all__` in cuda/pathfinder/__init__.py --- cuda_pathfinder/cuda/pathfinder/__init__.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cuda_pathfinder/cuda/pathfinder/__init__.py b/cuda_pathfinder/cuda/pathfinder/__init__.py index f8bb288b3..1009b8b36 100644 --- a/cuda_pathfinder/cuda/pathfinder/__init__.py +++ b/cuda_pathfinder/cuda/pathfinder/__init__.py @@ -1,9 +1,9 @@ # SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 -from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL -from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_lib import load_nvidia_dynamic_lib -from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import SUPPORTED_LIBNAMES as SUPPORTED_NVIDIA_LIBNAMES -from cuda.pathfinder._version import __version__ - -__all__ = ["LoadedDL", "load_nvidia_dynamic_lib", "SUPPORTED_NVIDIA_LIBNAMES", "__version__"] +from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL as LoadedDL +from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_lib import load_nvidia_dynamic_lib as load_nvidia_dynamic_lib +from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import ( + SUPPORTED_LIBNAMES as SUPPORTED_NVIDIA_LIBNAMES, # noqa: F401 +) +from cuda.pathfinder._version import __version__ as __version__ From 222df6c05f636badee7562b0a5f21afc8427266c Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Thu, 3 Jul 2025 10:18:04 -0700 Subject: [PATCH 38/78] Fix `Check if the script was called with exactly 1 argument` implementation in ci/tools/run-tests --- ci/tools/run-tests | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ci/tools/run-tests b/ci/tools/run-tests index 3a35b6ad2..3fdb8fdf7 100755 --- a/ci/tools/run-tests +++ b/ci/tools/run-tests @@ -9,9 +9,12 @@ set -euo pipefail # Check if the script was called with exactly 1 argument -if [[ ${#} -ne 1 && ( "${1}" == "bindings" || "${1}" == "core" ) ]]; then - echo "Error: This script requires exactly 1 argument (what is tested). You provided ${#}" - echo "Usage: ${0} test_module[bindings or core]" +if [[ ${#} -ne 1 ]]; then + echo "Error: This script requires exactly 1 argument. You provided ${#}" + exit 1 +fi +if [[ "${1}" != "bindings" && "${1}" != "core" ]]; then + echo "Error: Invalid test module '${1}'. Must be 'bindings', or 'core'" exit 1 fi From 0b8af00b2423b6d8527c3b0a152b934b10ea0f63 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Thu, 3 Jul 2025 10:29:59 -0700 Subject: [PATCH 39/78] Add pathfinder install & test into ci/tools/run-tests --- ci/tools/run-tests | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/ci/tools/run-tests b/ci/tools/run-tests index 3fdb8fdf7..8e9eb761e 100755 --- a/ci/tools/run-tests +++ b/ci/tools/run-tests @@ -13,13 +13,27 @@ if [[ ${#} -ne 1 ]]; then echo "Error: This script requires exactly 1 argument. You provided ${#}" exit 1 fi -if [[ "${1}" != "bindings" && "${1}" != "core" ]]; then - echo "Error: Invalid test module '${1}'. Must be 'bindings', or 'core'" +if [[ "${1}" != "bindings" && "${1}" != "core" && "${1}" != "pathfinder" ]]; then + echo "Error: Invalid test module '${1}'. Must be 'bindings', 'core', or 'pathfinder'" exit 1 fi test_module=${1} +# Unconditionally install pathfinder wheel +# (it is a direct dependency of bindings, and a transitive dependency of core) +pushd ./cuda_pathfinder +echo "Installing pathfinder wheel" +pwd +ls +pip install $(ls *.whl)[test] +if [[ "${test_module}" == "pathfinder" ]]; then + echo "Running pathfinder tests" + pwd + pytest -ra -s -v tests/ +fi +popd + if [[ "${test_module}" == "bindings" ]]; then pushd "${CUDA_BINDINGS_ARTIFACTS_DIR}" echo "Installing bindings wheel" From f902dc9082a9fc4f5b1a2e2b30c25301120ee61d Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Thu, 3 Jul 2025 10:40:39 -0700 Subject: [PATCH 40/78] Add Download cuda-pathfinder, Run cuda.pathfinder tests in test-wheel-windows.yml --- .github/workflows/test-wheel-linux.yml | 2 -- .github/workflows/test-wheel-windows.yml | 15 ++++++++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test-wheel-linux.yml b/.github/workflows/test-wheel-linux.yml index 9b16b7a9a..f324488bd 100644 --- a/.github/workflows/test-wheel-linux.yml +++ b/.github/workflows/test-wheel-linux.yml @@ -164,7 +164,6 @@ jobs: run: ./ci/tools/env-vars test - name: Download cuda-pathfinder build artifacts - if: ${{ env.SKIP_CUDA_BINDINGS_TEST == '0'}} uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: name: cuda-pathfinder-wheel @@ -294,7 +293,6 @@ jobs: run: setup-sanitizer - name: Run cuda.pathfinder tests - if: ${{ env.SKIP_CUDA_PATHFINDER_TEST == '0' }} env: CUDA_VER: ${{ matrix.CUDA_VER }} LOCAL_CTK: ${{ matrix.LOCAL_CTK }} diff --git a/.github/workflows/test-wheel-windows.yml b/.github/workflows/test-wheel-windows.yml index 86769d4a0..633d30e2a 100644 --- a/.github/workflows/test-wheel-windows.yml +++ b/.github/workflows/test-wheel-windows.yml @@ -121,6 +121,12 @@ jobs: shell: bash --noprofile --norc -xeuo pipefail {0} run: ./ci/tools/env-vars test + - name: Download cuda-pathfinder build artifacts + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + name: cuda-pathfinder-wheel + path: . + - name: Download cuda-python build artifacts if: ${{ env.SKIP_CUDA_BINDINGS_TEST == '0'}} uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 @@ -184,7 +190,7 @@ jobs: New-Item -Path "${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }}" -ItemType Directory -Force Move-Item -Path "$OLD_BASENAME/*.whl" -Destination "${{ env.CUDA_BINDINGS_ARTIFACTS_DIR }}" Remove-Item -Path $OLD_BASENAME -Force - + gh run download $LATEST_PRIOR_RUN_ID -p cuda-python-wheel -R NVIDIA/cuda-python Get-ChildItem -Path cuda-python-wheel Move-Item -Path "cuda-python-wheel/*.whl" -Destination . @@ -250,6 +256,13 @@ jobs: host-platform: ${{ inputs.host-platform }} cuda-version: ${{ matrix.CUDA_VER }} + - name: Run cuda.pathfinder tests + env: + CUDA_VER: ${{ matrix.CUDA_VER }} + LOCAL_CTK: ${{ matrix.LOCAL_CTK }} + shell: bash --noprofile --norc -xeuo pipefail {0} + run: run-tests pathfinder + - name: Run cuda.bindings tests if: ${{ env.SKIP_CUDA_BINDINGS_TEST == '0' }} env: From 481f8de7d2bd6d27f063233683a50c60e6ae123d Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Thu, 3 Jul 2025 11:56:57 -0700 Subject: [PATCH 41/78] Download cuda-pathfinder-wheel into `./cuda_pathfinder` (not `.`) --- .github/workflows/test-wheel-linux.yml | 2 +- .github/workflows/test-wheel-windows.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-wheel-linux.yml b/.github/workflows/test-wheel-linux.yml index f324488bd..29ac243df 100644 --- a/.github/workflows/test-wheel-linux.yml +++ b/.github/workflows/test-wheel-linux.yml @@ -167,7 +167,7 @@ jobs: uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: name: cuda-pathfinder-wheel - path: . + path: ./cuda_pathfinder - name: Download cuda-python build artifacts if: ${{ env.SKIP_CUDA_BINDINGS_TEST == '0'}} diff --git a/.github/workflows/test-wheel-windows.yml b/.github/workflows/test-wheel-windows.yml index 633d30e2a..626c46223 100644 --- a/.github/workflows/test-wheel-windows.yml +++ b/.github/workflows/test-wheel-windows.yml @@ -125,7 +125,7 @@ jobs: uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: name: cuda-pathfinder-wheel - path: . + path: ./cuda_pathfinder - name: Download cuda-python build artifacts if: ${{ env.SKIP_CUDA_BINDINGS_TEST == '0'}} From fd18e1e2a7dbb4d102c123c300d476405425aaf2 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Thu, 3 Jul 2025 13:15:44 -0700 Subject: [PATCH 42/78] Run cuda.pathfinder tests only after cuda.bindings tests, so that all wheels are installed already. --- .github/workflows/test-wheel-linux.yml | 17 +++++++++-------- .github/workflows/test-wheel-windows.yml | 23 ++++++++++------------- ci/tools/run-tests | 9 +++++---- 3 files changed, 24 insertions(+), 25 deletions(-) diff --git a/.github/workflows/test-wheel-linux.yml b/.github/workflows/test-wheel-linux.yml index 29ac243df..d3640be49 100644 --- a/.github/workflows/test-wheel-linux.yml +++ b/.github/workflows/test-wheel-linux.yml @@ -292,12 +292,6 @@ jobs: - name: Set up compute-sanitizer run: setup-sanitizer - - name: Run cuda.pathfinder tests - env: - CUDA_VER: ${{ matrix.CUDA_VER }} - LOCAL_CTK: ${{ matrix.LOCAL_CTK }} - run: run-tests pathfinder - - name: Run cuda.bindings tests if: ${{ env.SKIP_CUDA_BINDINGS_TEST == '0' }} env: @@ -311,10 +305,17 @@ jobs: LOCAL_CTK: ${{ matrix.LOCAL_CTK }} run: run-tests core + # Run only after cuda.bindings tests, so that all wheels are installed already. + - name: Run cuda.pathfinder tests + env: + CUDA_VER: ${{ matrix.CUDA_VER }} + LOCAL_CTK: ${{ matrix.LOCAL_CTK }} + run: run-tests pathfinder + - name: Ensure cuda-python installable run: | if [[ "${{ matrix.LOCAL_CTK }}" == 1 ]]; then - pip install cuda_pathfinder*.whl cuda_python*.whl + pip install cuda_python*.whl else - pip install $(ls cuda_pathfinder*.whl) $(ls cuda_python*.whl)[all] + pip install $(ls cuda_python*.whl)[all] fi diff --git a/.github/workflows/test-wheel-windows.yml b/.github/workflows/test-wheel-windows.yml index 626c46223..fdd7c9af7 100644 --- a/.github/workflows/test-wheel-windows.yml +++ b/.github/workflows/test-wheel-windows.yml @@ -256,13 +256,6 @@ jobs: host-platform: ${{ inputs.host-platform }} cuda-version: ${{ matrix.CUDA_VER }} - - name: Run cuda.pathfinder tests - env: - CUDA_VER: ${{ matrix.CUDA_VER }} - LOCAL_CTK: ${{ matrix.LOCAL_CTK }} - shell: bash --noprofile --norc -xeuo pipefail {0} - run: run-tests pathfinder - - name: Run cuda.bindings tests if: ${{ env.SKIP_CUDA_BINDINGS_TEST == '0' }} env: @@ -278,14 +271,18 @@ jobs: shell: bash --noprofile --norc -xeuo pipefail {0} run: run-tests core + # Run only after cuda.bindings tests, so that all wheels are installed already. + - name: Run cuda.pathfinder tests + env: + CUDA_VER: ${{ matrix.CUDA_VER }} + LOCAL_CTK: ${{ matrix.LOCAL_CTK }} + shell: bash --noprofile --norc -xeuo pipefail {0} + run: run-tests pathfinder + - name: Ensure cuda-python installable run: | if ('${{ matrix.LOCAL_CTK }}' -eq '1') { - $pathfinder = (Get-ChildItem -Filter cuda_pathfinder*.whl).FullName - $umbrella = (Get-ChildItem -Filter cuda_python*.whl).FullName - pip install $pathfinder $umbrella + pip install (Get-ChildItem -Filter cuda_python*.whl).FullName } else { - $pathfinder = (Get-ChildItem -Filter cuda_pathfinder*.whl).FullName - $umbrella = (Get-ChildItem -Filter cuda_python*.whl).FullName - pip install "$pathfinder" "$umbrella[all]" + pip install "$((Get-ChildItem -Filter cuda_python*.whl).FullName)[all]" } diff --git a/ci/tools/run-tests b/ci/tools/run-tests index 8e9eb761e..16df1a184 100755 --- a/ci/tools/run-tests +++ b/ci/tools/run-tests @@ -27,14 +27,15 @@ echo "Installing pathfinder wheel" pwd ls pip install $(ls *.whl)[test] +popd + if [[ "${test_module}" == "pathfinder" ]]; then + pushd ./cuda_pathfinder echo "Running pathfinder tests" pwd pytest -ra -s -v tests/ -fi -popd - -if [[ "${test_module}" == "bindings" ]]; then + popd +elif [[ "${test_module}" == "bindings" ]]; then pushd "${CUDA_BINDINGS_ARTIFACTS_DIR}" echo "Installing bindings wheel" pwd From 796bd462beb9a094de907c8b04ffec45b461b990 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Thu, 3 Jul 2025 14:24:17 -0700 Subject: [PATCH 43/78] =?UTF-8?q?Drive-by=20fix:=20test=5Ffind=5For=5Fload?= =?UTF-8?q?=20=E2=86=92=20test=5Fload?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py b/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py index 90611817a..5ea924fb7 100644 --- a/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py @@ -15,11 +15,11 @@ ALL_LIBNAMES_WINDOWS = SUPPORTED_NVIDIA_LIBNAMES + supported_nvidia_libs.PARTIALLY_SUPPORTED_LIBNAMES_WINDOWS if os.environ.get("CUDA_PATHFINDER_TEST_ALL_LIBNAMES", False): if sys.platform == "win32": - TEST_FIND_OR_LOAD_LIBNAMES = ALL_LIBNAMES_WINDOWS + TEST_LOAD_LIBNAMES = ALL_LIBNAMES_WINDOWS else: - TEST_FIND_OR_LOAD_LIBNAMES = ALL_LIBNAMES_LINUX + TEST_LOAD_LIBNAMES = ALL_LIBNAMES_LINUX else: - TEST_FIND_OR_LOAD_LIBNAMES = SUPPORTED_NVIDIA_LIBNAMES + TEST_LOAD_LIBNAMES = SUPPORTED_NVIDIA_LIBNAMES def test_all_libnames_linux_sonames_consistency(): @@ -80,8 +80,8 @@ def child_process_func(libname): print(f"{loaded_dl_fresh.abs_path!r}") -@pytest.mark.parametrize("libname", TEST_FIND_OR_LOAD_LIBNAMES) -def test_find_or_load_nvidia_dynamic_lib(info_summary_append, libname): +@pytest.mark.parametrize("libname", TEST_LOAD_LIBNAMES) +def test_load_nvidia_dynamic_lib(info_summary_append, libname): # We intentionally run each dynamic library operation in a child process # to ensure isolation of global dynamic linking state (e.g., dlopen handles). # Without child processes, loading/unloading libraries during testing could From 06763af099886fdad2ab1ea28c123f94bee72083 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Thu, 3 Jul 2025 15:25:40 -0700 Subject: [PATCH 44/78] Introduce CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS environment variable. --- .../tests/test_load_nvidia_dynamic_lib.py | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py b/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py index 5ea924fb7..bb08d3719 100644 --- a/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py @@ -13,13 +13,13 @@ ALL_LIBNAMES = SUPPORTED_NVIDIA_LIBNAMES + supported_nvidia_libs.PARTIALLY_SUPPORTED_LIBNAMES_ALL ALL_LIBNAMES_LINUX = SUPPORTED_NVIDIA_LIBNAMES + supported_nvidia_libs.PARTIALLY_SUPPORTED_LIBNAMES_LINUX ALL_LIBNAMES_WINDOWS = SUPPORTED_NVIDIA_LIBNAMES + supported_nvidia_libs.PARTIALLY_SUPPORTED_LIBNAMES_WINDOWS -if os.environ.get("CUDA_PATHFINDER_TEST_ALL_LIBNAMES", False): - if sys.platform == "win32": - TEST_LOAD_LIBNAMES = ALL_LIBNAMES_WINDOWS - else: - TEST_LOAD_LIBNAMES = ALL_LIBNAMES_LINUX +if sys.platform == "win32": + TEST_LOAD_LIBNAMES = ALL_LIBNAMES_WINDOWS else: - TEST_LOAD_LIBNAMES = SUPPORTED_NVIDIA_LIBNAMES + TEST_LOAD_LIBNAMES = ALL_LIBNAMES_LINUX + +STRICTNESS = os.environ.get("CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS", "supported_must_work") +assert STRICTNESS in ("see_what_works", "supported_must_work", "all_must_work") def test_all_libnames_linux_sonames_consistency(): @@ -90,4 +90,16 @@ def test_load_nvidia_dynamic_lib(info_summary_append, libname): if result.returncode == 0: info_summary_append(f"abs_path={result.stdout.rstrip()}") else: - raise RuntimeError(build_child_process_failed_for_libname_message(libname, result)) + if STRICTNESS == "all_must_work": + strict = True + elif STRICTNESS == "supported_must_work": + strict = libname in SUPPORTED_NVIDIA_LIBNAMES + else: # "see_what_works" + strict = False + if ( + strict + or "loaded_dl_fresh = load_nvidia_dynamic_lib(libname)" not in result.stderr + or "RuntimeError: Failure finding " not in result.stderr + ): + raise RuntimeError(build_child_process_failed_for_libname_message(libname, result)) + info_summary_append(f"Not found: {libname=!r}") From b2135cf554824926f357af28fc8d0e6df9302974 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Thu, 3 Jul 2025 15:33:25 -0700 Subject: [PATCH 45/78] CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS=supported_must_work|see_what_works (/ci/tools/run-tests). --- ci/tools/run-tests | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ci/tools/run-tests b/ci/tools/run-tests index 16df1a184..0058d1dc6 100755 --- a/ci/tools/run-tests +++ b/ci/tools/run-tests @@ -33,6 +33,11 @@ if [[ "${test_module}" == "pathfinder" ]]; then pushd ./cuda_pathfinder echo "Running pathfinder tests" pwd + if [[ "${SKIP_CUDA_BINDINGS_TEST}" == 0 ]]; then + export CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS=supported_must_work + else + export CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS=see_what_works + fi pytest -ra -s -v tests/ popd elif [[ "${test_module}" == "bindings" ]]; then From bf4814261dfef4557d69527840ea8dc1e92de6b1 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Thu, 3 Jul 2025 16:08:25 -0700 Subject: [PATCH 46/78] Add cuda-pathfinder in .github/workflows/build-docs.yml --- .github/workflows/build-docs.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index f7852155f..474179f81 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -115,6 +115,17 @@ jobs: pwd ls -lahR . + - name: Download cuda-pathfinder build artifacts + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + name: cuda-pathfinder-wheel + path: ./cuda_pathfinder + + - name: Display structure of downloaded cuda-pathfinder artifacts + run: | + pwd + ls -lahR cuda_pathfinder + - name: Download cuda.bindings build artifacts if: ${{ !inputs.is-release }} uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 @@ -161,6 +172,10 @@ jobs: - name: Install all packages run: | + pushd cuda_pathfinder + pip install *.whl + popd + pushd "${CUDA_BINDINGS_ARTIFACTS_DIR}" pip install *.whl popd From 135a37d263802a9053d6539508830a5921d28096 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sat, 5 Jul 2025 14:09:52 -0700 Subject: [PATCH 47/78] Remove 32-bit DLLs from SUPPORTED_WINDOWS_DLLS --- .../cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py | 4 ---- toolshed/build_path_finder_dlls.py | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py index 7fde02f7b..b59d2ec30 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py @@ -250,9 +250,6 @@ "cublasLt64_12.dll", ), "cudart": ( - "cudart32_110.dll", - "cudart32_65.dll", - "cudart32_90.dll", "cudart64_101.dll", "cudart64_110.dll", "cudart64_12.dll", @@ -340,7 +337,6 @@ "nvrtc64_120_0.dll", ), "nvvm": ( - "nvvm32.dll", "nvvm64.dll", "nvvm64_33_0.dll", "nvvm64_40_0.dll", diff --git a/toolshed/build_path_finder_dlls.py b/toolshed/build_path_finder_dlls.py index be2db0d1f..a44ddceb7 100755 --- a/toolshed/build_path_finder_dlls.py +++ b/toolshed/build_path_finder_dlls.py @@ -9,6 +9,7 @@ # The output of this script # requires obvious manual edits to remove duplicates and unwanted dlls. +# TODO: filter out cudart32_*.dll, nvvm32.dll import sys From 48c6d630ece697483bfbdebaba646817242b9c3b Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sat, 5 Jul 2025 14:59:40 -0700 Subject: [PATCH 48/78] Add guard: RuntimeError: cuda.pathfinder.load_nvidia_dynamic_lib() requires 64-bit Python. Currently running: 32-bit Python --- .../pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py index b6dc484e1..d05779d06 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py @@ -2,6 +2,8 @@ # SPDX-License-Identifier: Apache-2.0 import functools +import struct +import sys from cuda.pathfinder._dynamic_libs.find_nvidia_dynamic_lib import _find_nvidia_dynamic_lib from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL, load_dependencies @@ -58,4 +60,11 @@ def load_nvidia_dynamic_lib(libname: str) -> LoadedDL: Raises: RuntimeError: If the library cannot be found or loaded """ + pointer_size_bits = struct.calcsize("P") * 8 + if pointer_size_bits != 64: + raise RuntimeError( + f"cuda.pathfinder.load_nvidia_dynamic_lib() requires 64-bit Python." + f" Currently running: {pointer_size_bits}-bit Python" + f" {sys.version_info.major}.{sys.version_info.minor}" + ) return _load_lib_no_cache(libname) From 7ab201a0d60804c43e6b944ea6264584075dcc83 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sat, 5 Jul 2025 15:10:10 -0700 Subject: [PATCH 49/78] is_suppressed_dll_file(): return path_basename.startswith(("cudart32_", "nvvm32")) --- .../cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py index b59d2ec30..d544ac963 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py @@ -358,7 +358,7 @@ def is_suppressed_dll_file(path_basename: str) -> bool: # nvrtc64_120_0.alt.dll # nvrtc64_120_0.dll return path_basename.endswith(".alt.dll") or "-builtins" in path_basename - return False + return path_basename.startswith(("cudart32_", "nvvm32")) # Based on nm output for Linux x86_64 /usr/local/cuda (12.8.1) From 9f3e9a4109088ed1811ce0c3fa81d698187865c3 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sat, 5 Jul 2025 15:35:06 -0700 Subject: [PATCH 50/78] Add nvidia_wheels_cu12 to [project.optional-dependencies] in cuda_pathfinder/pyproject.toml --- cuda_pathfinder/pyproject.toml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/cuda_pathfinder/pyproject.toml b/cuda_pathfinder/pyproject.toml index a39932a13..5c705cad4 100644 --- a/cuda_pathfinder/pyproject.toml +++ b/cuda_pathfinder/pyproject.toml @@ -16,6 +16,21 @@ dependencies = [ test = [ "pytest>=6.2.4", ] +nvidia_wheels_cu12 = [ + "nvidia-cublas-cu12", + "nvidia-cuda-nvcc-cu12", + "nvidia-cuda-nvrtc-cu12", + "nvidia-cuda-runtime-cu12", + "nvidia-cufft-cu12", + "nvidia-cufile-cu12; sys_platform != 'win32'", + "nvidia-curand-cu12", + "nvidia-cusolver-cu12", + "nvidia-cusparse-cu12", + "nvidia-npp-cu12", + "nvidia-nvfatbin-cu12", + "nvidia-nvjitlink-cu12", + "nvidia-nvjpeg-cu12", +] [project.urls] Repository = "https://github.com/NVIDIA/cuda-python" From 00c8b6ac4ae5674cbb5c7db947e95104ac519250 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sat, 5 Jul 2025 16:09:10 -0700 Subject: [PATCH 51/78] Install cuda.pathfinder nvidia_wheels_cu12 and run-tests pathfinder again with all_must_work --- .github/workflows/test-wheel-linux.yml | 17 ++++++++++++++--- .github/workflows/test-wheel-windows.yml | 18 +++++++++++++++--- ci/tools/run-tests | 10 ++++++---- 3 files changed, 35 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test-wheel-linux.yml b/.github/workflows/test-wheel-linux.yml index d3640be49..b76f1306b 100644 --- a/.github/workflows/test-wheel-linux.yml +++ b/.github/workflows/test-wheel-linux.yml @@ -307,9 +307,6 @@ jobs: # Run only after cuda.bindings tests, so that all wheels are installed already. - name: Run cuda.pathfinder tests - env: - CUDA_VER: ${{ matrix.CUDA_VER }} - LOCAL_CTK: ${{ matrix.LOCAL_CTK }} run: run-tests pathfinder - name: Ensure cuda-python installable @@ -319,3 +316,17 @@ jobs: else pip install $(ls cuda_python*.whl)[all] fi + + - name: Install cuda.pathfinder nvidia_wheels_cu12 + if: ${{ env.SKIP_CUDA_BINDINGS_TEST == '0'}} + run: | + pushd cuda_pathfinder + pip install -v .[nvidia_wheels_cu12] + pip freeze + popd + + - name: Run cuda.pathfinder tests with all_must_work + if: ${{ env.SKIP_CUDA_BINDINGS_TEST == '0'}} + env: + CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS: all_must_work + run: run-tests pathfinder diff --git a/.github/workflows/test-wheel-windows.yml b/.github/workflows/test-wheel-windows.yml index fdd7c9af7..8baa4e7f9 100644 --- a/.github/workflows/test-wheel-windows.yml +++ b/.github/workflows/test-wheel-windows.yml @@ -273,9 +273,6 @@ jobs: # Run only after cuda.bindings tests, so that all wheels are installed already. - name: Run cuda.pathfinder tests - env: - CUDA_VER: ${{ matrix.CUDA_VER }} - LOCAL_CTK: ${{ matrix.LOCAL_CTK }} shell: bash --noprofile --norc -xeuo pipefail {0} run: run-tests pathfinder @@ -286,3 +283,18 @@ jobs: } else { pip install "$((Get-ChildItem -Filter cuda_python*.whl).FullName)[all]" } + + - name: Install cuda.pathfinder nvidia_wheels_cu12 + if: ${{ env.SKIP_CUDA_BINDINGS_TEST == '0' }} + shell: bash --noprofile --norc -xeuo pipefail {0} + run: | + pushd cuda_pathfinder + pip install -v .[nvidia_wheels_cu12] + pip freeze + popd + + - name: Run cuda.pathfinder tests with all_must_work + if: ${{ env.SKIP_CUDA_BINDINGS_TEST == '0' }} + env: + CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS: all_must_work + run: run-tests pathfinder diff --git a/ci/tools/run-tests b/ci/tools/run-tests index 0058d1dc6..3384191f2 100755 --- a/ci/tools/run-tests +++ b/ci/tools/run-tests @@ -33,10 +33,12 @@ if [[ "${test_module}" == "pathfinder" ]]; then pushd ./cuda_pathfinder echo "Running pathfinder tests" pwd - if [[ "${SKIP_CUDA_BINDINGS_TEST}" == 0 ]]; then - export CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS=supported_must_work - else - export CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS=see_what_works + if [ -z "${CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS}" ]; then + if [ "${SKIP_CUDA_BINDINGS_TEST}" == 0 ]; then + export CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS=supported_must_work + else + export CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS=see_what_works + fi fi pytest -ra -s -v tests/ popd From 034286a1bf03df743f0cb4aae386df051e6c32a3 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sat, 5 Jul 2025 20:17:21 -0700 Subject: [PATCH 52/78] ci/tools/run-tests: use bash `-v` instead of `-z` to test if CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS is defined (to resolve `unbound variable` error). --- ci/tools/run-tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/tools/run-tests b/ci/tools/run-tests index 3384191f2..98bfa05f5 100755 --- a/ci/tools/run-tests +++ b/ci/tools/run-tests @@ -33,7 +33,7 @@ if [[ "${test_module}" == "pathfinder" ]]; then pushd ./cuda_pathfinder echo "Running pathfinder tests" pwd - if [ -z "${CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS}" ]; then + if [ ! -v CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS ]; then if [ "${SKIP_CUDA_BINDINGS_TEST}" == 0 ]; then export CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS=supported_must_work else From aaed5f264b7315790855fa2c3e49b2700e8a533e Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sat, 5 Jul 2025 21:09:24 -0700 Subject: [PATCH 53/78] Add missing `shell: bash` line in test-wheel-windows.yml --- .github/workflows/test-wheel-windows.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test-wheel-windows.yml b/.github/workflows/test-wheel-windows.yml index 8baa4e7f9..133baf8f6 100644 --- a/.github/workflows/test-wheel-windows.yml +++ b/.github/workflows/test-wheel-windows.yml @@ -297,4 +297,5 @@ jobs: if: ${{ env.SKIP_CUDA_BINDINGS_TEST == '0' }} env: CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS: all_must_work + shell: bash --noprofile --norc -xeuo pipefail {0} run: run-tests pathfinder From 9d8c70ccdf8f42a9b64e910e5f0d46c2a9e62beb Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sat, 5 Jul 2025 22:10:16 -0700 Subject: [PATCH 54/78] test_load_nvidia_dynamic_lib: increase timeout to 120 seconds for Windows (to see if that resolves the cusolver failures) --- cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py b/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py index bb08d3719..0cc3f1ead 100644 --- a/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py @@ -86,7 +86,8 @@ def test_load_nvidia_dynamic_lib(info_summary_append, libname): # to ensure isolation of global dynamic linking state (e.g., dlopen handles). # Without child processes, loading/unloading libraries during testing could # interfere across test cases and lead to nondeterministic or platform-specific failures. - result = spawned_process_runner.run_in_spawned_child_process(child_process_func, args=(libname,), timeout=30) + timeout = 120 if sys.platform == "win32" else 30 + result = spawned_process_runner.run_in_spawned_child_process(child_process_func, args=(libname,), timeout=timeout) if result.returncode == 0: info_summary_append(f"abs_path={result.stdout.rstrip()}") else: From 8440f902b6d09f70746a935c8603eb6c2967139c Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 6 Jul 2025 10:34:15 -0700 Subject: [PATCH 55/78] Add test_load_nvidia_dynamic_lib::test_runtime_error_on_non_64bit_python --- cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py b/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py index 0cc3f1ead..7e43ce8bc 100644 --- a/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py @@ -3,6 +3,7 @@ import os import sys +from unittest.mock import patch import pytest import spawned_process_runner @@ -50,6 +51,14 @@ def test_all_libnames_expected_lib_symbols_consistency(): assert tuple(sorted(ALL_LIBNAMES)) == tuple(sorted(supported_nvidia_libs.EXPECTED_LIB_SYMBOLS.keys())) +def test_runtime_error_on_non_64bit_python(): + with ( + patch("struct.calcsize", return_value=3), # fake 24-bit pointer + pytest.raises(RuntimeError, match=r"requires 64-bit Python\. Currently running: 24-bit Python"), + ): + load_nvidia_dynamic_lib("not_used") + + def build_child_process_failed_for_libname_message(libname, result): return ( f"Child process failed for {libname=!r} with exit code {result.returncode}\n" From 98ae874eea746893be7a1585721dcafedb932575 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 6 Jul 2025 11:04:22 -0700 Subject: [PATCH 56/78] Add DynamicLibNotFound exception type in load_dl_common.py and simplify test_load_nvidia_dynamic_lib() --- .../pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py | 3 ++- .../cuda/pathfinder/_dynamic_libs/load_dl_common.py | 4 ++++ cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py | 6 +----- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py index 9f07d6345..1389573d3 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py @@ -5,6 +5,7 @@ import glob import os +from cuda.pathfinder._dynamic_libs.load_dl_common import DynamicLibNotFound from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import ( IS_WINDOWS, is_suppressed_dll_file, @@ -160,7 +161,7 @@ def raise_if_abs_path_is_None(self): return self.abs_path err = ", ".join(self.error_messages) att = "\n".join(self.attachments) - raise RuntimeError(f'Failure finding "{self.lib_searched_for}": {err}\n{att}') + raise DynamicLibNotFound(f'Failure finding "{self.lib_searched_for}": {err}\n{att}') @functools.cache diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py index 47891e394..836c62c42 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py @@ -17,6 +17,10 @@ HandleType = int +class DynamicLibNotFound(RuntimeError): + pass + + @dataclass class LoadedDL: handle: HandleType diff --git a/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py b/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py index 7e43ce8bc..457c0e118 100644 --- a/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py @@ -106,10 +106,6 @@ def test_load_nvidia_dynamic_lib(info_summary_append, libname): strict = libname in SUPPORTED_NVIDIA_LIBNAMES else: # "see_what_works" strict = False - if ( - strict - or "loaded_dl_fresh = load_nvidia_dynamic_lib(libname)" not in result.stderr - or "RuntimeError: Failure finding " not in result.stderr - ): + if strict or "DynamicLibNotFound: Failure finding " not in result.stderr: raise RuntimeError(build_child_process_failed_for_libname_message(libname, result)) info_summary_append(f"Not found: {libname=!r}") From 9686c2f047074fa9223ac91fd114a82f35350012 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 6 Jul 2025 11:20:56 -0700 Subject: [PATCH 57/78] Run cuda.pathfinder tests with see_what_works before running any other tests. --- .github/workflows/test-wheel-linux.yml | 9 +++++---- .github/workflows/test-wheel-windows.yml | 11 ++++++----- ci/tools/run-tests | 9 +-------- 3 files changed, 12 insertions(+), 17 deletions(-) diff --git a/.github/workflows/test-wheel-linux.yml b/.github/workflows/test-wheel-linux.yml index b76f1306b..5480a730c 100644 --- a/.github/workflows/test-wheel-linux.yml +++ b/.github/workflows/test-wheel-linux.yml @@ -292,6 +292,11 @@ jobs: - name: Set up compute-sanitizer run: setup-sanitizer + - name: Run cuda.pathfinder tests with see_what_works + env: + CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS: see_what_works + run: run-tests pathfinder + - name: Run cuda.bindings tests if: ${{ env.SKIP_CUDA_BINDINGS_TEST == '0' }} env: @@ -305,10 +310,6 @@ jobs: LOCAL_CTK: ${{ matrix.LOCAL_CTK }} run: run-tests core - # Run only after cuda.bindings tests, so that all wheels are installed already. - - name: Run cuda.pathfinder tests - run: run-tests pathfinder - - name: Ensure cuda-python installable run: | if [[ "${{ matrix.LOCAL_CTK }}" == 1 ]]; then diff --git a/.github/workflows/test-wheel-windows.yml b/.github/workflows/test-wheel-windows.yml index 133baf8f6..86d21ed82 100644 --- a/.github/workflows/test-wheel-windows.yml +++ b/.github/workflows/test-wheel-windows.yml @@ -256,6 +256,12 @@ jobs: host-platform: ${{ inputs.host-platform }} cuda-version: ${{ matrix.CUDA_VER }} + - name: Run cuda.pathfinder tests with see_what_works + env: + CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS: see_what_works + shell: bash --noprofile --norc -xeuo pipefail {0} + run: run-tests pathfinder + - name: Run cuda.bindings tests if: ${{ env.SKIP_CUDA_BINDINGS_TEST == '0' }} env: @@ -271,11 +277,6 @@ jobs: shell: bash --noprofile --norc -xeuo pipefail {0} run: run-tests core - # Run only after cuda.bindings tests, so that all wheels are installed already. - - name: Run cuda.pathfinder tests - shell: bash --noprofile --norc -xeuo pipefail {0} - run: run-tests pathfinder - - name: Ensure cuda-python installable run: | if ('${{ matrix.LOCAL_CTK }}' -eq '1') { diff --git a/ci/tools/run-tests b/ci/tools/run-tests index 98bfa05f5..363f7ccef 100755 --- a/ci/tools/run-tests +++ b/ci/tools/run-tests @@ -31,15 +31,8 @@ popd if [[ "${test_module}" == "pathfinder" ]]; then pushd ./cuda_pathfinder - echo "Running pathfinder tests" + echo "Running pathfinder tests with ${CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS}" pwd - if [ ! -v CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS ]; then - if [ "${SKIP_CUDA_BINDINGS_TEST}" == 0 ]; then - export CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS=supported_must_work - else - export CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS=see_what_works - fi - fi pytest -ra -s -v tests/ popd elif [[ "${test_module}" == "bindings" ]]; then From f3c00060968f0be42662f0814748c5a5a4277ef6 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 6 Jul 2025 11:44:06 -0700 Subject: [PATCH 58/78] Use `if: startsWith(matrix.CUDA_VER, 12.)` to guard pathfinder tests with CUDA 12 wheels. --- .github/workflows/test-wheel-linux.yml | 4 ++-- .github/workflows/test-wheel-windows.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test-wheel-linux.yml b/.github/workflows/test-wheel-linux.yml index 5480a730c..ef6b966e8 100644 --- a/.github/workflows/test-wheel-linux.yml +++ b/.github/workflows/test-wheel-linux.yml @@ -319,7 +319,7 @@ jobs: fi - name: Install cuda.pathfinder nvidia_wheels_cu12 - if: ${{ env.SKIP_CUDA_BINDINGS_TEST == '0'}} + if: startsWith(matrix.CUDA_VER, '12.') run: | pushd cuda_pathfinder pip install -v .[nvidia_wheels_cu12] @@ -327,7 +327,7 @@ jobs: popd - name: Run cuda.pathfinder tests with all_must_work - if: ${{ env.SKIP_CUDA_BINDINGS_TEST == '0'}} + if: startsWith(matrix.CUDA_VER, '12.') env: CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS: all_must_work run: run-tests pathfinder diff --git a/.github/workflows/test-wheel-windows.yml b/.github/workflows/test-wheel-windows.yml index 86d21ed82..b3b51e0fd 100644 --- a/.github/workflows/test-wheel-windows.yml +++ b/.github/workflows/test-wheel-windows.yml @@ -286,7 +286,7 @@ jobs: } - name: Install cuda.pathfinder nvidia_wheels_cu12 - if: ${{ env.SKIP_CUDA_BINDINGS_TEST == '0' }} + if: startsWith(matrix.CUDA_VER, '12.') shell: bash --noprofile --norc -xeuo pipefail {0} run: | pushd cuda_pathfinder @@ -295,7 +295,7 @@ jobs: popd - name: Run cuda.pathfinder tests with all_must_work - if: ${{ env.SKIP_CUDA_BINDINGS_TEST == '0' }} + if: startsWith(matrix.CUDA_VER, '12.') env: CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS: all_must_work shell: bash --noprofile --norc -xeuo pipefail {0} From 8f015d211c082f6492d5f8a08709f6ce99bf5e3f Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 6 Jul 2025 12:22:47 -0700 Subject: [PATCH 59/78] Get rid of "partially supported" concept. --- .../_dynamic_libs/supported_nvidia_libs.py | 32 ++++-------- .../tests/test_load_nvidia_dynamic_lib.py | 51 +++++++++---------- 2 files changed, 32 insertions(+), 51 deletions(-) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py index d544ac963..a8c8f2542 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py @@ -12,17 +12,13 @@ IS_WINDOWS = sys.platform == "win32" -SUPPORTED_LIBNAMES = ( +SUPPORTED_LIBNAMES_COMMON = ( # Core CUDA Runtime and Compiler + "cudart", + "nvfatbin", "nvJitLink", "nvrtc", "nvvm", -) - -PARTIALLY_SUPPORTED_LIBNAMES_COMMON = ( - # Core CUDA Runtime and Compiler - "cudart", - "nvfatbin", # Math Libraries "cublas", "cublasLt", @@ -55,27 +51,17 @@ # and limited availability. Keeping this as a reference avoids having to # reconstruct the information from scratch in the future. -PARTIALLY_SUPPORTED_LIBNAMES_LINUX_ONLY = ( +SUPPORTED_LIBNAMES_LINUX_ONLY = ( "cufile", # "cufile_rdma", # Requires libmlx5.so ) +SUPPORTED_LIBNAMES_LINUX = SUPPORTED_LIBNAMES_COMMON + SUPPORTED_LIBNAMES_LINUX_ONLY -PARTIALLY_SUPPORTED_LIBNAMES_LINUX = PARTIALLY_SUPPORTED_LIBNAMES_COMMON + PARTIALLY_SUPPORTED_LIBNAMES_LINUX_ONLY - -PARTIALLY_SUPPORTED_LIBNAMES_WINDOWS_ONLY = () - -PARTIALLY_SUPPORTED_LIBNAMES_WINDOWS = PARTIALLY_SUPPORTED_LIBNAMES_COMMON + PARTIALLY_SUPPORTED_LIBNAMES_WINDOWS_ONLY - -PARTIALLY_SUPPORTED_LIBNAMES_ALL = ( - PARTIALLY_SUPPORTED_LIBNAMES_COMMON - + PARTIALLY_SUPPORTED_LIBNAMES_LINUX_ONLY - + PARTIALLY_SUPPORTED_LIBNAMES_WINDOWS_ONLY -) +SUPPORTED_LIBNAMES_WINDOWS_ONLY = () +SUPPORTED_LIBNAMES_WINDOWS = SUPPORTED_LIBNAMES_COMMON + SUPPORTED_LIBNAMES_WINDOWS_ONLY -if IS_WINDOWS: - PARTIALLY_SUPPORTED_LIBNAMES = PARTIALLY_SUPPORTED_LIBNAMES_WINDOWS -else: - PARTIALLY_SUPPORTED_LIBNAMES = PARTIALLY_SUPPORTED_LIBNAMES_LINUX +SUPPORTED_LIBNAMES_ALL = SUPPORTED_LIBNAMES_COMMON + SUPPORTED_LIBNAMES_LINUX_ONLY + SUPPORTED_LIBNAMES_WINDOWS_ONLY +SUPPORTED_LIBNAMES = SUPPORTED_LIBNAMES_WINDOWS if IS_WINDOWS else SUPPORTED_LIBNAMES_LINUX # Based on ldd output for Linux x86_64 nvidia-*-cu12 wheels (12.8.1) DIRECT_DEPENDENCIES = { diff --git a/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py b/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py index 457c0e118..89e3ae6f2 100644 --- a/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py @@ -11,24 +11,20 @@ from cuda.pathfinder import SUPPORTED_NVIDIA_LIBNAMES, load_nvidia_dynamic_lib from cuda.pathfinder._dynamic_libs import supported_nvidia_libs -ALL_LIBNAMES = SUPPORTED_NVIDIA_LIBNAMES + supported_nvidia_libs.PARTIALLY_SUPPORTED_LIBNAMES_ALL -ALL_LIBNAMES_LINUX = SUPPORTED_NVIDIA_LIBNAMES + supported_nvidia_libs.PARTIALLY_SUPPORTED_LIBNAMES_LINUX -ALL_LIBNAMES_WINDOWS = SUPPORTED_NVIDIA_LIBNAMES + supported_nvidia_libs.PARTIALLY_SUPPORTED_LIBNAMES_WINDOWS -if sys.platform == "win32": - TEST_LOAD_LIBNAMES = ALL_LIBNAMES_WINDOWS -else: - TEST_LOAD_LIBNAMES = ALL_LIBNAMES_LINUX +STRICTNESS = os.environ.get("CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS", "see_what_works") +assert STRICTNESS in ("see_what_works", "all_must_work") -STRICTNESS = os.environ.get("CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS", "supported_must_work") -assert STRICTNESS in ("see_what_works", "supported_must_work", "all_must_work") - -def test_all_libnames_linux_sonames_consistency(): - assert tuple(sorted(ALL_LIBNAMES_LINUX)) == tuple(sorted(supported_nvidia_libs.SUPPORTED_LINUX_SONAMES.keys())) +def test_supported_libnames_linux_sonames_consistency(): + assert tuple(sorted(supported_nvidia_libs.SUPPORTED_LIBNAMES_LINUX)) == tuple( + sorted(supported_nvidia_libs.SUPPORTED_LINUX_SONAMES.keys()) + ) -def test_all_libnames_windows_dlls_consistency(): - assert tuple(sorted(ALL_LIBNAMES_WINDOWS)) == tuple(sorted(supported_nvidia_libs.SUPPORTED_WINDOWS_DLLS.keys())) +def test_supported_libnames_windows_dlls_consistency(): + assert tuple(sorted(supported_nvidia_libs.SUPPORTED_LIBNAMES_WINDOWS)) == tuple( + sorted(supported_nvidia_libs.SUPPORTED_WINDOWS_DLLS.keys()) + ) @pytest.mark.parametrize("dict_name", ["SUPPORTED_LINUX_SONAMES", "SUPPORTED_WINDOWS_DLLS"]) @@ -43,12 +39,17 @@ def test_libname_dict_values_are_unique(dict_name): libname_for_value[value] = libname -def test_all_libnames_libnames_requiring_os_add_dll_directory_consistency(): - assert not (set(supported_nvidia_libs.LIBNAMES_REQUIRING_OS_ADD_DLL_DIRECTORY) - set(ALL_LIBNAMES_WINDOWS)) +def test_supported_libnames_windows_libnames_requiring_os_add_dll_directory_consistency(): + assert not ( + set(supported_nvidia_libs.LIBNAMES_REQUIRING_OS_ADD_DLL_DIRECTORY) + - set(supported_nvidia_libs.SUPPORTED_LIBNAMES_WINDOWS) + ) -def test_all_libnames_expected_lib_symbols_consistency(): - assert tuple(sorted(ALL_LIBNAMES)) == tuple(sorted(supported_nvidia_libs.EXPECTED_LIB_SYMBOLS.keys())) +def test_supported_libnames_all_expected_lib_symbols_consistency(): + assert tuple(sorted(supported_nvidia_libs.SUPPORTED_LIBNAMES_ALL)) == tuple( + sorted(supported_nvidia_libs.EXPECTED_LIB_SYMBOLS.keys()) + ) def test_runtime_error_on_non_64bit_python(): @@ -89,7 +90,7 @@ def child_process_func(libname): print(f"{loaded_dl_fresh.abs_path!r}") -@pytest.mark.parametrize("libname", TEST_LOAD_LIBNAMES) +@pytest.mark.parametrize("libname", SUPPORTED_NVIDIA_LIBNAMES) def test_load_nvidia_dynamic_lib(info_summary_append, libname): # We intentionally run each dynamic library operation in a child process # to ensure isolation of global dynamic linking state (e.g., dlopen handles). @@ -99,13 +100,7 @@ def test_load_nvidia_dynamic_lib(info_summary_append, libname): result = spawned_process_runner.run_in_spawned_child_process(child_process_func, args=(libname,), timeout=timeout) if result.returncode == 0: info_summary_append(f"abs_path={result.stdout.rstrip()}") - else: - if STRICTNESS == "all_must_work": - strict = True - elif STRICTNESS == "supported_must_work": - strict = libname in SUPPORTED_NVIDIA_LIBNAMES - else: # "see_what_works" - strict = False - if strict or "DynamicLibNotFound: Failure finding " not in result.stderr: - raise RuntimeError(build_child_process_failed_for_libname_message(libname, result)) + elif STRICTNESS == "see_what_works" or "DynamicLibNotFound: Failure finding " in result.stderr: info_summary_append(f"Not found: {libname=!r}") + else: + raise RuntimeError(build_child_process_failed_for_libname_message(libname, result)) From 9f17cd11cc0497ab6f48e12cff2f0673dba6d08e Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 6 Jul 2025 12:26:43 -0700 Subject: [PATCH 60/78] Consistently use `IS_WINDOWS` (instead of `sys.platform == "win32"`). --- cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py b/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py index 89e3ae6f2..ee6b322b2 100644 --- a/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py @@ -2,7 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 import os -import sys from unittest.mock import patch import pytest @@ -10,6 +9,7 @@ from cuda.pathfinder import SUPPORTED_NVIDIA_LIBNAMES, load_nvidia_dynamic_lib from cuda.pathfinder._dynamic_libs import supported_nvidia_libs +from cuda.pathfinder._dynamic_libs.load_dl_common import IS_WINDOWS STRICTNESS = os.environ.get("CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS", "see_what_works") assert STRICTNESS in ("see_what_works", "all_must_work") @@ -96,7 +96,7 @@ def test_load_nvidia_dynamic_lib(info_summary_append, libname): # to ensure isolation of global dynamic linking state (e.g., dlopen handles). # Without child processes, loading/unloading libraries during testing could # interfere across test cases and lead to nondeterministic or platform-specific failures. - timeout = 120 if sys.platform == "win32" else 30 + timeout = 120 if IS_WINDOWS else 30 result = spawned_process_runner.run_in_spawned_child_process(child_process_func, args=(libname,), timeout=timeout) if result.returncode == 0: info_summary_append(f"abs_path={result.stdout.rstrip()}") From db7933ad87e197185de3e2cc7a2e5b046c8bdf0d Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 6 Jul 2025 12:32:54 -0700 Subject: [PATCH 61/78] Rename toolshed/build_pathfinder*.py scripts (no functional changes). --- .../pathfinder/_dynamic_libs/supported_nvidia_libs.py | 4 ++-- ...build_path_finder_dlls.py => build_pathfinder_dlls.py} | 8 ++++---- ...path_finder_sonames.py => build_pathfinder_sonames.py} | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) rename toolshed/{build_path_finder_dlls.py => build_pathfinder_dlls.py} (89%) rename toolshed/{build_path_finder_sonames.py => build_pathfinder_sonames.py} (86%) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py index a8c8f2542..19d73b23e 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py @@ -103,7 +103,7 @@ # cuda_12.6.2_560.35.03_linux.run # cuda_12.8.0_570.86.10_linux.run # cuda_12.9.0_575.51.03_linux.run -# Generated with toolshed/build_path_finder_sonames.py +# Generated with toolshed/build_pathfinder_sonames.py SUPPORTED_LINUX_SONAMES = { "cublas": ( "libcublas.so.11", @@ -225,7 +225,7 @@ # cuda_12.6.2_560.94_windows.exe # cuda_12.8.1_572.61_windows.exe # cuda_12.9.0_576.02_windows.txt -# Generated with toolshed/build_path_finder_dlls.py (WITH MANUAL EDITS) +# Generated with toolshed/build_pathfinder_dlls.py (WITH MANUAL EDITS) SUPPORTED_WINDOWS_DLLS = { "cublas": ( "cublas64_11.dll", diff --git a/toolshed/build_path_finder_dlls.py b/toolshed/build_pathfinder_dlls.py similarity index 89% rename from toolshed/build_path_finder_dlls.py rename to toolshed/build_pathfinder_dlls.py index a44ddceb7..e08bec82b 100755 --- a/toolshed/build_path_finder_dlls.py +++ b/toolshed/build_pathfinder_dlls.py @@ -13,7 +13,7 @@ import sys -LIBNAMES_IN_SCOPE_OF_CUDA_BINDINGS_PATH_FINDER = ( +LIBNAMES_IN_SCOPE_OF_CUDA_PATHFINDER = ( "nvJitLink", "nvrtc", "nvvm", @@ -66,10 +66,10 @@ def run(args): else: raise RuntimeError("------------------- NOT FOUND") - print("DLLs in scope of cuda.bindings.path_finder") - print("==========================================") + print("DLLs in scope of cuda.pathfinder") + print("================================") dlls_in_scope = set() - for libname in sorted(LIBNAMES_IN_SCOPE_OF_CUDA_BINDINGS_PATH_FINDER): + for libname in sorted(LIBNAMES_IN_SCOPE_OF_CUDA_PATHFINDER): print(f'"{libname}": (') for dll in sorted(dlls_from_files): if dll.startswith(libname): diff --git a/toolshed/build_path_finder_sonames.py b/toolshed/build_pathfinder_sonames.py similarity index 86% rename from toolshed/build_path_finder_sonames.py rename to toolshed/build_pathfinder_sonames.py index 17b7dd7b3..e595ca896 100755 --- a/toolshed/build_path_finder_sonames.py +++ b/toolshed/build_pathfinder_sonames.py @@ -12,7 +12,7 @@ import sys -LIBNAMES_IN_SCOPE_OF_CUDA_BINDINGS_PATH_FINDER = ( +LIBNAMES_IN_SCOPE_OF_CUDA_PATHFINDER = ( "nvJitLink", "nvrtc", "nvvm", @@ -54,10 +54,10 @@ def run(args): if flds[-1] != "SONAME_NOT_SET": sonames_from_file.add(flds[-1]) - print("SONAMEs in scope of cuda.bindings.path_finder") - print("=============================================") + print("SONAMEs in scope of cuda.pathfinder") + print("===================================") sonames_in_scope = set() - for libname in sorted(LIBNAMES_IN_SCOPE_OF_CUDA_BINDINGS_PATH_FINDER): + for libname in sorted(LIBNAMES_IN_SCOPE_OF_CUDA_PATHFINDER): print(f'"{libname}": (') lib_so = "lib" + libname + ".so" for soname in sorted(sonames_from_file): From 1b9a92960f3d40fa5512bf653ec839c5d3e09cc4 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 6 Jul 2025 12:42:54 -0700 Subject: [PATCH 62/78] Rename toolshed/run_cuda_pathfinder.py --- ...bindings_path_finder.py => run_cuda_pathfinder.py} | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) rename toolshed/{run_cuda_bindings_path_finder.py => run_cuda_pathfinder.py} (67%) diff --git a/toolshed/run_cuda_bindings_path_finder.py b/toolshed/run_cuda_pathfinder.py similarity index 67% rename from toolshed/run_cuda_bindings_path_finder.py rename to toolshed/run_cuda_pathfinder.py index ca2193a81..cf197c837 100644 --- a/toolshed/run_cuda_bindings_path_finder.py +++ b/toolshed/run_cuda_pathfinder.py @@ -5,24 +5,19 @@ import sys import traceback -from cuda.bindings import path_finder -from cuda.bindings._path_finder import supported_libs - -ALL_LIBNAMES = ( - path_finder._SUPPORTED_LIBNAMES + supported_libs.PARTIALLY_SUPPORTED_LIBNAMES -) +from cuda import pathfinder def run(args): if args: libnames = args else: - libnames = ALL_LIBNAMES + libnames = pathfinder.SUPPORTED_NVIDIA_LIBNAMES for libname in libnames: print(f"{libname=}") try: - loaded_dl = path_finder._load_nvidia_dynamic_library(libname) + loaded_dl = pathfinder.load_nvidia_dynamic_lib(libname) except Exception: print(f"EXCEPTION for {libname=}:") traceback.print_exc(file=sys.stdout) From b69bf23eefc8d77a8539b92b4fdd1de44d6f5a00 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 6 Jul 2025 14:02:04 -0700 Subject: [PATCH 63/78] Make output of toolshed/build_pathfinder_dlls.py usable as-is. --- toolshed/build_pathfinder_dlls.py | 52 +++++++++++++++++++++------- toolshed/build_pathfinder_sonames.py | 3 +- 2 files changed, 41 insertions(+), 14 deletions(-) diff --git a/toolshed/build_pathfinder_dlls.py b/toolshed/build_pathfinder_dlls.py index e08bec82b..3c62a9386 100755 --- a/toolshed/build_pathfinder_dlls.py +++ b/toolshed/build_pathfinder_dlls.py @@ -7,25 +7,26 @@ # Input for this script: .txt files generated with: # for exe in *.exe; do 7z l $exe > "${exe%.exe}.txt"; done -# The output of this script -# requires obvious manual edits to remove duplicates and unwanted dlls. -# TODO: filter out cudart32_*.dll, nvvm32.dll +# The output of this script is expected to be usable as-is. +import collections import sys +# ATTENTION: Ambiguous shorter names need to appear after matching longer names +# (e.g. "cufft" after "cufftw") LIBNAMES_IN_SCOPE_OF_CUDA_PATHFINDER = ( "nvJitLink", "nvrtc", "nvvm", "cudart", "nvfatbin", - "cublas", "cublasLt", - "cufft", + "cublas", "cufftw", + "cufft", "curand", - "cusolver", "cusolverMg", + "cusolver", "cusparse", "nppc", "nppial", @@ -39,12 +40,25 @@ "nppitc", "npps", "nvblas", - "cufile", - "cufile_rdma", "nvjpeg", ) +def is_suppressed_dll(libname, dll): + if libname == "cudart": + if dll.startswith("cudart32_"): + return True + elif libname == "nvrtc": + if dll.endswith(".alt.dll"): + return True + if dll.startswith("nvrtc-builtins"): + return True + elif libname == "nvvm": + if dll == "nvvm32.dll": + return True + return False + + def run(args): dlls_from_files = set() for filename in args: @@ -69,15 +83,29 @@ def run(args): print("DLLs in scope of cuda.pathfinder") print("================================") dlls_in_scope = set() - for libname in sorted(LIBNAMES_IN_SCOPE_OF_CUDA_PATHFINDER): - print(f'"{libname}": (') + dlls_by_libname = collections.defaultdict(list) + suppressed_dlls = set() + for libname in LIBNAMES_IN_SCOPE_OF_CUDA_PATHFINDER: for dll in sorted(dlls_from_files): - if dll.startswith(libname): + if dll not in dlls_in_scope and dll.startswith(libname): + if is_suppressed_dll(libname, dll): + suppressed_dlls.add(dll) + else: + dlls_by_libname[libname].append(dll) dlls_in_scope.add(dll) - print(f' "{dll}",') + for libname, dlls in sorted(dlls_by_libname.items()): + print(f'"{libname}": (') + for dll in dlls: + print(f' "{dll}",') print("),") print() + print("Suppressed DLLs") + print("===============") + for dll in sorted(suppressed_dlls): + print(dll) + print() + print("DLLs out of scope") print("=================") for dll in sorted(dlls_from_files - dlls_in_scope): diff --git a/toolshed/build_pathfinder_sonames.py b/toolshed/build_pathfinder_sonames.py index e595ca896..3cdaf185a 100755 --- a/toolshed/build_pathfinder_sonames.py +++ b/toolshed/build_pathfinder_sonames.py @@ -7,8 +7,7 @@ # Input for this script: # output of toolshed/find_sonames.sh -# The output of this script -# is expected to be usable as-is. +# The output of this script is expected to be usable as-is. import sys From 80ebbdad33ea735ded1756eed72da85bd1edaa78 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 7 Jul 2025 09:32:55 -0700 Subject: [PATCH 64/78] Add DynamicLibNotFound to cuda/pathfinder/__init__.py --- cuda_pathfinder/cuda/pathfinder/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cuda_pathfinder/cuda/pathfinder/__init__.py b/cuda_pathfinder/cuda/pathfinder/__init__.py index 1009b8b36..d72cd966c 100644 --- a/cuda_pathfinder/cuda/pathfinder/__init__.py +++ b/cuda_pathfinder/cuda/pathfinder/__init__.py @@ -1,6 +1,7 @@ # SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL as DynamicLibNotFound from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL as LoadedDL from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_lib import load_nvidia_dynamic_lib as load_nvidia_dynamic_lib from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import ( From 52e1369fa6159d187bd7a5a3f62f26e847ca116d Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 7 Jul 2025 09:40:46 -0700 Subject: [PATCH 65/78] Fix accident in previous commit (DynamicLibNotFound) --- cuda_pathfinder/cuda/pathfinder/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cuda_pathfinder/cuda/pathfinder/__init__.py b/cuda_pathfinder/cuda/pathfinder/__init__.py index d72cd966c..e148036d5 100644 --- a/cuda_pathfinder/cuda/pathfinder/__init__.py +++ b/cuda_pathfinder/cuda/pathfinder/__init__.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 -from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL as DynamicLibNotFound +from cuda.pathfinder._dynamic_libs.load_dl_common import DynamicLibNotFound as DynamicLibNotFound from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL as LoadedDL from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_lib import load_nvidia_dynamic_lib as load_nvidia_dynamic_lib from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import ( From 70d1c148ab56dce16dcbeab9a0e9365a4ffd2f4b Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 7 Jul 2025 09:51:12 -0700 Subject: [PATCH 66/78] Update README.md --- cuda_pathfinder/cuda/pathfinder/README.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/cuda_pathfinder/cuda/pathfinder/README.md b/cuda_pathfinder/cuda/pathfinder/README.md index f071ccc2f..297b71e8e 100644 --- a/cuda_pathfinder/cuda/pathfinder/README.md +++ b/cuda_pathfinder/cuda/pathfinder/README.md @@ -1,13 +1,17 @@ # `cuda.pathfinder` Module -## Public API (Work in Progress) +## Public API for loading NVIDIA Dynamic Libs -Currently exposes two primary interfaces: +* `cuda.pathfinder.SUPPORTED_NVIDIA_LIBNAMES` (`tuple[str]`) -``` -cuda.pathfinder.SUPPORTED_NVIDIA_LIBNAMES # ('nvJitLink', 'nvrtc', 'nvvm') -cuda.pathfinder.load_nvidia_dynamic_lib(libname: str) -> LoadedDL -``` +* `cuda.pathfinder.load_nvidia_dynamic_lib(libname: str) -> LoadedDL` + +* `cuda.pathfinder.LoadedDL`: + * `handle` (platform-specific type) + * `abs_path` (`str`) + * `was_already_loaded_from_elsewhere` (`bool`) + +* `cuda.pathfinder.DynamicLibNotFound` (inherits from `RuntimeError`) ## Dynamic Library Loading Search Priority From 342ca4976faf5c099c7db4bc42e85605f89c6330 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 7 Jul 2025 10:33:53 -0700 Subject: [PATCH 67/78] mypy cleanup --- .../_dynamic_libs/find_nvidia_dynamic_lib.py | 37 +++++++++++++------ .../_dynamic_libs/load_dl_common.py | 2 +- .../pathfinder/_dynamic_libs/load_dl_linux.py | 2 +- .../_dynamic_libs/load_dl_windows.py | 8 ++-- .../_dynamic_libs/load_nvidia_dynamic_lib.py | 1 + .../cuda/pathfinder/_utils/find_sub_dirs.py | 11 +++--- cuda_pathfinder/mypy.ini | 33 +++++++++++++++++ cuda_pathfinder/pyproject.toml | 3 ++ 8 files changed, 74 insertions(+), 23 deletions(-) create mode 100644 cuda_pathfinder/mypy.ini diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py index 1389573d3..4d0d4f9c9 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py @@ -4,6 +4,8 @@ import functools import glob import os +from collections.abc import Sequence +from typing import Optional from cuda.pathfinder._dynamic_libs.load_dl_common import DynamicLibNotFound from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import ( @@ -13,7 +15,9 @@ from cuda.pathfinder._utils.find_sub_dirs import find_sub_dirs_all_sitepackages -def _no_such_file_in_sub_dirs(sub_dirs, file_wild, error_messages, attachments): +def _no_such_file_in_sub_dirs( + sub_dirs: Sequence[str], file_wild: str, error_messages: list[str], attachments: list[str] +) -> None: error_messages.append(f"No such file: {file_wild}") for sub_dir in find_sub_dirs_all_sitepackages(sub_dirs): attachments.append(f' listdir("{sub_dir}"):') @@ -21,7 +25,9 @@ def _no_such_file_in_sub_dirs(sub_dirs, file_wild, error_messages, attachments): attachments.append(f" {node}") -def _find_so_using_nvidia_lib_dirs(libname, so_basename, error_messages, attachments): +def _find_so_using_nvidia_lib_dirs( + libname: str, so_basename: str, error_messages: list[str], attachments: list[str] +) -> Optional[str]: nvidia_sub_dirs = ("nvidia", "*", "nvvm", "lib64") if libname == "nvvm" else ("nvidia", "*", "lib") file_wild = so_basename + "*" for lib_dir in find_sub_dirs_all_sitepackages(nvidia_sub_dirs): @@ -38,7 +44,7 @@ def _find_so_using_nvidia_lib_dirs(libname, so_basename, error_messages, attachm return None -def _find_dll_under_dir(dirpath, file_wild): +def _find_dll_under_dir(dirpath: str, file_wild: str) -> Optional[str]: for path in sorted(glob.glob(os.path.join(dirpath, file_wild))): if not os.path.isfile(path): continue @@ -47,7 +53,9 @@ def _find_dll_under_dir(dirpath, file_wild): return None -def _find_dll_using_nvidia_bin_dirs(libname, lib_searched_for, error_messages, attachments): +def _find_dll_using_nvidia_bin_dirs( + libname: str, lib_searched_for: str, error_messages: list[str], attachments: list[str] +) -> Optional[str]: nvidia_sub_dirs = ("nvidia", "*", "nvvm", "bin") if libname == "nvvm" else ("nvidia", "*", "bin") for bin_dir in find_sub_dirs_all_sitepackages(nvidia_sub_dirs): dll_name = _find_dll_under_dir(bin_dir, lib_searched_for) @@ -57,17 +65,18 @@ def _find_dll_using_nvidia_bin_dirs(libname, lib_searched_for, error_messages, a return None -def _get_cuda_home(): +def _get_cuda_home() -> Optional[str]: cuda_home = os.environ.get("CUDA_HOME") if cuda_home is None: cuda_home = os.environ.get("CUDA_PATH") return cuda_home -def _find_lib_dir_using_cuda_home(libname): +def _find_lib_dir_using_cuda_home(libname: str) -> Optional[str]: cuda_home = _get_cuda_home() if cuda_home is None: return None + subdirs: tuple[str, ...] if IS_WINDOWS: subdirs = (os.path.join("nvvm", "bin"),) if libname == "nvvm" else ("bin",) else: @@ -86,7 +95,9 @@ def _find_lib_dir_using_cuda_home(libname): return None -def _find_so_using_lib_dir(lib_dir, so_basename, error_messages, attachments): +def _find_so_using_lib_dir( + lib_dir: str, so_basename: str, error_messages: list[str], attachments: list[str] +) -> Optional[str]: so_name = os.path.join(lib_dir, so_basename) if os.path.isfile(so_name): return so_name @@ -100,7 +111,9 @@ def _find_so_using_lib_dir(lib_dir, so_basename, error_messages, attachments): return None -def _find_dll_using_lib_dir(lib_dir, libname, error_messages, attachments): +def _find_dll_using_lib_dir( + lib_dir: str, libname: str, error_messages: list[str], attachments: list[str] +) -> Optional[str]: file_wild = libname + "*.dll" dll_name = _find_dll_under_dir(lib_dir, file_wild) if dll_name is not None: @@ -115,8 +128,8 @@ def _find_dll_using_lib_dir(lib_dir, libname, error_messages, attachments): class _find_nvidia_dynamic_lib: def __init__(self, libname: str): self.libname = libname - self.error_messages = [] - self.attachments = [] + self.error_messages: list[str] = [] + self.attachments: list[str] = [] self.abs_path = None if IS_WINDOWS: @@ -138,7 +151,7 @@ def __init__(self, libname: str): self.attachments, ) - def retry_with_cuda_home_priority_last(self): + def retry_with_cuda_home_priority_last(self) -> None: cuda_home_lib_dir = _find_lib_dir_using_cuda_home(self.libname) if cuda_home_lib_dir is not None: if IS_WINDOWS: @@ -156,7 +169,7 @@ def retry_with_cuda_home_priority_last(self): self.attachments, ) - def raise_if_abs_path_is_None(self): + def raise_if_abs_path_is_None(self) -> str: if self.abs_path: return self.abs_path err = ", ".join(self.error_messages) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py index 836c62c42..1b6fef9e8 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py @@ -23,7 +23,7 @@ class DynamicLibNotFound(RuntimeError): @dataclass class LoadedDL: - handle: HandleType + handle: HandleType # type: ignore[valid-type] abs_path: Optional[str] was_already_loaded_from_elsewhere: bool diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py index 9ab45d2ef..ac080ec6e 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py @@ -53,7 +53,7 @@ def abs_path_for_dynamic_library(libname: str, handle: ctypes.CDLL) -> Optional[ info = Dl_info() if LIBDL.dladdr(addr, ctypes.byref(info)) == 0: raise OSError(f"dladdr failed for {libname=!r}") - return info.dli_fname.decode() + return info.dli_fname.decode() # type: ignore[no-any-return] def check_if_already_loaded_from_elsewhere(libname: str) -> Optional[LoadedDL]: diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py index ac24b9cec..3bf9653d2 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py @@ -27,7 +27,7 @@ def add_dll_directory(dll_abs_path: str) -> None: dirpath = os.path.dirname(dll_abs_path) assert os.path.isdir(dirpath), dll_abs_path # Add the DLL directory to the search path - os.add_dll_directory(dirpath) + os.add_dll_directory(dirpath) # type: ignore[attr-defined] # Update PATH as a fallback for dependent DLL resolution curr_path = os.environ.get("PATH") os.environ["PATH"] = dirpath if curr_path is None else os.pathsep.join((curr_path, dirpath)) @@ -36,7 +36,7 @@ def add_dll_directory(dll_abs_path: str) -> None: def abs_path_for_dynamic_library(libname: str, handle: pywintypes.HANDLE) -> str: """Get the absolute path of a loaded dynamic library on Windows.""" try: - return win32api.GetModuleFileName(handle) + return win32api.GetModuleFileName(handle) # type: ignore[no-any-return] except Exception as e: raise RuntimeError(f"GetModuleFileName failed for {libname!r} (exception type: {type(e)})") from e @@ -67,12 +67,12 @@ def check_if_already_loaded_from_elsewhere(libname: str) -> Optional[LoadedDL]: return None -def load_with_system_search(libname: str, _unused: str) -> Optional[LoadedDL]: +def load_with_system_search(libname: str, soname: str) -> Optional[LoadedDL]: """Try to load a DLL using system search paths. Args: libname: The name of the library to load - _unused: Unused parameter (kept for interface consistency) + soname: Unused parameter (kept for interface consistency) Returns: A LoadedDL object if successful, None if the library cannot be loaded diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py index d05779d06..101088e60 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py @@ -44,6 +44,7 @@ def _load_lib_no_cache(libname: str) -> LoadedDL: found.raise_if_abs_path_is_None() # Load the library from the found path + assert found.abs_path is not None # for mypy return load_with_abs_path(libname, found.abs_path) diff --git a/cuda_pathfinder/cuda/pathfinder/_utils/find_sub_dirs.py b/cuda_pathfinder/cuda/pathfinder/_utils/find_sub_dirs.py index 8af8f24fd..b05467e52 100644 --- a/cuda_pathfinder/cuda/pathfinder/_utils/find_sub_dirs.py +++ b/cuda_pathfinder/cuda/pathfinder/_utils/find_sub_dirs.py @@ -5,9 +5,10 @@ import os import site import sys +from collections.abc import Sequence -def find_sub_dirs_no_cache(parent_dirs, sub_dirs): +def find_sub_dirs_no_cache(parent_dirs: Sequence[str], sub_dirs: Sequence[str]) -> list[str]: results = [] for base in parent_dirs: stack = [(base, 0)] # (current_path, index into sub_dirs) @@ -36,17 +37,17 @@ def find_sub_dirs_no_cache(parent_dirs, sub_dirs): @functools.cache -def find_sub_dirs_cached(parent_dirs, sub_dirs): +def find_sub_dirs_cached(parent_dirs: Sequence[str], sub_dirs: Sequence[str]) -> list[str]: return find_sub_dirs_no_cache(parent_dirs, sub_dirs) -def find_sub_dirs(parent_dirs, sub_dirs): +def find_sub_dirs(parent_dirs: Sequence[str], sub_dirs: Sequence[str]) -> list[str]: return find_sub_dirs_cached(tuple(parent_dirs), tuple(sub_dirs)) -def find_sub_dirs_sys_path(sub_dirs): +def find_sub_dirs_sys_path(sub_dirs: Sequence[str]) -> list[str]: return find_sub_dirs(sys.path, sub_dirs) -def find_sub_dirs_all_sitepackages(sub_dirs): +def find_sub_dirs_all_sitepackages(sub_dirs: Sequence[str]) -> list[str]: return find_sub_dirs((site.getusersitepackages(),) + tuple(site.getsitepackages()), sub_dirs) diff --git a/cuda_pathfinder/mypy.ini b/cuda_pathfinder/mypy.ini new file mode 100644 index 000000000..8eb52bb92 --- /dev/null +++ b/cuda_pathfinder/mypy.ini @@ -0,0 +1,33 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +[mypy] +# Basic settings +python_version = 3.9 +explicit_package_bases = True +warn_return_any = True +warn_unused_configs = True +disallow_untyped_defs = True + +# Start strict, but allow some flexibility +check_untyped_defs = True +disallow_any_generics = True +no_implicit_optional = True +warn_redundant_casts = True +warn_unused_ignores = True + +# Allow some common patterns to keep it simple +allow_redefinition = True +implicit_reexport = True + +# Ignore missing imports for now (you can tighten this later) +ignore_missing_imports = True + +# Only check your package +[mypy-cuda.pathfinder.*] +disallow_untyped_defs = True + +# Be more lenient with test files +[mypy-tests.*] +disallow_untyped_defs = False +ignore_errors = True diff --git a/cuda_pathfinder/pyproject.toml b/cuda_pathfinder/pyproject.toml index 5c705cad4..a3a62e939 100644 --- a/cuda_pathfinder/pyproject.toml +++ b/cuda_pathfinder/pyproject.toml @@ -16,6 +16,9 @@ dependencies = [ test = [ "pytest>=6.2.4", ] +typing = [ + "mypy>=1.0.0", +] nvidia_wheels_cu12 = [ "nvidia-cublas-cu12", "nvidia-cuda-nvcc-cu12", From 4e0033c0f224d5775f038bf413840233f66fc957 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 7 Jul 2025 12:10:28 -0700 Subject: [PATCH 68/78] Run mypy from pre-commit --- .pre-commit-config.yaml | 8 ++++++++ cuda_pathfinder/pyproject.toml | 3 --- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a7112246a..7cf95c031 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -37,5 +37,13 @@ repos: - --ini - .bandit + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.8.0 + hooks: + - id: mypy + name: mypy-pathfinder + files: ^cuda_pathfinder/cuda/.*\.py$ # Exclude tests directory + args: [--config-file=cuda_pathfinder/mypy.ini] + default_language_version: python: python3 diff --git a/cuda_pathfinder/pyproject.toml b/cuda_pathfinder/pyproject.toml index a3a62e939..5c705cad4 100644 --- a/cuda_pathfinder/pyproject.toml +++ b/cuda_pathfinder/pyproject.toml @@ -16,9 +16,6 @@ dependencies = [ test = [ "pytest>=6.2.4", ] -typing = [ - "mypy>=1.0.0", -] nvidia_wheels_cu12 = [ "nvidia-cublas-cu12", "nvidia-cuda-nvcc-cu12", From 74ef126b5aeee3c10c6b9d591abc5f7d9fe32f26 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 7 Jul 2025 15:31:45 -0700 Subject: [PATCH 69/78] Use SHA for mypy version in .pre-commit-config.yaml (generated with `pre-commit autoupdate --freeze`, but keeping only the change for mypy). --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7cf95c031..7e9059d22 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -38,7 +38,7 @@ repos: - .bandit - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.8.0 + rev: 0f86793af5ef5f6dc63c8d04a3cabfa3ea8f9c6a # frozen: v1.16.1 hooks: - id: mypy name: mypy-pathfinder From 5e85328192be7843fa6791cc2060d2572577bb7e Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 7 Jul 2025 15:49:39 -0700 Subject: [PATCH 70/78] cuda_bindings/pyproject.toml: constrain "cuda-pathfinder ~= 1.0" --- cuda_bindings/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cuda_bindings/pyproject.toml b/cuda_bindings/pyproject.toml index 50d0ba5b2..47cc6a00e 100644 --- a/cuda_bindings/pyproject.toml +++ b/cuda_bindings/pyproject.toml @@ -27,7 +27,7 @@ dynamic = [ "readme", ] dependencies = [ - "cuda-pathfinder", + "cuda-pathfinder ~= 1.0", "pywin32; sys_platform == 'win32'", ] From 46fd972099e69a04b457c24b0505ebf29f447f86 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 9 Jul 2025 09:19:36 -0700 Subject: [PATCH 71/78] Make LoadedDL.handle an unsigned integer also for Windows. (cuda_pathfinder/tests pass, cuda_bindings/tests are broken). Interactive testing: CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS=all_must_work pytest -ra -s -v tests/ python ../toolshed/run_cuda_pathfinder.py --- .../_dynamic_libs/load_dl_common.py | 14 ++--------- .../_dynamic_libs/load_dl_windows.py | 23 ++++++++++++++++--- .../tests/test_load_nvidia_dynamic_lib.py | 3 +-- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py index 1b6fef9e8..5b090dab7 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py @@ -4,17 +4,7 @@ from dataclasses import dataclass from typing import Callable, Optional -from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import ( - DIRECT_DEPENDENCIES, - IS_WINDOWS, -) - -if IS_WINDOWS: - import pywintypes - - HandleType = pywintypes.HANDLE -else: - HandleType = int +from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import DIRECT_DEPENDENCIES class DynamicLibNotFound(RuntimeError): @@ -23,9 +13,9 @@ class DynamicLibNotFound(RuntimeError): @dataclass class LoadedDL: - handle: HandleType # type: ignore[valid-type] abs_path: Optional[str] was_already_loaded_from_elsewhere: bool + handle: int # Platform-agnostic unsigned pointer value def load_dependencies(libname: str, load_func: Callable[[str], LoadedDL]) -> None: diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py index 3bf9653d2..be1f15e99 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py @@ -1,6 +1,7 @@ # SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +import struct from typing import Optional import pywintypes @@ -12,6 +13,18 @@ WINBASE_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x00000100 WINBASE_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x00001000 +POINTER_ADDRESS_SPACE = 2 ** (struct.calcsize("P") * 8) + + +def pywintypes_handle_to_unsigned_int(pywintypes_handle: pywintypes.HANDLE) -> int: + # pywintypes.HANDLE is already an integer representation of a pointer + # Just ensure it's treated as unsigned + handle_uint = int(pywintypes_handle) + if handle_uint < 0: + # Convert from signed to unsigned representation + handle_uint += POINTER_ADDRESS_SPACE + return handle_uint + def add_dll_directory(dll_abs_path: str) -> None: """Add a DLL directory to the search path and update PATH environment variable. @@ -63,7 +76,9 @@ def check_if_already_loaded_from_elsewhere(libname: str) -> Optional[LoadedDL]: except pywintypes.error: continue else: - return LoadedDL(handle, abs_path_for_dynamic_library(libname, handle), True) + return LoadedDL( + pywintypes_handle_to_unsigned_int(handle), abs_path_for_dynamic_library(libname, handle), True + ) return None @@ -85,7 +100,9 @@ def load_with_system_search(libname: str, soname: str) -> Optional[LoadedDL]: except pywintypes.error: continue else: - return LoadedDL(handle, abs_path_for_dynamic_library(libname, handle), False) + return LoadedDL( + pywintypes_handle_to_unsigned_int(handle), abs_path_for_dynamic_library(libname, handle), False + ) return None @@ -115,4 +132,4 @@ def load_with_abs_path(libname: str, found_path: str) -> LoadedDL: handle = win32api.LoadLibraryEx(found_path, 0, flags) except pywintypes.error as e: raise RuntimeError(f"Failed to load DLL at {found_path}: {e}") from e - return LoadedDL(handle, found_path, False) + return LoadedDL(pywintypes_handle_to_unsigned_int(handle), found_path, False) diff --git a/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py b/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py index ee6b322b2..31263f7d2 100644 --- a/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py @@ -9,7 +9,6 @@ from cuda.pathfinder import SUPPORTED_NVIDIA_LIBNAMES, load_nvidia_dynamic_lib from cuda.pathfinder._dynamic_libs import supported_nvidia_libs -from cuda.pathfinder._dynamic_libs.load_dl_common import IS_WINDOWS STRICTNESS = os.environ.get("CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS", "see_what_works") assert STRICTNESS in ("see_what_works", "all_must_work") @@ -96,7 +95,7 @@ def test_load_nvidia_dynamic_lib(info_summary_append, libname): # to ensure isolation of global dynamic linking state (e.g., dlopen handles). # Without child processes, loading/unloading libraries during testing could # interfere across test cases and lead to nondeterministic or platform-specific failures. - timeout = 120 if IS_WINDOWS else 30 + timeout = 120 if supported_nvidia_libs.IS_WINDOWS else 30 result = spawned_process_runner.run_in_spawned_child_process(child_process_func, args=(libname,), timeout=timeout) if result.returncode == 0: info_summary_append(f"abs_path={result.stdout.rstrip()}") From 428a2dcbaee23e041791457227ebb949c1a39c31 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 9 Jul 2025 09:27:24 -0700 Subject: [PATCH 72/78] =?UTF-8?q?Rename=20LoadedDL.handle=20=E2=86=92=20Lo?= =?UTF-8?q?adedDL.=5Fhandle=5Fuint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This does not break any cuda_pathfinder tests. (cuda_bindings tests are "more broken".) --- cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py index 5b090dab7..d61875ac4 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py @@ -13,9 +13,9 @@ class DynamicLibNotFound(RuntimeError): @dataclass class LoadedDL: + _handle_uint: int # Platform-agnostic unsigned pointer value abs_path: Optional[str] was_already_loaded_from_elsewhere: bool - handle: int # Platform-agnostic unsigned pointer value def load_dependencies(libname: str, load_func: Callable[[str], LoadedDL]) -> None: From 40968855f6793497e8d622efe2b6842de4cfa25c Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 9 Jul 2025 09:37:32 -0700 Subject: [PATCH 73/78] Move `_handle_uint` last in `LoadedDL`, to emphasize that this is private member. --- .../cuda/pathfinder/_dynamic_libs/load_dl_common.py | 2 +- .../cuda/pathfinder/_dynamic_libs/load_dl_linux.py | 6 +++--- .../cuda/pathfinder/_dynamic_libs/load_dl_windows.py | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py index d61875ac4..9d1282f01 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py @@ -13,9 +13,9 @@ class DynamicLibNotFound(RuntimeError): @dataclass class LoadedDL: - _handle_uint: int # Platform-agnostic unsigned pointer value abs_path: Optional[str] was_already_loaded_from_elsewhere: bool + _handle_uint: int # Platform-agnostic unsigned pointer value def load_dependencies(libname: str, load_func: Callable[[str], LoadedDL]) -> None: diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py index ac080ec6e..e0c965037 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py @@ -78,7 +78,7 @@ def check_if_already_loaded_from_elsewhere(libname: str) -> Optional[LoadedDL]: except OSError: continue else: - return LoadedDL(handle._handle, abs_path_for_dynamic_library(libname, handle), True) + return LoadedDL(abs_path_for_dynamic_library(libname, handle), True, handle._handle) return None @@ -100,7 +100,7 @@ def load_with_system_search(libname: str, soname: str) -> Optional[LoadedDL]: abs_path = abs_path_for_dynamic_library(libname, handle) if abs_path is None: raise RuntimeError(f"No expected symbol for {libname=!r}") - return LoadedDL(handle._handle, abs_path, False) + return LoadedDL(abs_path, False, handle._handle) except OSError: return None @@ -122,4 +122,4 @@ def load_with_abs_path(libname: str, found_path: str) -> LoadedDL: handle = ctypes.CDLL(found_path, CDLL_MODE) except OSError as e: raise RuntimeError(f"Failed to dlopen {found_path}: {e}") from e - return LoadedDL(handle._handle, found_path, False) + return LoadedDL(found_path, False, handle._handle) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py index be1f15e99..506d81b4b 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py @@ -77,7 +77,7 @@ def check_if_already_loaded_from_elsewhere(libname: str) -> Optional[LoadedDL]: continue else: return LoadedDL( - pywintypes_handle_to_unsigned_int(handle), abs_path_for_dynamic_library(libname, handle), True + abs_path_for_dynamic_library(libname, handle), True, pywintypes_handle_to_unsigned_int(handle) ) return None @@ -101,7 +101,7 @@ def load_with_system_search(libname: str, soname: str) -> Optional[LoadedDL]: continue else: return LoadedDL( - pywintypes_handle_to_unsigned_int(handle), abs_path_for_dynamic_library(libname, handle), False + abs_path_for_dynamic_library(libname, handle), False, pywintypes_handle_to_unsigned_int(handle) ) return None @@ -132,4 +132,4 @@ def load_with_abs_path(libname: str, found_path: str) -> LoadedDL: handle = win32api.LoadLibraryEx(found_path, 0, flags) except pywintypes.error as e: raise RuntimeError(f"Failed to load DLL at {found_path}: {e}") from e - return LoadedDL(pywintypes_handle_to_unsigned_int(handle), found_path, False) + return LoadedDL(found_path, False, pywintypes_handle_to_unsigned_int(handle)) From 5e6c7e5d630fc3b0a9e60a815650ad091e73810f Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 9 Jul 2025 09:58:59 -0700 Subject: [PATCH 74/78] Implement TEMPORARY BACKWARD COMPATIBILITY in /cuda/bindings/path_finder.py --- cuda_bindings/cuda/bindings/path_finder.py | 39 +++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/cuda_bindings/cuda/bindings/path_finder.py b/cuda_bindings/cuda/bindings/path_finder.py index da129e6b4..095ed0406 100644 --- a/cuda_bindings/cuda/bindings/path_finder.py +++ b/cuda_bindings/cuda/bindings/path_finder.py @@ -2,9 +2,46 @@ # SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE from cuda.pathfinder import SUPPORTED_NVIDIA_LIBNAMES as _SUPPORTED_LIBNAMES -from cuda.pathfinder import load_nvidia_dynamic_lib as _load_nvidia_dynamic_library +from cuda.pathfinder import load_nvidia_dynamic_lib __all__ = [ "_load_nvidia_dynamic_library", "_SUPPORTED_LIBNAMES", ] + +# All code below this line is for TEMPORARY BACKWARD COMPATIBILITY only. + +from dataclasses import dataclass +from typing import Optional + +from cuda.pathfinder._dynamic_libs import supported_nvidia_libs + +if supported_nvidia_libs.IS_WINDOWS: + import pywintypes + + from cuda.pathfinder._load_dl_windows import POINTER_ADDRESS_SPACE + + def _unsigned_int_to_pywintypes_handle(handle_uint: int) -> pywintypes.HANDLE: + handle_int = handle_uint - POINTER_ADDRESS_SPACE if handle_uint >= POINTER_ADDRESS_SPACE // 2 else handle_uint + return pywintypes.HANDLE(handle_int) + + HandleType = pywintypes.HANDLE +else: + HandleType = int + + +# Original implementation, before making handle private as _handle_uint. +@dataclass +class LoadedDL: + handle: HandleType # type: ignore[valid-type] + abs_path: Optional[str] + was_already_loaded_from_elsewhere: bool + + +def _load_nvidia_dynamic_library(libname: str) -> LoadedDL: + loaded_dl_uint = load_nvidia_dynamic_lib(libname) + if supported_nvidia_libs.IS_WINDOWS: + handle = _unsigned_int_to_pywintypes_handle(loaded_dl_uint._handle_uint) + else: + handle = loaded_dl_uint._handle_uint + return LoadedDL(handle, loaded_dl_uint.abs_path, loaded_dl_uint.was_already_loaded_from_elsewhere) From d787a4c42b8bb5f15e3db0a981c9ce8eae4b6064 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Wed, 9 Jul 2025 10:49:59 -0700 Subject: [PATCH 75/78] Fix oversight discovered via local Windows testing. --- cuda_bindings/cuda/bindings/path_finder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cuda_bindings/cuda/bindings/path_finder.py b/cuda_bindings/cuda/bindings/path_finder.py index 095ed0406..1185c1d89 100644 --- a/cuda_bindings/cuda/bindings/path_finder.py +++ b/cuda_bindings/cuda/bindings/path_finder.py @@ -19,7 +19,7 @@ if supported_nvidia_libs.IS_WINDOWS: import pywintypes - from cuda.pathfinder._load_dl_windows import POINTER_ADDRESS_SPACE + from cuda.pathfinder._dynamic_libs.load_dl_windows import POINTER_ADDRESS_SPACE def _unsigned_int_to_pywintypes_handle(handle_uint: int) -> pywintypes.HANDLE: handle_int = handle_uint - POINTER_ADDRESS_SPACE if handle_uint >= POINTER_ADDRESS_SPACE // 2 else handle_uint From c0509beebe88bcbd223c7e8fe817e6a1d4fb7266 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 11 Jul 2025 12:43:02 -0700 Subject: [PATCH 76/78] Put the changes from https://github.com/NVIDIA/cuda-python/pull/751 on top of this PR (723) --- cuda_pathfinder/cuda/pathfinder/README.md | 2 +- cuda_pathfinder/cuda/pathfinder/__init__.py | 2 +- .../_dynamic_libs/find_nvidia_dynamic_lib.py | 10 +- .../_dynamic_libs/load_dl_common.py | 2 +- .../pathfinder/_dynamic_libs/load_dl_linux.py | 10 +- .../_dynamic_libs/load_dl_windows.py | 112 ++++++++++++------ .../_dynamic_libs/load_nvidia_dynamic_lib.py | 4 +- .../cuda/pathfinder/_utils/find_sub_dirs.py | 2 +- cuda_pathfinder/pyproject.toml | 41 ++++--- cuda_pathfinder/tests/conftest.py | 2 +- .../tests/test_load_nvidia_dynamic_lib.py | 5 +- 11 files changed, 118 insertions(+), 74 deletions(-) diff --git a/cuda_pathfinder/cuda/pathfinder/README.md b/cuda_pathfinder/cuda/pathfinder/README.md index 297b71e8e..6cc667621 100644 --- a/cuda_pathfinder/cuda/pathfinder/README.md +++ b/cuda_pathfinder/cuda/pathfinder/README.md @@ -11,7 +11,7 @@ * `abs_path` (`str`) * `was_already_loaded_from_elsewhere` (`bool`) -* `cuda.pathfinder.DynamicLibNotFound` (inherits from `RuntimeError`) +* `cuda.pathfinder.DynamicLibNotFoundError` (inherits from `RuntimeError`) ## Dynamic Library Loading Search Priority diff --git a/cuda_pathfinder/cuda/pathfinder/__init__.py b/cuda_pathfinder/cuda/pathfinder/__init__.py index e148036d5..6bdeb151e 100644 --- a/cuda_pathfinder/cuda/pathfinder/__init__.py +++ b/cuda_pathfinder/cuda/pathfinder/__init__.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 -from cuda.pathfinder._dynamic_libs.load_dl_common import DynamicLibNotFound as DynamicLibNotFound +from cuda.pathfinder._dynamic_libs.load_dl_common import DynamicLibNotFoundError as DynamicLibNotFoundError from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL as LoadedDL from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_lib import load_nvidia_dynamic_lib as load_nvidia_dynamic_lib from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import ( diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py index 4d0d4f9c9..388c75845 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/find_nvidia_dynamic_lib.py @@ -7,7 +7,7 @@ from collections.abc import Sequence from typing import Optional -from cuda.pathfinder._dynamic_libs.load_dl_common import DynamicLibNotFound +from cuda.pathfinder._dynamic_libs.load_dl_common import DynamicLibNotFoundError from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import ( IS_WINDOWS, is_suppressed_dll_file, @@ -125,7 +125,7 @@ def _find_dll_using_lib_dir( return None -class _find_nvidia_dynamic_lib: +class _FindNvidiaDynamicLib: def __init__(self, libname: str): self.libname = libname self.error_messages: list[str] = [] @@ -169,14 +169,14 @@ def retry_with_cuda_home_priority_last(self) -> None: self.attachments, ) - def raise_if_abs_path_is_None(self) -> str: + def raise_if_abs_path_is_None(self) -> str: # noqa: N802 if self.abs_path: return self.abs_path err = ", ".join(self.error_messages) att = "\n".join(self.attachments) - raise DynamicLibNotFound(f'Failure finding "{self.lib_searched_for}": {err}\n{att}') + raise DynamicLibNotFoundError(f'Failure finding "{self.lib_searched_for}": {err}\n{att}') @functools.cache def find_nvidia_dynamic_lib(libname: str) -> str: - return _find_nvidia_dynamic_lib(libname).raise_if_abs_path_is_None() + return _FindNvidiaDynamicLib(libname).raise_if_abs_path_is_None() diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py index 9d1282f01..416718f5a 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_common.py @@ -7,7 +7,7 @@ from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import DIRECT_DEPENDENCIES -class DynamicLibNotFound(RuntimeError): +class DynamicLibNotFoundError(RuntimeError): pass diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py index e0c965037..73afce86b 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_linux.py @@ -16,15 +16,15 @@ LIBDL.dladdr.restype = ctypes.c_int -class Dl_info(ctypes.Structure): +class DlInfo(ctypes.Structure): """Structure used by dladdr to return information about a loaded symbol.""" - _fields_ = [ + _fields_ = ( ("dli_fname", ctypes.c_char_p), # path to .so ("dli_fbase", ctypes.c_void_p), ("dli_sname", ctypes.c_char_p), ("dli_saddr", ctypes.c_void_p), - ] + ) def abs_path_for_dynamic_library(libname: str, handle: ctypes.CDLL) -> Optional[str]: @@ -50,7 +50,7 @@ def abs_path_for_dynamic_library(libname: str, handle: ctypes.CDLL) -> Optional[ return None addr = ctypes.cast(symbol, ctypes.c_void_p) - info = Dl_info() + info = DlInfo() if LIBDL.dladdr(addr, ctypes.byref(info)) == 0: raise OSError(f"dladdr failed for {libname=!r}") return info.dli_fname.decode() # type: ignore[no-any-return] @@ -105,7 +105,7 @@ def load_with_system_search(libname: str, soname: str) -> Optional[LoadedDL]: return None -def load_with_abs_path(libname: str, found_path: str) -> LoadedDL: +def load_with_abs_path(_libname: str, found_path: str) -> LoadedDL: """Load a dynamic library from the given path. Args: diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py index 506d81b4b..e843c5fbc 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_dl_windows.py @@ -1,12 +1,12 @@ # SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +import ctypes +import ctypes.wintypes +import os import struct from typing import Optional -import pywintypes -import win32api - from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL # Mirrors WinBase.h (unfortunately not defined already elsewhere) @@ -15,11 +15,37 @@ POINTER_ADDRESS_SPACE = 2 ** (struct.calcsize("P") * 8) - -def pywintypes_handle_to_unsigned_int(pywintypes_handle: pywintypes.HANDLE) -> int: - # pywintypes.HANDLE is already an integer representation of a pointer - # Just ensure it's treated as unsigned - handle_uint = int(pywintypes_handle) +# Set up kernel32 functions with proper types +kernel32 = ctypes.windll.kernel32 # type: ignore[attr-defined] + +# GetModuleHandleW +kernel32.GetModuleHandleW.argtypes = [ctypes.wintypes.LPCWSTR] +kernel32.GetModuleHandleW.restype = ctypes.wintypes.HMODULE + +# LoadLibraryExW +kernel32.LoadLibraryExW.argtypes = [ + ctypes.wintypes.LPCWSTR, # lpLibFileName + ctypes.wintypes.HANDLE, # hFile (reserved, must be NULL) + ctypes.wintypes.DWORD, # dwFlags +] +kernel32.LoadLibraryExW.restype = ctypes.wintypes.HMODULE + +# GetModuleFileNameW +kernel32.GetModuleFileNameW.argtypes = [ + ctypes.wintypes.HMODULE, # hModule + ctypes.wintypes.LPWSTR, # lpFilename + ctypes.wintypes.DWORD, # nSize +] +kernel32.GetModuleFileNameW.restype = ctypes.wintypes.DWORD + +# AddDllDirectory (Windows 7+) +kernel32.AddDllDirectory.argtypes = [ctypes.wintypes.LPCWSTR] +kernel32.AddDllDirectory.restype = ctypes.c_void_p # DLL_DIRECTORY_COOKIE + + +def ctypes_handle_to_unsigned_int(handle: ctypes.wintypes.HMODULE) -> int: + """Convert ctypes HMODULE to unsigned int.""" + handle_uint = int(handle) if handle_uint < 0: # Convert from signed to unsigned representation handle_uint += POINTER_ADDRESS_SPACE @@ -35,23 +61,39 @@ def add_dll_directory(dll_abs_path: str) -> None: Raises: AssertionError: If the directory containing the DLL does not exist """ - import os - dirpath = os.path.dirname(dll_abs_path) assert os.path.isdir(dirpath), dll_abs_path + # Add the DLL directory to the search path - os.add_dll_directory(dirpath) # type: ignore[attr-defined] + result = kernel32.AddDllDirectory(dirpath) + if not result: + # Fallback: just update PATH if AddDllDirectory fails + pass + # Update PATH as a fallback for dependent DLL resolution curr_path = os.environ.get("PATH") os.environ["PATH"] = dirpath if curr_path is None else os.pathsep.join((curr_path, dirpath)) -def abs_path_for_dynamic_library(libname: str, handle: pywintypes.HANDLE) -> str: +def abs_path_for_dynamic_library(libname: str, handle: ctypes.wintypes.HMODULE) -> str: """Get the absolute path of a loaded dynamic library on Windows.""" - try: - return win32api.GetModuleFileName(handle) # type: ignore[no-any-return] - except Exception as e: - raise RuntimeError(f"GetModuleFileName failed for {libname!r} (exception type: {type(e)})") from e + # Create buffer for the path + buffer = ctypes.create_unicode_buffer(260) # MAX_PATH + length = kernel32.GetModuleFileNameW(handle, buffer, len(buffer)) + + if length == 0: + error_code = ctypes.GetLastError() # type: ignore[attr-defined] + raise RuntimeError(f"GetModuleFileNameW failed for {libname!r} (error code: {error_code})") + + # If buffer was too small, try with larger buffer + if length == len(buffer): + buffer = ctypes.create_unicode_buffer(32768) # Extended path length + length = kernel32.GetModuleFileNameW(handle, buffer, len(buffer)) + if length == 0: + error_code = ctypes.GetLastError() # type: ignore[attr-defined] + raise RuntimeError(f"GetModuleFileNameW failed for {libname!r} (error code: {error_code})") + + return buffer.value def check_if_already_loaded_from_elsewhere(libname: str) -> Optional[LoadedDL]: @@ -71,18 +113,14 @@ def check_if_already_loaded_from_elsewhere(libname: str) -> Optional[LoadedDL]: from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import SUPPORTED_WINDOWS_DLLS for dll_name in SUPPORTED_WINDOWS_DLLS.get(libname, ()): - try: - handle = win32api.GetModuleHandle(dll_name) - except pywintypes.error: - continue - else: - return LoadedDL( - abs_path_for_dynamic_library(libname, handle), True, pywintypes_handle_to_unsigned_int(handle) - ) + handle = kernel32.GetModuleHandleW(dll_name) + if handle: + abs_path = abs_path_for_dynamic_library(libname, handle) + return LoadedDL(abs_path, True, ctypes_handle_to_unsigned_int(handle)) return None -def load_with_system_search(libname: str, soname: str) -> Optional[LoadedDL]: +def load_with_system_search(libname: str, _soname: str) -> Optional[LoadedDL]: """Try to load a DLL using system search paths. Args: @@ -95,14 +133,10 @@ def load_with_system_search(libname: str, soname: str) -> Optional[LoadedDL]: from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import SUPPORTED_WINDOWS_DLLS for dll_name in SUPPORTED_WINDOWS_DLLS.get(libname, ()): - try: - handle = win32api.LoadLibraryEx(dll_name, 0, 0) - except pywintypes.error: - continue - else: - return LoadedDL( - abs_path_for_dynamic_library(libname, handle), False, pywintypes_handle_to_unsigned_int(handle) - ) + handle = kernel32.LoadLibraryExW(dll_name, None, 0) + if handle: + abs_path = abs_path_for_dynamic_library(libname, handle) + return LoadedDL(abs_path, False, ctypes_handle_to_unsigned_int(handle)) return None @@ -128,8 +162,10 @@ def load_with_abs_path(libname: str, found_path: str) -> LoadedDL: add_dll_directory(found_path) flags = WINBASE_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | WINBASE_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR - try: - handle = win32api.LoadLibraryEx(found_path, 0, flags) - except pywintypes.error as e: - raise RuntimeError(f"Failed to load DLL at {found_path}: {e}") from e - return LoadedDL(found_path, False, pywintypes_handle_to_unsigned_int(handle)) + handle = kernel32.LoadLibraryExW(found_path, None, flags) + + if not handle: + error_code = ctypes.GetLastError() # type: ignore[attr-defined] + raise RuntimeError(f"Failed to load DLL at {found_path}: Windows error {error_code}") + + return LoadedDL(found_path, False, ctypes_handle_to_unsigned_int(handle)) diff --git a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py index 101088e60..827718753 100644 --- a/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py @@ -5,7 +5,7 @@ import struct import sys -from cuda.pathfinder._dynamic_libs.find_nvidia_dynamic_lib import _find_nvidia_dynamic_lib +from cuda.pathfinder._dynamic_libs.find_nvidia_dynamic_lib import _FindNvidiaDynamicLib from cuda.pathfinder._dynamic_libs.load_dl_common import LoadedDL, load_dependencies from cuda.pathfinder._dynamic_libs.supported_nvidia_libs import IS_WINDOWS @@ -35,7 +35,7 @@ def _load_lib_no_cache(libname: str) -> LoadedDL: load_dependencies(libname, load_nvidia_dynamic_lib) # Find the library path - found = _find_nvidia_dynamic_lib(libname) + found = _FindNvidiaDynamicLib(libname) if found.abs_path is None: loaded = load_with_system_search(libname, found.lib_searched_for) if loaded is not None: diff --git a/cuda_pathfinder/cuda/pathfinder/_utils/find_sub_dirs.py b/cuda_pathfinder/cuda/pathfinder/_utils/find_sub_dirs.py index b05467e52..0b6f06c47 100644 --- a/cuda_pathfinder/cuda/pathfinder/_utils/find_sub_dirs.py +++ b/cuda_pathfinder/cuda/pathfinder/_utils/find_sub_dirs.py @@ -50,4 +50,4 @@ def find_sub_dirs_sys_path(sub_dirs: Sequence[str]) -> list[str]: def find_sub_dirs_all_sitepackages(sub_dirs: Sequence[str]) -> list[str]: - return find_sub_dirs((site.getusersitepackages(),) + tuple(site.getsitepackages()), sub_dirs) + return find_sub_dirs((site.getusersitepackages(), *site.getsitepackages()), sub_dirs) diff --git a/cuda_pathfinder/pyproject.toml b/cuda_pathfinder/pyproject.toml index 5c705cad4..46d477564 100644 --- a/cuda_pathfinder/pyproject.toml +++ b/cuda_pathfinder/pyproject.toml @@ -8,9 +8,7 @@ authors = [{ name = "NVIDIA Corporation", email = "cuda-python-conduct@nvidia.co license = "Apache-2.0" requires-python = ">=3.9" dynamic = ["version"] -dependencies = [ - "pywin32; sys_platform == 'win32'", -] +dependencies = [] [project.optional-dependencies] test = [ @@ -56,18 +54,27 @@ docstring-code-format = true [tool.ruff.lint] select = [ - # pycodestyle Error - "E", - # Pyflakes - "F", - # pycodestyle Warning - "W", - # pyupgrade - "UP", - # flake8-bugbear - "B", - # flake8-simplify - "SIM", - # isort - "I", + "E", # pycodestyle Error + "F", # Pyflakes + "W", # pycodestyle Warning + "UP", # pyupgrade + "B", # flake8-bugbear + "SIM", # flake8-simplify + "I", # isort + "ARG", # flake8-unused-arguments + "Q", # flake8-quotes + "N", # pep8-naming + "C4", # flake8-comprehensions + "PIE", # flake8-pie + "T20", # flake8-print + "RUF", # Ruff-specific rules + "PT", # flake8-pytest-style + "DTZ", # flake8-datetimez ] +extend-select = ["B9"] + +[tool.ruff.lint.flake8-quotes] +inline-quotes = "double" + +[tool.ruff.lint.per-file-ignores] +"tests/**/*" = ["S101"] diff --git a/cuda_pathfinder/tests/conftest.py b/cuda_pathfinder/tests/conftest.py index 1069de59b..cfef9a954 100644 --- a/cuda_pathfinder/tests/conftest.py +++ b/cuda_pathfinder/tests/conftest.py @@ -9,7 +9,7 @@ def pytest_configure(config): config.custom_info = [] -def pytest_terminal_summary(terminalreporter, exitstatus, config): +def pytest_terminal_summary(terminalreporter, exitstatus, config): # noqa: ARG001 if config.custom_info: terminalreporter.write_sep("=", "INFO summary") for msg in config.custom_info: diff --git a/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py b/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py index 31263f7d2..26d8eabec 100644 --- a/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py +++ b/cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py @@ -2,6 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 import os +import sys from unittest.mock import patch import pytest @@ -86,7 +87,7 @@ def child_process_func(libname): if not os.path.samefile(loaded_dl_no_cache.abs_path, loaded_dl_fresh.abs_path): raise RuntimeError(f"not os.path.samefile({loaded_dl_no_cache.abs_path=!r}, {loaded_dl_fresh.abs_path=!r})") - print(f"{loaded_dl_fresh.abs_path!r}") + sys.stdout.write(f"{loaded_dl_fresh.abs_path!r}\n") @pytest.mark.parametrize("libname", SUPPORTED_NVIDIA_LIBNAMES) @@ -99,7 +100,7 @@ def test_load_nvidia_dynamic_lib(info_summary_append, libname): result = spawned_process_runner.run_in_spawned_child_process(child_process_func, args=(libname,), timeout=timeout) if result.returncode == 0: info_summary_append(f"abs_path={result.stdout.rstrip()}") - elif STRICTNESS == "see_what_works" or "DynamicLibNotFound: Failure finding " in result.stderr: + elif STRICTNESS == "see_what_works" or "DynamicLibNotFoundError: Failure finding " in result.stderr: info_summary_append(f"Not found: {libname=!r}") else: raise RuntimeError(build_child_process_failed_for_libname_message(libname, result)) From eedf658020b1befe2de88f2f68dd4efcbe3c04c8 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 11 Jul 2025 16:44:27 -0700 Subject: [PATCH 77/78] Add `cuda-pathfinder` to `options` in .github/workflows/release.yml --- .github/workflows/release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 411bfad10..c483d1be8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,6 +16,7 @@ on: options: - cuda-core - cuda-bindings + - cuda-pathfinder - cuda-python - all git-tag: From 58ca181684671988101dcac68fa7b7d3dfc527aa Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sat, 12 Jul 2025 10:12:20 -0700 Subject: [PATCH 78/78] Move temporary backward compatibility code to _path_finder/temporary_backward_compatibility.py, to fully sanitize path_finder.py --- .../cuda/bindings/_path_finder/README.md | 2 + .../temporary_backward_compatibility.py | 41 +++++++++++++++++ cuda_bindings/cuda/bindings/path_finder.py | 44 +++---------------- 3 files changed, 49 insertions(+), 38 deletions(-) create mode 100644 cuda_bindings/cuda/bindings/_path_finder/temporary_backward_compatibility.py diff --git a/cuda_bindings/cuda/bindings/_path_finder/README.md b/cuda_bindings/cuda/bindings/_path_finder/README.md index d402c935c..fcbdeed8d 100644 --- a/cuda_bindings/cuda/bindings/_path_finder/README.md +++ b/cuda_bindings/cuda/bindings/_path_finder/README.md @@ -1 +1,3 @@ # The `cuda.bindings.path_finder` module was moved → `cuda.pathfinder` + +`cuda.bindings.pathfinder` is slated to be removed after the next `cuda-bindings` release. diff --git a/cuda_bindings/cuda/bindings/_path_finder/temporary_backward_compatibility.py b/cuda_bindings/cuda/bindings/_path_finder/temporary_backward_compatibility.py new file mode 100644 index 000000000..9200db3aa --- /dev/null +++ b/cuda_bindings/cuda/bindings/_path_finder/temporary_backward_compatibility.py @@ -0,0 +1,41 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE + +# This is for TEMPORARY BACKWARD COMPATIBILITY only. +# cuda.bindings.pathfinder is slated to be removed after the next cuda-bindings release. + +from dataclasses import dataclass +from typing import Optional + +from cuda.pathfinder import load_nvidia_dynamic_lib +from cuda.pathfinder._dynamic_libs import supported_nvidia_libs + +if supported_nvidia_libs.IS_WINDOWS: + import pywintypes + + from cuda.pathfinder._dynamic_libs.load_dl_windows import POINTER_ADDRESS_SPACE + + def _unsigned_int_to_pywintypes_handle(handle_uint: int) -> pywintypes.HANDLE: + handle_int = handle_uint - POINTER_ADDRESS_SPACE if handle_uint >= POINTER_ADDRESS_SPACE // 2 else handle_uint + return pywintypes.HANDLE(handle_int) + + HandleType = pywintypes.HANDLE +else: + HandleType = int + + +# Original implementation, before making handle private as _handle_uint. +@dataclass +class LoadedDL: + handle: HandleType # type: ignore[valid-type] + abs_path: Optional[str] + was_already_loaded_from_elsewhere: bool + + +def load_nvidia_dynamic_library(libname: str) -> LoadedDL: + loaded_dl_uint = load_nvidia_dynamic_lib(libname) + if supported_nvidia_libs.IS_WINDOWS: + handle = _unsigned_int_to_pywintypes_handle(loaded_dl_uint._handle_uint) + else: + handle = loaded_dl_uint._handle_uint + return LoadedDL(handle, loaded_dl_uint.abs_path, loaded_dl_uint.was_already_loaded_from_elsewhere) diff --git a/cuda_bindings/cuda/bindings/path_finder.py b/cuda_bindings/cuda/bindings/path_finder.py index 15f37925c..b4d8f622b 100644 --- a/cuda_bindings/cuda/bindings/path_finder.py +++ b/cuda_bindings/cuda/bindings/path_finder.py @@ -1,47 +1,15 @@ # SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE +# This file is for TEMPORARY BACKWARD COMPATIBILITY only. +# cuda.bindings.pathfinder is slated to be removed after the next cuda-bindings release. + +from cuda.bindings._path_finder.temporary_backward_compatibility import ( + load_nvidia_dynamic_library as _load_nvidia_dynamic_library, +) from cuda.pathfinder import SUPPORTED_NVIDIA_LIBNAMES as _SUPPORTED_LIBNAMES -from cuda.pathfinder import load_nvidia_dynamic_lib __all__ = [ "_load_nvidia_dynamic_library", "_SUPPORTED_LIBNAMES", ] - -# All code below this line is for TEMPORARY BACKWARD COMPATIBILITY only. - -from dataclasses import dataclass -from typing import Optional - -from cuda.pathfinder._dynamic_libs import supported_nvidia_libs - -if supported_nvidia_libs.IS_WINDOWS: - import pywintypes - - from cuda.pathfinder._dynamic_libs.load_dl_windows import POINTER_ADDRESS_SPACE - - def _unsigned_int_to_pywintypes_handle(handle_uint: int) -> pywintypes.HANDLE: - handle_int = handle_uint - POINTER_ADDRESS_SPACE if handle_uint >= POINTER_ADDRESS_SPACE // 2 else handle_uint - return pywintypes.HANDLE(handle_int) - - HandleType = pywintypes.HANDLE -else: - HandleType = int - - -# Original implementation, before making handle private as _handle_uint. -@dataclass -class LoadedDL: - handle: HandleType # type: ignore[valid-type] - abs_path: Optional[str] - was_already_loaded_from_elsewhere: bool - - -def _load_nvidia_dynamic_library(libname: str) -> LoadedDL: - loaded_dl_uint = load_nvidia_dynamic_lib(libname) - if supported_nvidia_libs.IS_WINDOWS: - handle = _unsigned_int_to_pywintypes_handle(loaded_dl_uint._handle_uint) - else: - handle = loaded_dl_uint._handle_uint - return LoadedDL(handle, loaded_dl_uint.abs_path, loaded_dl_uint.was_already_loaded_from_elsewhere)