Skip to content

Commit b8cc00d

Browse files
authored
Merge branch 'main' into rparolin/cuda.core.hashable
2 parents 8227c21 + 9769bc7 commit b8cc00d

14 files changed

+246
-99
lines changed

cuda_pathfinder/cuda/pathfinder/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from cuda.pathfinder._headers.supported_nvidia_headers import SUPPORTED_HEADERS_CTK as _SUPPORTED_HEADERS_CTK
1414
from cuda.pathfinder._version import __version__ as __version__
1515

16-
# Indirection to help Sphinx find the docstring.
16+
# Indirections to help Sphinx find the docstrings.
1717
#: Mapping from short CUDA Toolkit (CTK) library names to their canonical
1818
#: header basenames (used to validate a discovered include directory).
1919
#: Example: ``"cublas" → "cublas.h"``. The key set is platform-aware

cuda_pathfinder/cuda/pathfinder/_dynamic_libs/supported_nvidia_libs.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,11 @@
8282
}
8383
DIRECT_DEPENDENCIES = DIRECT_DEPENDENCIES_CTK | {
8484
"mathdx": ("nvrtc",),
85+
"cublasmp": ("cublas", "cublasLt", "nvshmem_host"),
8586
"cufftMp": ("nvshmem_host",),
8687
"cudss": ("cublas", "cublasLt"),
88+
"cutensor": ("cublasLt",),
89+
"cutensorMg": ("cutensor", "cublasLt"),
8790
}
8891

