Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
fbdebfa
Move files WITHOUT trying to make anything work.
rwgk Jun 22, 2025
731256d
First pass changing imports from cuda.bindings → cuda.path_finder WIT…
rwgk Jun 22, 2025
6e0ec6c
Move README.md one level up.
rwgk Jun 22, 2025
07e1385
Move find_sub_dirs.py → ../_utils/find_sub_dirs.py
rwgk Jun 22, 2025
68aa8d5
Move files from cuda_bindings/tests to cuda_path_finder/tests WITHOUT…
rwgk Jun 22, 2025
fafa998
First VERY ROUGH version of pyproject.toml
rwgk Jun 22, 2025
4eff7d2
Change imports in tests/ WITHOUT trying to make anything work.
rwgk Jun 22, 2025
db0f540
Clean up pyproject.toml (with the help of ChatGPT) WITHOUT trying to …
rwgk Jun 22, 2025
9fea2e7
ruff automatic fix: Replace deprecated typing.Sequence with collectio…
rwgk Jun 22, 2025
c494ef2
Add `dynamic = ["version"]` in pyproject.toml and cuda/path_finder/__…
rwgk Jun 23, 2025
78b8c6d
Modernize `[project] license` line.
rwgk Jun 23, 2025
5690d96
Change dir/file names: path_finder → pathfinder
rwgk Jun 23, 2025
81b9bd9
Change imports: path_finder → pathfinder
rwgk Jun 23, 2025
b9be5cb
Fix up broken imports.
rwgk Jun 23, 2025
79a8019
add [project.optional-dependencies] test
rwgk Jun 23, 2025
975ba0b
Adopt cuda_core license.
rwgk Jun 25, 2025
3678fb4
cuda.pathfinder.nvidia_dynamic_libs.load_lib → cuda.pathfinder.load_n…
rwgk Jun 25, 2025
c25184e
Merge branch 'main' into move_path_finder_to_top
rwgk Jul 1, 2025
58b2513
Revert "cuda.pathfinder.nvidia_dynamic_libs.load_lib → cuda.pathfinde…
rwgk Jul 1, 2025
050f857
Simple name changes for consistency: library -> lib
rwgk Jul 1, 2025
1933869
Implement consensus API
rwgk Jul 1, 2025
50f4f8e
Use suggested version number 0.1.0
rwgk Jul 1, 2025
787236c
Fix oversight: `license =` line in pyproject.toml
rwgk Jul 1, 2025
5b5078b
Simplify `description =` line in pyproject.toml
rwgk Jul 1, 2025
13e08ae
Remove Maintenance Requirements from main README. Add the list of "Li…
rwgk Jul 1, 2025
97f9dc8
Adjust cuda_bindings/cuda/bindings/path_finder.py to changes in cuda_…
rwgk Jul 1, 2025
e18cf05
First guess at what changes are needed to include cuda_pathfinder in …
rwgk Jul 1, 2025
b015bbe
Merge branch 'main' into move_path_finder_to_top
rwgk Jul 2, 2025
36491c8
git mv nvidia_dynamic_libs.py __init__.py
rwgk Jul 2, 2025
c6187db
Do not use `cibuildwheel` for a `noarch` package (`cuda-pathfinder`).…
rwgk Jul 2, 2025
346e8b9
twine cleanup
rwgk Jul 2, 2025
9207966
Hard-wire cuda-pathfinder artifact name and path for simplicity, simi…
rwgk Jul 2, 2025
3682f7d
Change to __version__ = "1.0.0"
rwgk Jul 2, 2025
7742c5c
Import __version__ in cuda/pathfinder/__init__.py
rwgk Jul 2, 2025
92c8441
Add missing line in step `name: List the cuda.pathfinder artifacts di…
rwgk Jul 2, 2025
a5b7190
`Install cuda.pathfinder` before ` Build cuda.bindings Cython tests`
rwgk Jul 2, 2025
db0ea56
Add missing line in step `name: Check cuda.pathfinder wheel`
rwgk Jul 3, 2025
9a9f1d7
fix build workflow
leofang Jul 3, 2025
aac1cf7
Merge branch 'main' into move_path_finder_to_top
rwgk Jul 3, 2025
989db08
Remove `__all__` in cuda/pathfinder/__init__.py
rwgk Jul 3, 2025
222df6c
Fix `Check if the script was called with exactly 1 argument` implemen…
rwgk Jul 3, 2025
0b8af00
Add pathfinder install & test into ci/tools/run-tests
rwgk Jul 3, 2025
f902dc9
Add Download cuda-pathfinder, Run cuda.pathfinder tests in test-whee…
rwgk Jul 3, 2025
481f8de
Download cuda-pathfinder-wheel into `./cuda_pathfinder` (not `.`)
rwgk Jul 3, 2025
fd18e1e
Run cuda.pathfinder tests only after cuda.bindings tests, so that all…
rwgk Jul 3, 2025
796bd46
Drive-by fix: test_find_or_load → test_load
rwgk Jul 3, 2025
06763af
Introduce CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS env…
rwgk Jul 3, 2025
b2135cf
CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS=supported_mus…
rwgk Jul 3, 2025
bf48142
Add cuda-pathfinder in .github/workflows/build-docs.yml
rwgk Jul 3, 2025
135a37d
Remove 32-bit DLLs from SUPPORTED_WINDOWS_DLLS
rwgk Jul 5, 2025
48c6d63
Add guard: RuntimeError: cuda.pathfinder.load_nvidia_dynamic_lib() r…
rwgk Jul 5, 2025
7ab201a
is_suppressed_dll_file(): return path_basename.startswith(("cudart32_…
rwgk Jul 5, 2025
9f3e9a4
Add nvidia_wheels_cu12 to [project.optional-dependencies] in cuda_pat…
rwgk Jul 5, 2025
00c8b6a
Install cuda.pathfinder nvidia_wheels_cu12 and run-tests pathfinder a…
rwgk Jul 5, 2025
034286a
ci/tools/run-tests: use bash `-v` instead of `-z` to test if CUDA_PAT…
rwgk Jul 6, 2025
aaed5f2
Add missing `shell: bash` line in test-wheel-windows.yml
rwgk Jul 6, 2025
9d8c70c
test_load_nvidia_dynamic_lib: increase timeout to 120 seconds for Win…
rwgk Jul 6, 2025
8440f90
Add test_load_nvidia_dynamic_lib::test_runtime_error_on_non_64bit_python
rwgk Jul 6, 2025
98ae874
Add DynamicLibNotFound exception type in load_dl_common.py and simpli…
rwgk Jul 6, 2025
9686c2f
Run cuda.pathfinder tests with see_what_works before running any othe…
rwgk Jul 6, 2025
f3c0006
Use `if: startsWith(matrix.CUDA_VER, 12.)` to guard pathfinder tests …
rwgk Jul 6, 2025
8f015d2
Get rid of "partially supported" concept.
rwgk Jul 6, 2025
9f17cd1
Consistently use `IS_WINDOWS` (instead of `sys.platform == "win32"`).
rwgk Jul 6, 2025
db7933a
Rename toolshed/build_pathfinder*.py scripts (no functional changes).
rwgk Jul 6, 2025
1b9a929
Rename toolshed/run_cuda_pathfinder.py
rwgk Jul 6, 2025
b69bf23
Make output of toolshed/build_pathfinder_dlls.py usable as-is.
rwgk Jul 6, 2025
80ebbda
Add DynamicLibNotFound to cuda/pathfinder/__init__.py
rwgk Jul 7, 2025
1c8d315
Merge branch 'move_path_finder_to_top' of https://github.com/rwgk/cud…
rwgk Jul 7, 2025
52e1369
Fix accident in previous commit (DynamicLibNotFound)
rwgk Jul 7, 2025
70d1c14
Update README.md
rwgk Jul 7, 2025
342ca49
mypy cleanup
rwgk Jul 7, 2025
4e0033c
Run mypy from pre-commit
rwgk Jul 7, 2025
74ef126
Use SHA for mypy version in .pre-commit-config.yaml (generated with `…
rwgk Jul 7, 2025
5e85328
cuda_bindings/pyproject.toml: constrain "cuda-pathfinder ~= 1.0"
rwgk Jul 7, 2025
46fd972
Make LoadedDL.handle an unsigned integer also for Windows. (cuda_path…
rwgk Jul 9, 2025
428a2dc
Rename LoadedDL.handle → LoadedDL._handle_uint
rwgk Jul 9, 2025
4096885
Move `_handle_uint` last in `LoadedDL`, to emphasize that this is pri…
rwgk Jul 9, 2025
5e6c7e5
Implement TEMPORARY BACKWARD COMPATIBILITY in /cuda/bindings/path_fin…
rwgk Jul 9, 2025
d787a4c
Fix oversight discovered via local Windows testing.
rwgk Jul 9, 2025
60918d5
Merge branch 'main' into move_path_finder_to_top
rwgk Jul 9, 2025
933a889
Merge branch 'main' into move_path_finder_to_top
rwgk Jul 11, 2025
c0509be
Put the changes from https://github.com/NVIDIA/cuda-python/pull/751 o…
rwgk Jul 11, 2025
eedf658
Add `cuda-pathfinder` to `options` in .github/workflows/release.yml
rwgk Jul 11, 2025
58ca181
Move temporary backward compatibility code to _path_finder/temporary_…
rwgk Jul 12, 2025
b73f421
Consolidate mypy configuration into pyproject.toml
rwgk Jul 14, 2025
88c4ebc
Change "slated" to "deprecated and slated ... in the next ... major v…
rwgk Jul 14, 2025
ee19b0c
Remove mention of LoadedDL handle in README.md (it was an oversight t…
rwgk Jul 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cuda_bindings/cuda/bindings/path_finder.py
Original file line number Diff line number Diff line change
@@ -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
Comment thread
kkraus14 marked this conversation as resolved.
Outdated

__all__ = [
"_load_nvidia_dynamic_library",
Expand Down
23 changes: 23 additions & 0 deletions cuda_pathfinder/cuda/pathfinder/__init__.py
Original file line number Diff line number Diff line change
@@ -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)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could define this wrapper function in the _dynamic_libs module and just import it here. This way your __init__.py here wouldn't have a ton of function definitions.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is meant to be the public API in one view.

This way your __init__.py here wouldn't have a ton of function definitions.

I understood exactly that was your goal: a flat list of available APIs.

Note that I moved the docstring here.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is meant to be the public API in one view.

Indeed, everything we define (or import) here that is not prefixed with _ constitutes the public API of the module cuda.path_finder. My above suggestion is just that we import load_nvidia_dynamic_lib rather than define it here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would make the public API far less obvious. E.g. to see the docstring, they'd need to open a private file.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that's true. They could still do:

from cuda.path_finder import load_nvidia_dynamic_lib
help(load_nvidia_dynamic_lib)

Same as they would do now?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That'll only work interactively.

What I have now can be inspected in obvious ways directly in the sources, e.g. when looking at the sources on github. I can send URLs pointing to specific APIs in this init.py file.

Each function here will just be:

def function(...) -> ...:
    """docstring""
    return call_into_private_code(...)

That's exactly the public API, with a one-line call that's easy to ignore.

What's the point of hiding that away, especially hiding away the docstring and the type hints?

Copy link
Copy Markdown
Contributor

@shwina shwina Jun 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That'll only work interactively.

The docstrings and type hints would also get picked up:

  • Sphinx (which we use to generate API docs
    -pydoc
  • the developers' IDEs/lsp

Those are primarily the ways consumers of a package interact with docstrings or type hints, rather than looking directly at the source.

What's the point of hiding that away, especially hiding away the docstring and the type hints?

It tightens the scope of __init__.py, whose job is:

  • to include any initialization code for the module
  • to import stuff from submodules that the module wants to expose
  • to define __all__ for the module if needed

As examples, we can look at the __init__.py from some other popular libraries:

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It tightens the scope of init.py, whose job is

The most important job: Show the public API

You didn't answer why you want to hide that away.

Copy link
Copy Markdown
Contributor

@shwina shwina Jun 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm advocating for keeping function and type definitions outside of __init__.py. I don't think that "hides" anything from the user as we still import them here.

The main reason I'm advocating for that is because __init__.py typically only defines functions and types needed for module initialization, and imports anything else. I think the examples I linked to above are a good demonstration of that.

Defining functions and types beyond that serves to clutter __init__.py.

I would argue it makes the code base less navigable than more for people looking at the source. Do I expect the function load_nvidia_dynamic_libs to be defined in a file called _dynamic_libs.py, or a file called __init__.py?

If this all seems nitpicky, I apologize. While I do have a strong opinion here, I don't mind at all if another reviewer (or you, as the author of this PR) made the final call about this.

Copy link
Copy Markdown
Member

@leofang leofang Jun 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cuda.core's __init__.py is a good example for what Ashwin suggested. As a developer who occasionally peeks into someone else's __init__.py, I certainly get confused why we are defining things in there directly, as opposed to properly organizing them in respective public/private modules, and just import them. What's imported are considered public APIs (including types). Does it make sense?

Original file line number Diff line number Diff line change
Expand Up @@ -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)
7 changes: 0 additions & 7 deletions cuda_pathfinder/cuda/pathfinder/nvidia_dynamic_libs.py

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -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():
Expand Down Expand Up @@ -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")

Expand All @@ -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
Expand Down