Skip to content

Commit c3ce5e4

Browse files
authored
Merge branch 'main' into traceback
2 parents f367700 + 76bac4e commit c3ce5e4

16 files changed

Lines changed: 36673 additions & 30401 deletions

File tree

‎.github/workflows/ci-pixi-source-test.yml‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,11 @@ defaults:
5252
shell: bash --noprofile --norc -xeuo pipefail {0}
5353

5454
env:
55-
PIXI_VERSION: "v0.66.0" # keep in sync with the version developers run locally
55+
# keep in sync with the version developers run locally. Must be >=0.71.0:
56+
# older pixi re-ran the editable source build on every `pixi run`, recompiling
57+
# all Cython extensions (#2138). The fix (content-addressed source-build cache,
58+
# prefix-dev/pixi#6285 + #6123) also bumps the pixi.lock format to v7.
59+
PIXI_VERSION: "v0.73.0"
5660

5761
jobs:
5862
# ── PR guard: CPU-only build + import + placement smoke ──

‎benchmarks/cuda_bindings/pixi.lock‎

Lines changed: 1286 additions & 621 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎benchmarks/cuda_core/pixi.lock‎

Lines changed: 1052 additions & 287 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎cuda_bindings/pixi.lock‎

Lines changed: 13405 additions & 11417 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎cuda_core/pixi.lock‎

Lines changed: 15667 additions & 13614 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎cuda_pathfinder/cuda/pathfinder/_binaries/find_nvidia_binary_utility.py‎

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33

44
import functools
55
import os
6-
import shutil
76

87
from cuda.pathfinder._binaries import supported_nvidia_binaries
8+
from cuda.pathfinder._utils.ctk_root_canary import CTK_ROOT_CANARY_ANCHOR_LIBNAMES
99
from cuda.pathfinder._utils.env_vars import get_cuda_path_or_home
1010
from cuda.pathfinder._utils.find_sub_dirs import find_sub_dirs_all_sitepackages
1111
from cuda.pathfinder._utils.platform_aware import IS_WINDOWS
@@ -28,6 +28,45 @@ def _normalize_utility_name(utility_name: str) -> str:
2828
return utility_name
2929

3030

