Skip to content

Commit ec89acc

Browse files
committed
Add SUPPORTED_LINUX_SONAMES in _path_finder/supported_libs.py
1 parent b98e1fa commit ec89acc

5 files changed

Lines changed: 206 additions & 6 deletions

File tree

cuda_bindings/cuda/bindings/_path_finder/load_nvidia_dynamic_library.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class Dl_info(ctypes.Structure):
3838

3939

4040
from .find_nvidia_dynamic_library import _find_nvidia_dynamic_library
41-
from .supported_libs import DIRECT_DEPENDENCIES, EXPECTED_LIB_SYMBOLS, SUPPORTED_WINDOWS_DLLS
41+
from .supported_libs import DIRECT_DEPENDENCIES, EXPECTED_LIB_SYMBOLS, SUPPORTED_LINUX_SONAMES, SUPPORTED_WINDOWS_DLLS
4242

4343

4444
@functools.cache
@@ -100,18 +100,19 @@ def _load_and_report_path_linux(libname, soname: str) -> Tuple[int, str]:
100100

101101
@functools.cache
102102
def load_nvidia_dynamic_library(libname: str) -> int:
103+
# Detect if the library was loaded already in some other way (i.e. not via this function).
103104
if sys.platform == "win32":
104105
for dll_name in SUPPORTED_WINDOWS_DLLS.get(libname):
105106
try:
106107
return win32api.GetModuleHandle(dll_name)
107108
except pywintypes.error:
108109
pass
109110
else:
110-
try:
111-
# TODO: This misses lib{libname}.so.N
112-
return ctypes.CDLL(f"lib{libname}.so", mode=os.RTLD_NOLOAD)
113-
except OSError:
114-
pass
111+
for soname in SUPPORTED_LINUX_SONAMES.get(libname):
112+
try:
113+
return ctypes.CDLL(soname, mode=os.RTLD_NOLOAD)
114+
except OSError:
115+
pass
115116

116117
for dep in DIRECT_DEPENDENCIES.get(libname, ()):
117118
load_nvidia_dynamic_library(dep)

cuda_bindings/cuda/bindings/_path_finder/supported_libs.py

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,127 @@
6363
"nvblas": ("cublas", "cublasLt"),
6464
}
6565

66+
# Based on these released files:
67+
# cuda_11.0.3_450.51.06_linux.run
68+
# cuda_11.1.1_455.32.00_linux.run
69+
# cuda_11.2.2_460.32.03_linux.run
70+
# cuda_11.3.1_465.19.01_linux.run
71+
# cuda_11.4.4_470.82.01_linux.run
72+
# cuda_11.5.1_495.29.05_linux.run
73+
# cuda_11.6.2_510.47.03_linux.run
74+
# cuda_11.7.1_515.65.01_linux.run
75+
# cuda_11.8.0_520.61.05_linux.run
76+
# cuda_12.0.1_525.85.12_linux.run
77+
# cuda_12.1.1_530.30.02_linux.run
78+
# cuda_12.2.2_535.104.05_linux.run
79+
# cuda_12.3.2_545.23.08_linux.run
80+
# cuda_12.4.1_550.54.15_linux.run
81+
# cuda_12.5.1_555.42.06_linux.run
82+
# cuda_12.6.2_560.35.03_linux.run
83+
# cuda_12.8.0_570.86.10_linux.run
84+
# Generated with toolshed/build_path_finder_sonames.py
85+
SUPPORTED_LINUX_SONAMES = {
86+
"cublas": (
87+
"libcublas.so.11",
88+
"libcublas.so.12",
89+
),
90+
"cublasLt": (
91+
"libcublasLt.so.11",
92+
"libcublasLt.so.12",
93+
),
94+
"cudart": (
95+
"libcudart.so.11.0",
96+
"libcudart.so.12",
97+
),
98+
"cufft": (
99+
"libcufft.so.10",
100+
"libcufft.so.11",
101+
),
102+
"cufftw": (
103+
"libcufftw.so.10",
104+
"libcufftw.so.11",
105+
),
106+
"cufile": ("libcufile.so.0",),
107+
# "cufile_rdma": ("libcufile_rdma.so.1",),
108+
"curand": ("libcurand.so.10",),
109+
"cusolver": (
110+
"libcusolver.so.10",
111+
"libcusolver.so.11",
112+
),
113+
"cusolverMg": (
114+
"libcusolverMg.so.10",
115+
"libcusolverMg.so.11",
116+
),
117+
"cusparse": (
118+
"libcusparse.so.11",
119+
"libcusparse.so.12",
120+
),
121+
"nppc": (
122+
"libnppc.so.11",
123+
"libnppc.so.12",
124+
),
125+
"nppial": (
126+
"libnppial.so.11",
127+
"libnppial.so.12",
128+
),
129+
"nppicc": (
130+
"libnppicc.so.11",
131+
"libnppicc.so.12",
132+
),
133+
"nppidei": (
134+
"libnppidei.so.11",
135+
"libnppidei.so.12",
136+
),
137+
"nppif": (
138+
"libnppif.so.11",
139+
"libnppif.so.12",
140+
),
141+
"nppig": (
142+
"libnppig.so.11",
143+
"libnppig.so.12",
144+
),
145+
"nppim": (
146+
"libnppim.so.11",
147+
"libnppim.so.12",
148+
),
149+
"nppist": (
150+
"libnppist.so.11",
151+
"libnppist.so.12",
152+
),
153+
"nppisu": (
154+
"libnppisu.so.11",
155+
"libnppisu.so.12",
156+
),
157+
"nppitc": (
158+
"libnppitc.so.11",
159+
"libnppitc.so.12",
160+
),
161+
"npps": (
162+
"libnpps.so.11",
163+
"libnpps.so.12",
164+
),
165+
"nvJitLink": ("libnvJitLink.so.12",),
166+
"nvblas": (
167+
"libnvblas.so.11",
168+
"libnvblas.so.12",
169+
),
170+
"nvfatbin": ("libnvfatbin.so.12",),
171+
"nvjpeg": (
172+
"libnvjpeg.so.11",
173+
"libnvjpeg.so.12",
174+
),
175+
"nvrtc": (
176+
"libnvrtc.so.11.0",
177+
"libnvrtc.so.11.1",
178+
"libnvrtc.so.11.2",
179+
"libnvrtc.so.12",
180+
),
181+
"nvvm": (
182+
"libnvvm.so.3",
183+
"libnvvm.so.4",
184+
),
185+
}
186+
66187
# Based on https://developer.download.nvidia.com/compute/cuda/redist/
67188
# as of 2025-04-11 (redistrib_12.8.1.json was the newest .json file).
68189
# Tuples of DLLs are sorted newest-to-oldest.