8992
# Based on these released files:
@@ -238,9 +241,11 @@
238241
}
239242
SUPPORTED_LINUX_SONAMES_OTHER = {
240243
"cublasmp": ("libcublasmp.so.0",),
241-
"cufftMp": ("libcufftMp.so.11",),
244+
"cufftMp": ("libcufftMp.so.12", "libcufftMp.so.11"),
242245
"mathdx": ("libmathdx.so.0",),
243246
"cudss": ("libcudss.so.0",),
247+
"cutensor": ("libcutensor.so.2",),
248+
"cutensorMg": ("libcutensorMg.so.2",),
244249
"nccl": ("libnccl.so.2",),
245250
"nvpl_fftw": ("libnvpl_fftw.so.0",),
246251
"nvshmem_host": ("libnvshmem_host.so.3",),
@@ -402,6 +407,8 @@
402407
SUPPORTED_WINDOWS_DLLS_OTHER = {
403408
"mathdx": ("mathdx64_0.dll",),
404409
"cudss": ("cudss64_0.dll",),
410+
"cutensor": ("cutensor.dll",),
411+
"cutensorMg": ("cutensorMg.dll",),
405412
}
406413
SUPPORTED_WINDOWS_DLLS = SUPPORTED_WINDOWS_DLLS_CTK | SUPPORTED_WINDOWS_DLLS_OTHER
407414

@@ -446,7 +453,9 @@
446453
SITE_PACKAGES_LIBDIRS_LINUX_OTHER = {
447454
"cublasmp": ("nvidia/cublasmp/cu13/lib", "nvidia/cublasmp/cu12/lib"),
448455
"cudss": ("nvidia/cu13/lib", "nvidia/cu12/lib"),
449-
"cufftMp": ("nvidia/cufftmp/cu12/lib",),
456+
"cufftMp": ("nvidia/cufftmp/cu13/lib", "nvidia/cufftmp/cu12/lib"),
457+
"cutensor": ("cutensor/lib",),
458+
"cutensorMg": ("cutensor/lib",),
450459
"mathdx": ("nvidia/cu13/lib", "nvidia/cu12/lib"),
451460
"nccl": ("nvidia/nccl/lib",),
452461
"nvpl_fftw": ("nvpl/lib",),
@@ -484,7 +493,10 @@
484493
"nvvm": ("nvidia/cu13/bin/x86_64", "nvidia/cuda_nvcc/nvvm/bin"),
485494
}
486495
SITE_PACKAGES_LIBDIRS_WINDOWS_OTHER = {
496+
"cudss": ("nvidia/cu13/bin", "nvidia/cu12/bin"),
487497
"mathdx": ("nvidia/cu13/bin/x86_64", "nvidia/cu12/bin"),
498+
"cutensor": ("cutensor/bin",),
499+
"cutensorMg": ("cutensor/bin",),
488500
}
489501
SITE_PACKAGES_LIBDIRS_WINDOWS = SITE_PACKAGES_LIBDIRS_WINDOWS_CTK | SITE_PACKAGES_LIBDIRS_WINDOWS_OTHER
490502

cuda_pathfinder/cuda/pathfinder/_headers/find_nvidia_headers.py

Lines changed: 50 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -22,28 +22,12 @@ def _joined_isfile(dirpath: str, basename: str) -> bool:
2222
return os.path.isfile(os.path.join(dirpath, basename))
2323

2424

25-
def _find_nvshmem_header_directory() -> Optional[str]:
26-
if IS_WINDOWS:
27-
# nvshmem has no Windows support.
28-
return None
29-
25+
def _find_under_site_packages(sub_dir: str, h_basename: str) -> Optional[str]:
3026
# Installed from a wheel
31-
nvidia_sub_dirs = ("nvidia", "nvshmem", "include")
3227
hdr_dir: str # help mypy
33-
for hdr_dir in find_sub_dirs_all_sitepackages(nvidia_sub_dirs):
34-
if _joined_isfile(hdr_dir, "nvshmem.h"):
35-
return hdr_dir
36-
37-
conda_prefix = os.environ.get("CONDA_PREFIX")
38-
if conda_prefix and os.path.isdir(conda_prefix):
39-
hdr_dir = os.path.join(conda_prefix, "include")
40-
if _joined_isfile(hdr_dir, "nvshmem.h"):
41-
return hdr_dir
42-
43-
for hdr_dir in sorted(glob.glob("/usr/include/nvshmem_*"), reverse=True):
44-
if _joined_isfile(hdr_dir, "nvshmem.h"):
28+
for hdr_dir in find_sub_dirs_all_sitepackages(tuple(sub_dir.split("/"))):
29+
if _joined_isfile(hdr_dir, h_basename):
4530
return hdr_dir
46-
4731
return None
4832

4933

@@ -54,6 +38,13 @@ def _find_based_on_ctk_layout(libname: str, h_basename: str, anchor_point: str)
5438
parts.append("include")
5539
idir = os.path.join(*parts)
5640
if libname == "cccl":
41+
if IS_WINDOWS:
42+
cdir_ctk12 = os.path.join(idir, "targets", "x64") # conda has this anomaly
43+
cdir_ctk13 = os.path.join(cdir_ctk12, "cccl")
44+
if _joined_isfile(cdir_ctk13, h_basename):
45+
return cdir_ctk13
46+
if _joined_isfile(cdir_ctk12, h_basename):
47+
return cdir_ctk12
5748
cdir = os.path.join(idir, "cccl") # CTK 13
5849
if _joined_isfile(cdir, h_basename):
5950
return cdir
@@ -62,38 +53,40 @@ def _find_based_on_ctk_layout(libname: str, h_basename: str, anchor_point: str)
6253
return None
6354

6455

65-
def _find_based_on_conda_layout(libname: str, h_basename: str, conda_prefix: str) -> Optional[str]:
56+
def _find_based_on_conda_layout(libname: str, h_basename: str, ctk_layout: bool) -> Optional[str]:
57+
conda_prefix = os.environ.get("CONDA_PREFIX")
58+
if not conda_prefix:
59+
return None
6660
if IS_WINDOWS:
6761
anchor_point = os.path.join(conda_prefix, "Library")
6862
if not os.path.isdir(anchor_point):
6963
return None
7064
else:
71-
targets_include_path = glob.glob(os.path.join(conda_prefix, "targets", "*", "include"))
72-
if not targets_include_path:
73-
return None
74-
if len(targets_include_path) != 1:
75-
# Conda does not support multiple architectures.
76-
# QUESTION(PR#956): Do we want to issue a warning?
77-
return None
78-
anchor_point = os.path.dirname(targets_include_path[0])
65+
if ctk_layout:
66+
targets_include_path = glob.glob(os.path.join(conda_prefix, "targets", "*", "include"))
67+
if not targets_include_path:
68+
return None
69+
if len(targets_include_path) != 1:
70+
# Conda does not support multiple architectures.
71+
# QUESTION(PR#956): Do we want to issue a warning?
72+
return None
73+
include_path = targets_include_path[0]
74+
else:
75+
include_path = os.path.join(conda_prefix, "include")
76+
anchor_point = os.path.dirname(include_path)
7977
return _find_based_on_ctk_layout(libname, h_basename, anchor_point)
8078

8179

8280
def _find_ctk_header_directory(libname: str) -> Optional[str]:
8381
h_basename = supported_nvidia_headers.SUPPORTED_HEADERS_CTK[libname]
8482
candidate_dirs = supported_nvidia_headers.SUPPORTED_SITE_PACKAGE_HEADER_DIRS_CTK[libname]
8583

86-
# Installed from a wheel
8784
for cdir in candidate_dirs:
88-
hdr_dir: str # help mypy
89-
for hdr_dir in find_sub_dirs_all_sitepackages(tuple(cdir.split("/"))):
90-
if _joined_isfile(hdr_dir, h_basename):
91-
return hdr_dir
85+
if hdr_dir := _find_under_site_packages(cdir, h_basename):
86+
return hdr_dir
9287

93-
conda_prefix = os.environ.get("CONDA_PREFIX")
94-
if conda_prefix: # noqa: SIM102
95-
if result := _find_based_on_conda_layout(libname, h_basename, conda_prefix):
96-
return result
88+
if hdr_dir := _find_based_on_conda_layout(libname, h_basename, True):
89+
return hdr_dir
9790

9891
cuda_home = get_cuda_home_or_path()
9992
if cuda_home: # noqa: SIM102
@@ -132,19 +125,28 @@ def find_nvidia_header_directory(libname: str) -> Optional[str]:
132125
3. **CUDA Toolkit environment variables**
133126
134127
- Use ``CUDA_HOME`` or ``CUDA_PATH`` (in that order).
135-
136-
Notes:
137-
- The ``SUPPORTED_HEADERS_CTK`` dictionary maps each supported CUDA Toolkit
138-
(CTK) library to the name of its canonical header (e.g., ``"cublas" →
139-
"cublas.h"``). This is used to verify that the located directory is valid.
140-
141-
- The only supported non-CTK library at present is ``nvshmem``.
142128
"""
143129

144-
if libname == "nvshmem":
145-
return _abs_norm(_find_nvshmem_header_directory())
146-
147130
if libname in supported_nvidia_headers.SUPPORTED_HEADERS_CTK:
148131
return _abs_norm(_find_ctk_header_directory(libname))
149132

150-
raise RuntimeError(f"UNKNOWN {libname=}")
133+
h_basename = supported_nvidia_headers.SUPPORTED_HEADERS_NON_CTK.get(libname)
134+
if h_basename is None:
135+
raise RuntimeError(f"UNKNOWN {libname=}")
136+
137+
candidate_dirs = supported_nvidia_headers.SUPPORTED_SITE_PACKAGE_HEADER_DIRS_NON_CTK.get(libname, [])
138+
hdr_dir: Optional[str] # help mypy
139+
for cdir in candidate_dirs:
140+
if hdr_dir := _find_under_site_packages(cdir, h_basename):
141+
return _abs_norm(hdr_dir)
142+
143+
if hdr_dir := _find_based_on_conda_layout(libname, h_basename, False):
144+
return _abs_norm(hdr_dir)
145+
146+
candidate_dirs = supported_nvidia_headers.SUPPORTED_INSTALL_DIRS_NON_CTK.get(libname, [])
147+
for cdir in candidate_dirs:
148+
for hdr_dir in sorted(glob.glob(cdir), reverse=True):
149+
if _joined_isfile(hdr_dir, h_basename):
150+
return _abs_norm(hdr_dir)
151+
152+
return None

cuda_pathfinder/cuda/pathfinder/_headers/supported_nvidia_headers.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,28 @@
5757
"nvrtc": ("nvidia/cu13/include", "nvidia/cuda_nvrtc/include"),
5858
"nvvm": ("nvidia/cu13/include", "nvidia/cuda_nvcc/nvvm/include"),
5959
}
60+
61+
SUPPORTED_HEADERS_NON_CTK_COMMON = {
62+
"cutensor": "cutensor.h",
63+
}
64+
SUPPORTED_HEADERS_NON_CTK_LINUX_ONLY = {
65+
"nvshmem": "nvshmem.h",
66+
}
67+
SUPPORTED_HEADERS_NON_CTK_WINDOWS_ONLY: Final[dict[str, str]] = {}
68+
SUPPORTED_HEADERS_NON_CTK_LINUX = SUPPORTED_HEADERS_NON_CTK_COMMON | SUPPORTED_HEADERS_NON_CTK_LINUX_ONLY
69+
SUPPORTED_HEADERS_NON_CTK_WINDOWS = SUPPORTED_HEADERS_NON_CTK_COMMON | SUPPORTED_HEADERS_NON_CTK_WINDOWS_ONLY
70+
SUPPORTED_HEADERS_NON_CTK_ALL = (
71+
SUPPORTED_HEADERS_NON_CTK_COMMON | SUPPORTED_HEADERS_NON_CTK_LINUX_ONLY | SUPPORTED_HEADERS_NON_CTK_WINDOWS_ONLY
72+
)
73+
SUPPORTED_HEADERS_NON_CTK: Final[dict[str, str]] = (
74+
SUPPORTED_HEADERS_NON_CTK_WINDOWS if IS_WINDOWS else SUPPORTED_HEADERS_NON_CTK_LINUX
75+
)
76+
77+
SUPPORTED_SITE_PACKAGE_HEADER_DIRS_NON_CTK = {
78+
"cutensor": ("cutensor/include",),
79+
"nvshmem": ("nvidia/nvshmem/include",),
80+
}
81+
82+
SUPPORTED_INSTALL_DIRS_NON_CTK = {
83+
"nvshmem": ("/usr/include/nvshmem_*",),
84+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
22
# SPDX-License-Identifier: Apache-2.0
33

4-
__version__ = "1.3.1"
4+
__version__ = "1.3.2"

cuda_pathfinder/docs/nv-versions.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
"version": "latest",
44
"url": "https://nvidia.github.io/cuda-python/cuda-pathfinder/latest/"
55
},
6+
{
7+
"version": "1.3.2",
8+
"url": "https://nvidia.github.io/cuda-python/cuda-pathfinder/1.3.2/"
9+
},
610
{
711
"version": "1.3.1",
812
"url": "https://nvidia.github.io/cuda-python/cuda-pathfinder/1.3.1/"

cuda_pathfinder/docs/source/api.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@ and experimental APIs for locating NVIDIA C/C++ header directories.
1818
DynamicLibNotFoundError
1919

2020
SUPPORTED_HEADERS_CTK
21+
SUPPORTED_HEADERS_NON_CTK
2122
find_nvidia_header_directory
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
.. SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
.. SPDX-License-Identifier: Apache-2.0
3+
4+
.. py:currentmodule:: cuda.pathfinder
5+
6+
``cuda-pathfinder`` 1.3.2 Release notes
7+
=======================================
8+
9+
Released on Oct 29, 2025
10+
11+
Highlights
12+
----------
13+
14+
* Add cuTENSOR support & bug fixes discovered while working on conda testing
15+
(`PR #1194 <https://github.com/NVIDIA/cuda-python/pull/1194>`_)

cuda_pathfinder/pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ test = [
1818
cu12 = [
1919
"cuda-toolkit[nvcc,cublas,nvrtc,cudart,cufft,curand,cusolver,cusparse,npp,nvfatbin,nvjitlink,nvjpeg,cccl]==12.*",
2020
"cuda-toolkit[cufile]==12.*; sys_platform != 'win32'",
21+
"cutensor-cu12",
2122
"nvidia-cublasmp-cu12; sys_platform != 'win32'",
2223
"nvidia-cudss-cu12",
2324
"nvidia-cufftmp-cu12; sys_platform != 'win32'",
@@ -28,6 +29,7 @@ cu12 = [
2829
cu13 = [
2930
"cuda-toolkit[nvcc,cublas,nvrtc,cudart,cufft,curand,cusolver,cusparse,npp,nvfatbin,nvjitlink,nvjpeg,cccl,nvvm]==13.*",
3031
"cuda-toolkit[cufile]==13.*; sys_platform != 'win32'",
32+
"cutensor-cu13",
3133
"nvidia-cublasmp-cu13; sys_platform != 'win32'",
3234
"nvidia-cudss-cu13",
3335
"nvidia-nccl-cu13; sys_platform != 'win32'",
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
import functools
5+
import importlib.metadata
6+
import re
7+
8+
9+
@functools.cache
10+
def have_distribution(name_pattern: str) -> bool:
11+
re_name_pattern = re.compile(name_pattern)
12+
return any(
13+
re_name_pattern.match(dist.metadata["Name"])
14+
for dist in importlib.metadata.distributions()
15+
if "Name" in dist.metadata
16+
)

0 commit comments

Comments
 (0)