31+
def _is_executable_candidate(path: str) -> bool:
32+
if not os.path.isfile(path):
33+
return False
34+
if IS_WINDOWS:
35+
return True
36+
return os.access(path, os.X_OK)
37+
38+
39+
def _ctk_bin_subdirs(root: str) -> list[str]:
40+
if IS_WINDOWS:
41+
return [
42+
os.path.join(root, "bin", "x64"),
43+
os.path.join(root, "bin", "x86_64"),
44+
os.path.join(root, "bin"),
45+
]
46+
return [os.path.join(root, "bin")]
47+
48+
49+
def _resolve_ctk_root_via_canary() -> str | None:
50+
from cuda.pathfinder._dynamic_libs.load_nvidia_dynamic_lib import resolve_ctk_root_via_canary
51+
52+
ctk_root: str | None = resolve_ctk_root_via_canary(CTK_ROOT_CANARY_ANCHOR_LIBNAMES[0])
53+
return ctk_root
54+
55+
56+
def _resolve_in_trusted_dirs(normalized_name: str, dirs: list[str]) -> str | None:
57+
"""Resolve ``normalized_name`` against ``dirs`` in order."""
58+
seen: set[str] = set()
59+
for directory in dirs:
60+
if directory in seen:
61+
continue
62+
assert directory
63+
seen.add(directory)
64+
candidate = os.path.join(directory, normalized_name)
65+
if _is_executable_candidate(candidate):
66+
return candidate
67+
return None
68+
69+
3170
@functools.cache
3271
def find_nvidia_binary_utility(utility_name: str) -> str | None:
3372
"""Locate a CUDA binary utility executable.
@@ -65,6 +104,12 @@ def find_nvidia_binary_utility(utility_name: str) -> str | None:
65104
``bin/x64``, ``bin/x86_64``, and ``bin`` subdirectories on Windows,
66105
or just ``bin`` on Linux.
67106
107+
4. **CTK-root canary fallback**
108+
109+
- Only when steps 1-3 miss: resolve the ``cudart`` library through the
110+
OS dynamic loader, derive the CUDA Toolkit root from it, and search
111+
that root's bin layout.
112+
68113
Note:
69114
Results are cached using ``@functools.cache`` for performance. The cache
70115
persists for the lifetime of the process.
@@ -73,6 +118,9 @@ def find_nvidia_binary_utility(utility_name: str) -> str | None:
73118
(``.exe``, ``.bat``, ``.cmd``). On Unix-like systems, executables
74119
are identified by the ``X_OK`` (execute) permission bit.
75120
121+
Lookup is restricted to the trusted directories and the canary-derived
122+
CTK root listed above.
123+
76124
Example:
77125
>>> from cuda.pathfinder import find_nvidia_binary_utility
78126
>>> nvdisasm = find_nvidia_binary_utility("nvdisasm")
@@ -98,10 +146,15 @@ def find_nvidia_binary_utility(utility_name: str) -> str | None:
98146

99147
# 3. Search in CUDA Toolkit (CUDA_HOME/CUDA_PATH)
100148
if (cuda_home := get_cuda_path_or_home()) is not None:
101-
if IS_WINDOWS:
102-
dirs.append(os.path.join(cuda_home, "bin", "x64"))
103-
dirs.append(os.path.join(cuda_home, "bin", "x86_64"))
104-
dirs.append(os.path.join(cuda_home, "bin"))
149+
dirs.extend(_ctk_bin_subdirs(cuda_home))
105150

106151
normalized_name = _normalize_utility_name(utility_name)
107-
return shutil.which(normalized_name, path=os.pathsep.join(dirs))
152+
found = _resolve_in_trusted_dirs(normalized_name, dirs)
153+
if found is not None:
154+
return found
155+
156+
# 4. CTK-root canary fallback.
157+
ctk_root = _resolve_ctk_root_via_canary()
158+
if ctk_root is not None:
159+
return _resolve_in_trusted_dirs(normalized_name, _ctk_bin_subdirs(ctk_root))
160+
return None

‎cuda_pathfinder/cuda/pathfinder/_dynamic_libs/descriptor_catalog.py‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
from dataclasses import dataclass
99
from typing import Literal
1010

11+
from cuda.pathfinder._utils.ctk_root_canary import CTK_ROOT_CANARY_ANCHOR_LIBNAMES
12+
1113
PackagedWith = Literal["ctk", "other", "driver"]
1214

1315

@@ -73,7 +75,7 @@ class DescriptorSpec:
7375
site_packages_windows=("nvidia/cu13/bin/x86_64", "nvidia/cuda_nvcc/nvvm/bin"),
7476
anchor_rel_dirs_linux=("nvvm/lib64",),
7577
anchor_rel_dirs_windows=("nvvm/bin/*", "nvvm/bin"),
76-
ctk_root_canary_anchor_libnames=("cudart",),
78+
ctk_root_canary_anchor_libnames=CTK_ROOT_CANARY_ANCHOR_LIBNAMES,
7779
),
7880
DescriptorSpec(
7981
name="cublas",
@@ -292,7 +294,7 @@ class DescriptorSpec:
292294
site_packages_windows=("nvidia/cu13/bin/x86_64", "nvidia/cuda_cupti/bin"),
293295
anchor_rel_dirs_linux=("extras/CUPTI/lib64", "lib"),
294296
anchor_rel_dirs_windows=("extras/CUPTI/lib64", "bin"),
295-
ctk_root_canary_anchor_libnames=("cudart",),
297+
ctk_root_canary_anchor_libnames=CTK_ROOT_CANARY_ANCHOR_LIBNAMES,
296298
),
297299
DescriptorSpec(
298300
name="cudla",

‎cuda_pathfinder/cuda/pathfinder/_dynamic_libs/load_nvidia_dynamic_lib.py‎

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,26 @@ def _loadable_via_canary_subprocess(libname: str, *, timeout: float = _CANARY_PR
136136
return _resolve_system_loaded_abs_path_in_subprocess(libname, timeout=timeout) is not None
137137

138138

139+
def resolve_ctk_root_via_canary(canary_libname: str) -> str | None:
140+
"""Resolve the CUDA Toolkit root from a system-loadable canary library.
141+
142+
The canary library's absolute path is resolved by the OS dynamic loader in
143+
an isolated subprocess, which honors ``LD_LIBRARY_PATH`` on Linux and the
144+
native DLL search on Windows. The toolkit root is then derived from that
145+
path. Returns ``None`` if the canary cannot be resolved or no root can be
146+
derived.
147+
"""
148+
canary_abs_path = _resolve_system_loaded_abs_path_in_subprocess(canary_libname)
149+
if canary_abs_path is None:
150+
return None
151+
ctk_root: str | None = derive_ctk_root(canary_abs_path)
152+
return ctk_root
153+
154+
139155
def _try_ctk_root_canary(ctx: SearchContext) -> str | None:
140156
"""Try CTK-root canary fallback for descriptor-configured libraries."""
141157
for canary_libname in ctx.desc.ctk_root_canary_anchor_libnames:
142-
canary_abs_path = _resolve_system_loaded_abs_path_in_subprocess(canary_libname)
143-
if canary_abs_path is None:
144-
continue
145-
ctk_root = derive_ctk_root(canary_abs_path)
158+
ctk_root = resolve_ctk_root_via_canary(canary_libname)
146159
if ctk_root is None:
147160
continue
148161
find = find_via_ctk_root(ctx, ctk_root)

‎cuda_pathfinder/cuda/pathfinder/_headers/find_nvidia_headers.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
platform_include_subdirs,
2020
resolve_conda_anchor,
2121
)
22+
from cuda.pathfinder._utils.ctk_root_canary import CTK_ROOT_CANARY_ANCHOR_LIBNAMES
2223
from cuda.pathfinder._utils.env_vars import get_cuda_path_or_home
2324
from cuda.pathfinder._utils.find_sub_dirs import find_sub_dirs_all_sitepackages
2425

@@ -121,7 +122,7 @@ def find_via_ctk_root_canary(desc: HeaderDescriptor) -> LocatedHeaderDir | None:
121122
"""
122123
if not desc.use_ctk_root_canary:
123124
return None
124-
canary_abs_path = _resolve_system_loaded_abs_path_in_subprocess("cudart")
125+
canary_abs_path = _resolve_system_loaded_abs_path_in_subprocess(CTK_ROOT_CANARY_ANCHOR_LIBNAMES[0])
125126
if canary_abs_path is None:
126127
return None
127128
ctk_root = derive_ctk_root(canary_abs_path)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
CTK_ROOT_CANARY_ANCHOR_LIBNAMES = ("cudart",)

0 commit comments

Comments
 (0)