cuda_bindings/tests/test_path_finder.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
TEST_LIBNAMES = path_finder.SUPPORTED_LIBNAMES
1515

1616

17+
def test_all_libnames_linux_sonames_consistency():
18+
assert tuple(sorted(ALL_LIBNAMES)) == tuple(sorted(supported_libs.SUPPORTED_LINUX_SONAMES.keys()))
19+
20+
1721
def test_all_libnames_windows_dlls_consistency():
1822
assert tuple(sorted(ALL_LIBNAMES)) == tuple(sorted(supported_libs.SUPPORTED_WINDOWS_DLLS.keys()))
1923

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#!/usr/bin/env python3
2+
3+
import sys
4+
5+
LIBNAMES_IN_SCOPE_OF_CUDA_BINDINGS_PATH_FINDER = (
6+
"nvJitLink",
7+
"nvrtc",
8+
"nvvm",
9+
"cudart",
10+
"nvfatbin",
11+
"cublas",
12+
"cublasLt",
13+
"cufft",
14+
"cufftw",
15+
"curand",
16+
"cusolver",
17+
"cusolverMg",
18+
"cusparse",
19+
"nppc",
20+
"nppial",
21+
"nppicc",
22+
"nppidei",
23+
"nppif",
24+
"nppig",
25+
"nppim",
26+
"nppist",
27+
"nppisu",
28+
"nppitc",
29+
"npps",
30+
"nvblas",
31+
"cufile",
32+
"cufile_rdma",
33+
"nvjpeg",
34+
)
35+
36+
37+
def run(args):
38+
assert len(args) == 1, "output-of-find_sonames.sh"
39+
40+
sonames_from_file = set()
41+
for line in open(args[0]).read().splitlines():
42+
flds = line.split()
43+
assert len(flds) == 3, flds
44+
if flds[-1] != "SONAME_NOT_SET":
45+
sonames_from_file.add(flds[-1])
46+
47+
print("SONAMEs in scope of cuda.bindings.path_finder")
48+
print("=============================================")
49+
sonames_in_scope = set()
50+
for libname in sorted(LIBNAMES_IN_SCOPE_OF_CUDA_BINDINGS_PATH_FINDER):
51+
print(f'"{libname}": (')
52+
lib_so = "lib" + libname + ".so"
53+
for soname in sorted(sonames_from_file):
54+
if soname.startswith(lib_so):
55+
sonames_in_scope.add(soname)
56+
print(f' "{soname}",')
57+
print("),")
58+
print()
59+
60+
print("SONAMEs out of scope")
61+
print("====================")
62+
for soname in sorted(sonames_from_file - sonames_in_scope):
63+
print(soname)
64+
print()
65+
66+
67+
if __name__ == "__main__":
68+
run(args=sys.argv[1:])

toolshed/find_sonames.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/bin/bash
2+
find "$@" -type f -name '*.so*' -print0 | while IFS= read -r -d '' f; do
3+
type=$(test -L "$f" && echo SYMLINK || echo FILE)
4+
soname=$(readelf -d "$f" 2>/dev/null | awk '/SONAME/ {gsub(/[][]/, "", $5); print $5; exit}')
5+
echo "$f $type ${soname:-SONAME_NOT_SET}"
6+
done

0 commit comments

Comments
 (0)