nvmath-python 0.5.0__cp313-cp313-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nvmath/__init__.pxd +0 -0
- nvmath/__init__.py +37 -0
- nvmath/_internal/__init__.py +0 -0
- nvmath/_internal/layout.py +58 -0
- nvmath/_utils.py +363 -0
- nvmath/bindings/__init__.pxd +0 -0
- nvmath/bindings/__init__.py +44 -0
- nvmath/bindings/_internal/__init__.pxd +0 -0
- nvmath/bindings/_internal/__init__.py +0 -0
- nvmath/bindings/_internal/cublas.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cublas.pxd +518 -0
- nvmath/bindings/_internal/cublasLt.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cublasLt.pxd +54 -0
- nvmath/bindings/_internal/cudss.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cudss.pxd +44 -0
- nvmath/bindings/_internal/cufft.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cufft.pxd +69 -0
- nvmath/bindings/_internal/cufftMp.pxd +77 -0
- nvmath/bindings/_internal/curand.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/curand.pxd +42 -0
- nvmath/bindings/_internal/cusolver.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cusolver.pxd +15 -0
- nvmath/bindings/_internal/cusolverDn.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cusolverDn.pxd +386 -0
- nvmath/bindings/_internal/cusparse.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cusparse.pxd +270 -0
- nvmath/bindings/_internal/mathdx.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/mathdx.pxd +79 -0
- nvmath/bindings/_internal/nvshmem.pxd +29 -0
- nvmath/bindings/_internal/utils.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/utils.pxd +186 -0
- nvmath/bindings/cublas.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cublas.pxd +545 -0
- nvmath/bindings/cublas.pyi +18 -0
- nvmath/bindings/cublasLt.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cublasLt.pxd +99 -0
- nvmath/bindings/cudss.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cudss.pxd +83 -0
- nvmath/bindings/cudss.pyi +249 -0
- nvmath/bindings/cufft.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cufft.pxd +114 -0
- nvmath/bindings/cufftMp.pxd +124 -0
- nvmath/bindings/curand.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/curand.pxd +71 -0
- nvmath/bindings/cusolver.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cusolver.pxd +60 -0
- nvmath/bindings/cusolverDn.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cusolverDn.pxd +410 -0
- nvmath/bindings/cusparse.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cusparse.pxd +329 -0
- nvmath/bindings/cycublas.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cycublas.pxd +657 -0
- nvmath/bindings/cycublasLt.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cycublasLt.pxd +1010 -0
- nvmath/bindings/cycudss.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cycudss.pxd +191 -0
- nvmath/bindings/cycufft.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cycufft.pxd +320 -0
- nvmath/bindings/cycufftMp.pxd +333 -0
- nvmath/bindings/cycurand.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cycurand.pxd +146 -0
- nvmath/bindings/cycusolver.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cycusolver.pxd +143 -0
- nvmath/bindings/cycusolverDn.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cycusolverDn.pxd +414 -0
- nvmath/bindings/cycusparse.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cycusparse.pxd +476 -0
- nvmath/bindings/cymathdx.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cymathdx.pxd +363 -0
- nvmath/bindings/cynvshmem.pxd +126 -0
- nvmath/bindings/mathdx.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/mathdx.pxd +131 -0
- nvmath/bindings/mathdx.pyi +686 -0
- nvmath/bindings/nvpl/__init__.pxd +0 -0
- nvmath/bindings/nvpl/__init__.py +11 -0
- nvmath/bindings/nvpl/_internal/__init__.pxd +0 -0
- nvmath/bindings/nvpl/_internal/__init__.py +0 -0
- nvmath/bindings/nvpl/_internal/fft.pxd +36 -0
- nvmath/bindings/nvpl/cyfft.pxd +87 -0
- nvmath/bindings/nvpl/fft.pxd +100 -0
- nvmath/bindings/nvshmem.pxd +54 -0
- nvmath/device/__init__.py +23 -0
- nvmath/device/_deprecated.py +33 -0
- nvmath/device/caching.py +51 -0
- nvmath/device/common.py +131 -0
- nvmath/device/common_backend.py +125 -0
- nvmath/device/common_cuda.py +156 -0
- nvmath/device/common_mathdx.py +97 -0
- nvmath/device/common_numba.py +159 -0
- nvmath/device/common_opaque_tensor.py +128 -0
- nvmath/device/cublasdx.py +1085 -0
- nvmath/device/cublasdx_backend.py +552 -0
- nvmath/device/cublasdx_numba.py +528 -0
- nvmath/device/cufftdx.py +551 -0
- nvmath/device/cufftdx_backend.py +194 -0
- nvmath/device/cufftdx_numba.py +123 -0
- nvmath/device/curand_kernel.py +9147 -0
- nvmath/device/nvrtc.py +95 -0
- nvmath/device/patch.py +35 -0
- nvmath/device/random.py +417 -0
- nvmath/device/random_helpers.py +23 -0
- nvmath/device/random_states.py +189 -0
- nvmath/device/types.py +11 -0
- nvmath/device/vector_types_numba.py +203 -0
- nvmath/distributed/__init__.py +117 -0
- nvmath/distributed/_internal/__init__.py +0 -0
- nvmath/distributed/_internal/nvshmem.py +243 -0
- nvmath/distributed/_internal/tensor_ifc_cupy.py +111 -0
- nvmath/distributed/_internal/tensor_ifc_numpy.py +53 -0
- nvmath/distributed/_internal/tensor_ifc_torch.py +108 -0
- nvmath/distributed/_internal/tensor_wrapper.py +59 -0
- nvmath/distributed/_utils.py +152 -0
- nvmath/distributed/fft/__init__.py +6 -0
- nvmath/distributed/fft/_configuration.py +86 -0
- nvmath/distributed/fft/fft.py +1737 -0
- nvmath/distributed/reshape/__init__.py +6 -0
- nvmath/distributed/reshape/_configuration.py +39 -0
- nvmath/distributed/reshape/reshape.py +1249 -0
- nvmath/fft/__init__.py +7 -0
- nvmath/fft/_configuration.py +208 -0
- nvmath/fft/_exec_utils.py +116 -0
- nvmath/fft/_helpers.py +260 -0
- nvmath/fft/fft.py +2346 -0
- nvmath/internal/__init__.py +5 -0
- nvmath/internal/enum_utils.py +142 -0
- nvmath/internal/formatters.py +87 -0
- nvmath/internal/mem_limit.py +51 -0
- nvmath/internal/package_ifc.py +119 -0
- nvmath/internal/package_ifc_cuda.py +43 -0
- nvmath/internal/package_ifc_cupy.py +49 -0
- nvmath/internal/package_ifc_torch.py +31 -0
- nvmath/internal/package_wrapper.py +14 -0
- nvmath/internal/tensor_ifc.py +143 -0
- nvmath/internal/tensor_ifc_cupy.py +185 -0
- nvmath/internal/tensor_ifc_numpy.py +157 -0
- nvmath/internal/tensor_ifc_torch.py +115 -0
- nvmath/internal/tensor_wrapper.py +160 -0
- nvmath/internal/typemaps.py +154 -0
- nvmath/internal/utils.py +634 -0
- nvmath/linalg/__init__.py +11 -0
- nvmath/linalg/_internal/__init__.py +3 -0
- nvmath/linalg/_internal/algo_cap_ifc.py +86 -0
- nvmath/linalg/_internal/algo_config_ifc.py +87 -0
- nvmath/linalg/_internal/enum_to_tuples.py +64 -0
- nvmath/linalg/_internal/epilog_protocol.py +738 -0
- nvmath/linalg/_internal/matmul_desc_ifc.py +72 -0
- nvmath/linalg/_internal/matmul_pref_ifc.py +65 -0
- nvmath/linalg/_internal/matrix_layout_ifc.py +59 -0
- nvmath/linalg/_internal/typemaps.py +135 -0
- nvmath/linalg/_internal/utils.py +96 -0
- nvmath/linalg/advanced/__init__.py +8 -0
- nvmath/linalg/advanced/_algorithmmod.py +142 -0
- nvmath/linalg/advanced/_configuration.py +320 -0
- nvmath/linalg/advanced/helpers/__init__.py +5 -0
- nvmath/linalg/advanced/helpers/matmul.py +173 -0
- nvmath/linalg/advanced/matmulmod.py +2855 -0
- nvmath/memory.py +266 -0
- nvmath/sparse/__init__.py +18 -0
- nvmath/sparse/_internal/__init__.py +21 -0
- nvmath/sparse/_internal/common_utils.py +81 -0
- nvmath/sparse/_internal/cudss_config_ifc.py +584 -0
- nvmath/sparse/_internal/cudss_data_ifc.py +291 -0
- nvmath/sparse/_internal/cudss_utils.py +398 -0
- nvmath/sparse/_internal/sparse_csr_ifc.py +154 -0
- nvmath/sparse/_internal/sparse_format_helpers.py +88 -0
- nvmath/sparse/_internal/sparse_tensor_ifc.py +80 -0
- nvmath/sparse/advanced/__init__.py +7 -0
- nvmath/sparse/advanced/_configuration.py +150 -0
- nvmath/sparse/advanced/direct_solver.py +1705 -0
- nvmath_python-0.5.0.dist-info/METADATA +122 -0
- nvmath_python-0.5.0.dist-info/RECORD +174 -0
- nvmath_python-0.5.0.dist-info/WHEEL +5 -0
- nvmath_python-0.5.0.dist-info/licenses/LICENSE +177 -0
- nvmath_python-0.5.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
__all__ = ["current_device_lto", "ComputeCapability", "CodeType", "ISAVersion", "Code", "Dim3", "MAX_SUPPORTED_CC"]
|
|
6
|
+
|
|
7
|
+
from typing import NamedTuple
|
|
8
|
+
from cuda.bindings import runtime as cudart, driver as cudadrv
|
|
9
|
+
import logging
|
|
10
|
+
from collections import namedtuple
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# Code = CodeType + ISAVersion + buffer
|
|
14
|
+
class Code(namedtuple("Code", ("code_type", "isa_version", "data"))):
|
|
15
|
+
"""
|
|
16
|
+
A namedtuple class that encapsulates code type, version, and buffer.
|
|
17
|
+
|
|
18
|
+
Attributes:
|
|
19
|
+
code_type (CodeType): The underlying code type.
|
|
20
|
+
isa_version (ISAVersion): The instruction set architecture version for the code.
|
|
21
|
+
data: The buffer pointer.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# CodeType = type + CC
|
|
28
|
+
class CodeType(namedtuple("CodeType", ("kind", "cc"))):
|
|
29
|
+
"""
|
|
30
|
+
A namedtuple class that encapsulates code kind and compute capability.
|
|
31
|
+
|
|
32
|
+
Attributes:
|
|
33
|
+
kind (str): A string denoting the nature of the code, e.g, ``'lto'``.
|
|
34
|
+
cc (ComputeCapability): The current GPU compute capability.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
pass
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
# CC = e.g. SM 9.0 (Hopper)
|
|
41
|
+
class ComputeCapability(NamedTuple):
|
|
42
|
+
"""
|
|
43
|
+
A namedtuple class that encapsulates the major and minor compute capability.
|
|
44
|
+
|
|
45
|
+
Attributes:
|
|
46
|
+
major (int): The major compute capability.
|
|
47
|
+
minor (int): The minor compute capability.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
major: int
|
|
51
|
+
minor: int
|
|
52
|
+
|
|
53
|
+
@property
|
|
54
|
+
def integer(self) -> int:
|
|
55
|
+
"""Integer representation of the ISAVersion"""
|
|
56
|
+
return self.major * 100 + self.minor * 10
|
|
57
|
+
|
|
58
|
+
def __str__(self):
|
|
59
|
+
"""String representation of the ComputeCapability"""
|
|
60
|
+
return f"{self.major}.{self.minor}"
|
|
61
|
+
|
|
62
|
+
pass
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
MAX_SUPPORTED_CC = ComputeCapability(12, 1)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class Dim3(namedtuple("Dim3", ("x", "y", "z"), defaults=(1, 1, 1))):
|
|
69
|
+
"""
|
|
70
|
+
A namedtuple class that encapsulates the dimensions for grids and blocks.
|
|
71
|
+
|
|
72
|
+
Attributes:
|
|
73
|
+
x (int): The dimension in the x direction (default 1).
|
|
74
|
+
y (int): The dimension in the y direction (default 1).
|
|
75
|
+
z (int): The dimension in the z direction (default 1).
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
pass
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
# ISAVersion = e.g. 12.3 (from CUDA 12.3)
|
|
82
|
+
class ISAVersion(NamedTuple):
|
|
83
|
+
"""
|
|
84
|
+
A namedtuple class that encapsulates the code version.
|
|
85
|
+
|
|
86
|
+
Attributes:
|
|
87
|
+
major (int): The major code version.
|
|
88
|
+
minor (int): The minor code version.
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
major: int
|
|
92
|
+
minor: int
|
|
93
|
+
|
|
94
|
+
@classmethod
|
|
95
|
+
def from_integer(cls, isa: int):
|
|
96
|
+
major = isa // 1000
|
|
97
|
+
minor = (isa % 1000) // 10
|
|
98
|
+
|
|
99
|
+
return cls(major, minor)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def CHECK_CUDART(err):
|
|
103
|
+
if err != cudart.cudaError_t.cudaSuccess:
|
|
104
|
+
err2, str = cudart.cudaGetErrorString(err)
|
|
105
|
+
raise RuntimeError(f"CUDArt Error: {str} ({err})")
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def CHECK_CUDA(err):
|
|
109
|
+
if err != cudadrv.CUresult.CUDA_SUCCESS:
|
|
110
|
+
err2, str = cudadrv.cuGetErrorName(err)
|
|
111
|
+
raise RuntimeError(f"CUDA Error: {str} ({err})")
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def get_current_device_cc():
|
|
115
|
+
(err,) = cudadrv.cuInit(0)
|
|
116
|
+
CHECK_CUDA(err)
|
|
117
|
+
# Check if a context exist
|
|
118
|
+
err, pctx = cudadrv.cuCtxGetCurrent()
|
|
119
|
+
CHECK_CUDA(err)
|
|
120
|
+
if int(pctx) == 0:
|
|
121
|
+
# If not, return the CC of device 0
|
|
122
|
+
device = 0
|
|
123
|
+
else:
|
|
124
|
+
err, device = cudart.cudaGetDevice()
|
|
125
|
+
CHECK_CUDART(err)
|
|
126
|
+
err, prop = cudart.cudaGetDeviceProperties(device)
|
|
127
|
+
CHECK_CUDART(err)
|
|
128
|
+
major, minor = prop.major, prop.minor
|
|
129
|
+
if (major, minor) > MAX_SUPPORTED_CC:
|
|
130
|
+
logging.info(
|
|
131
|
+
"The current device supports compute capability "
|
|
132
|
+
f"{prop.major}.{prop.minor}, but the generated LTO version is "
|
|
133
|
+
f"capped at {MAX_SUPPORTED_CC}."
|
|
134
|
+
)
|
|
135
|
+
major, minor = MAX_SUPPORTED_CC
|
|
136
|
+
logging.info(f"Using device {device} for default compute capability, found cc = {prop.major}.{prop.minor}")
|
|
137
|
+
return ComputeCapability(major, minor)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def get_default_code_type() -> CodeType:
|
|
141
|
+
try:
|
|
142
|
+
return CodeType("lto", get_current_device_cc())
|
|
143
|
+
except RuntimeError as e:
|
|
144
|
+
raise ValueError(f"Failed to get the current GPU compute capability (got {e}). Set code_type explicitly.")
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def current_device_lto():
|
|
148
|
+
"""
|
|
149
|
+
A helper function to get the default code type for link time optimization (LTO) on the
|
|
150
|
+
current device.
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
A :class:`CodeType` object representing the default LTO code type for the current
|
|
154
|
+
device.
|
|
155
|
+
"""
|
|
156
|
+
return get_default_code_type()
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
from importlib.metadata import files, PackageNotFoundError
|
|
6
|
+
import os
|
|
7
|
+
import platform
|
|
8
|
+
import re
|
|
9
|
+
import sys
|
|
10
|
+
import warnings
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
CUDA_HOME = None
|
|
14
|
+
CURAND_HOME = None
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
PLATFORM_LINUX = sys.platform.startswith("linux")
|
|
18
|
+
PLATFORM_WIN = sys.platform.startswith("win32")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def conda_get_target_name():
|
|
22
|
+
if PLATFORM_LINUX:
|
|
23
|
+
plat = platform.processor()
|
|
24
|
+
if plat == "aarch64":
|
|
25
|
+
return "sbsa-linux"
|
|
26
|
+
else:
|
|
27
|
+
return f"{plat}-linux"
|
|
28
|
+
elif PLATFORM_WIN:
|
|
29
|
+
return "x64"
|
|
30
|
+
else:
|
|
31
|
+
raise AssertionError()
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def check_cuda_home():
|
|
35
|
+
# We need some CUDA headers for compiling mathDx headers.
|
|
36
|
+
# We assume users properly managing their local envs (ex: no mix-n-match).
|
|
37
|
+
global CUDA_HOME
|
|
38
|
+
global CURAND_HOME
|
|
39
|
+
|
|
40
|
+
# Try wheel
|
|
41
|
+
try:
|
|
42
|
+
# We need CUDA 12+ for device API support
|
|
43
|
+
cudart = files("nvidia-cuda-runtime-cu12")
|
|
44
|
+
cccl = files("nvidia-cuda-cccl-cu12")
|
|
45
|
+
curand = files("nvidia-curand-cu12")
|
|
46
|
+
# use cuda_fp16.h (which we need) as a proxy
|
|
47
|
+
cudart = [f for f in cudart if "cuda_fp16.h" in str(f)][0]
|
|
48
|
+
cudart = os.path.join(os.path.dirname(cudart.locate()), "..")
|
|
49
|
+
# use cuda/std/type_traits as a proxy
|
|
50
|
+
cccl = min([f for f in cccl if re.match(r".*cuda\/std\/type_traits.*", str(f))], key=lambda x: len(str(x)))
|
|
51
|
+
cccl = os.path.join(os.path.dirname(cccl.locate()), "../../..")
|
|
52
|
+
curand = [f for f in curand if "curand_kernel.h" in str(f)][0]
|
|
53
|
+
curand = os.path.dirname(curand.locate())
|
|
54
|
+
except PackageNotFoundError:
|
|
55
|
+
pass
|
|
56
|
+
except ValueError:
|
|
57
|
+
# cccl wheel is buggy (headers missing), skip using wheels
|
|
58
|
+
pass
|
|
59
|
+
else:
|
|
60
|
+
CUDA_HOME = (cudart, cccl)
|
|
61
|
+
CURAND_HOME = curand
|
|
62
|
+
return
|
|
63
|
+
|
|
64
|
+
# Try conda
|
|
65
|
+
if "CONDA_PREFIX" in os.environ:
|
|
66
|
+
if PLATFORM_LINUX:
|
|
67
|
+
conda_include = os.path.join(os.environ["CONDA_PREFIX"], "targets", f"{conda_get_target_name()}", "include")
|
|
68
|
+
elif PLATFORM_WIN:
|
|
69
|
+
conda_include = os.path.join(os.environ["CONDA_PREFIX"], "Library", "include")
|
|
70
|
+
else:
|
|
71
|
+
raise AssertionError()
|
|
72
|
+
if os.path.isfile(os.path.join(conda_include, "cuda_fp16.h")) and os.path.isfile(
|
|
73
|
+
os.path.join(conda_include, "cuda/std/type_traits")
|
|
74
|
+
):
|
|
75
|
+
CUDA_HOME = (os.path.join(conda_include, ".."),)
|
|
76
|
+
CURAND_HOME = os.path.join(CUDA_HOME[0], "include")
|
|
77
|
+
return
|
|
78
|
+
|
|
79
|
+
# Try local
|
|
80
|
+
CUDA_PATH = os.environ.get("CUDA_PATH", None)
|
|
81
|
+
CUDA_HOME = os.environ.get("CUDA_HOME", None)
|
|
82
|
+
if CUDA_PATH is None and CUDA_HOME is None:
|
|
83
|
+
raise RuntimeError(
|
|
84
|
+
"cudart headers not found. Depending on how you install nvmath-python and other CUDA packages,\n"
|
|
85
|
+
"you may need to perform one of the steps below:\n"
|
|
86
|
+
" - conda install -c conda-forge cuda-cudart-dev cuda-cccl cuda-version=12\n"
|
|
87
|
+
" - export CUDA_HOME=/path/to/CUDA/Toolkit"
|
|
88
|
+
)
|
|
89
|
+
elif CUDA_PATH is not None and CUDA_HOME is None:
|
|
90
|
+
CUDA_HOME = CUDA_PATH
|
|
91
|
+
elif CUDA_PATH is not None and CUDA_HOME is not None and CUDA_HOME != CUDA_PATH:
|
|
92
|
+
warnings.warn("Both CUDA_HOME and CUDA_PATH are set but not consistent. Ignoring CUDA_PATH...")
|
|
93
|
+
CUDA_HOME = (CUDA_HOME,)
|
|
94
|
+
CURAND_HOME = os.path.join(CUDA_HOME[0], "include")
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
check_cuda_home()
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
from llvmlite import ir
|
|
6
|
+
from numba import types
|
|
7
|
+
from numba.core import cgutils
|
|
8
|
+
from numba.extending import models, overload_attribute
|
|
9
|
+
import numpy as np
|
|
10
|
+
|
|
11
|
+
from .vector_types_numba import float16x2_type, float16x4_type, float32x2_type, float64x2_type
|
|
12
|
+
from .types import np_float16x2, np_float16x4
|
|
13
|
+
from .common_opaque_tensor import OpaqueTensorType
|
|
14
|
+
|
|
15
|
+
NP_TYPES_TO_NUMBA_FE_TYPES = {
|
|
16
|
+
np.float16: np.float16,
|
|
17
|
+
np.float32: np.float32,
|
|
18
|
+
np.float64: np.float64,
|
|
19
|
+
np_float16x2: float16x2_type,
|
|
20
|
+
np_float16x4: float16x4_type,
|
|
21
|
+
np.complex64: float32x2_type,
|
|
22
|
+
np.complex128: float64x2_type,
|
|
23
|
+
np.int8: np.int8,
|
|
24
|
+
np.int16: np.int16,
|
|
25
|
+
np.int32: np.int32,
|
|
26
|
+
np.int64: np.int64,
|
|
27
|
+
np.uint8: np.uint8,
|
|
28
|
+
np.uint16: np.uint16,
|
|
29
|
+
np.uint32: np.uint32,
|
|
30
|
+
np.uint64: np.uint64,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
NUMBA_FE_TYPES_TO_NUMBA_IR = {
|
|
34
|
+
np.float16: types.float16,
|
|
35
|
+
np.float32: types.float32,
|
|
36
|
+
np.float64: types.float64,
|
|
37
|
+
float16x2_type: float16x2_type,
|
|
38
|
+
float16x4_type: float16x4_type,
|
|
39
|
+
float32x2_type: float32x2_type,
|
|
40
|
+
float64x2_type: float64x2_type,
|
|
41
|
+
np.int8: types.int8,
|
|
42
|
+
np.int16: types.int16,
|
|
43
|
+
np.int32: types.int32,
|
|
44
|
+
np.int64: types.int64,
|
|
45
|
+
np.uint8: types.uint8,
|
|
46
|
+
np.uint16: types.uint16,
|
|
47
|
+
np.uint32: types.uint32,
|
|
48
|
+
np.uint64: types.uint64,
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def make_dx_codegen_one_arg(context, builder: ir.IRBuilder, type_, arg):
|
|
53
|
+
# mathdx expects everything to be passed by pointers.
|
|
54
|
+
# Arrays are lowered by passing a pointer to the data
|
|
55
|
+
# arg can be None, in which case a null pointer is passed
|
|
56
|
+
if isinstance(type_, OpaqueTensorType):
|
|
57
|
+
ptrTy = ir.PointerType(ir.IntType(8))
|
|
58
|
+
ldTy = ir.IntType(64)
|
|
59
|
+
|
|
60
|
+
opaque_tensor = cgutils.create_struct_proxy(type_)(context, builder, arg)
|
|
61
|
+
ptr = cgutils.create_struct_proxy(type_.buffer_type)(context, builder, opaque_tensor.buffer).data
|
|
62
|
+
|
|
63
|
+
# Future release of numba-cuda may have support for address spaces.
|
|
64
|
+
# It is not supported to pass a non generic pointer to device function
|
|
65
|
+
# call.
|
|
66
|
+
if ptr.type.addrspace != 0:
|
|
67
|
+
ptr = builder.addrspacecast(ptr, ir.PointerType(ptr.type.pointee), "generic")
|
|
68
|
+
|
|
69
|
+
ptr = builder.bitcast(ptr, ptrTy)
|
|
70
|
+
|
|
71
|
+
layout = cgutils.create_struct_proxy(type_.layout)(context, builder, opaque_tensor.layout)
|
|
72
|
+
|
|
73
|
+
member_values = [ptr]
|
|
74
|
+
member_types = [ptrTy]
|
|
75
|
+
if type_.layout.dynamic_ld:
|
|
76
|
+
member_types += [ldTy]
|
|
77
|
+
ld = builder.bitcast(layout.leading_dimension, ldTy)
|
|
78
|
+
member_values += [ld]
|
|
79
|
+
|
|
80
|
+
structTy = ir.LiteralStructType(member_types)
|
|
81
|
+
val = cgutils.pack_struct(builder, member_values)
|
|
82
|
+
|
|
83
|
+
return (structTy, val)
|
|
84
|
+
elif isinstance(type_, types.Array):
|
|
85
|
+
dtype = type_.dtype
|
|
86
|
+
valueTy = context.get_value_type(dtype)
|
|
87
|
+
ptrTy = ir.PointerType(valueTy)
|
|
88
|
+
if arg is None:
|
|
89
|
+
ptr = ptrTy(None)
|
|
90
|
+
else:
|
|
91
|
+
ptr = cgutils.create_struct_proxy(type_)(context, builder, arg).data
|
|
92
|
+
|
|
93
|
+
# Future release of numba-cuda may have support for address spaces.
|
|
94
|
+
# It is not supported to pass a non generic pointer to device function
|
|
95
|
+
# call.
|
|
96
|
+
if ptr.type.addrspace != 0:
|
|
97
|
+
ptr = builder.addrspacecast(ptr, ir.PointerType(ptr.type.pointee), "generic")
|
|
98
|
+
|
|
99
|
+
return (ptrTy, ptr)
|
|
100
|
+
# Integers are passed as-pointers
|
|
101
|
+
# arg can be None, in which case a 0 is passed
|
|
102
|
+
elif isinstance(type_, types.Integer):
|
|
103
|
+
intTy = context.get_value_type(type_)
|
|
104
|
+
if arg is None:
|
|
105
|
+
val = intTy(0)
|
|
106
|
+
else:
|
|
107
|
+
val = arg
|
|
108
|
+
ptrTy = ir.PointerType(intTy)
|
|
109
|
+
ptr = cgutils.alloca_once_value(builder, val)
|
|
110
|
+
return (ptrTy, ptr)
|
|
111
|
+
# Floats and Complex are passed by reference (pointer) This is because some CUDA C++
|
|
112
|
+
# types, such as __half2 are non-trivial, and those must be passed by reference. For
|
|
113
|
+
# consistency we pass everything by reference.
|
|
114
|
+
elif type_ in [float16x2_type, float16x4_type, float32x2_type, float64x2_type] or isinstance( # noqa: UP038
|
|
115
|
+
type_, (types.Float, types.Complex)
|
|
116
|
+
):
|
|
117
|
+
assert arg is not None
|
|
118
|
+
valueTy = context.get_value_type(type_)
|
|
119
|
+
ptrTy = ir.PointerType(valueTy)
|
|
120
|
+
ptr = cgutils.alloca_once_value(builder, arg)
|
|
121
|
+
return (ptrTy, ptr)
|
|
122
|
+
else:
|
|
123
|
+
raise RuntimeError(f"Unsupported lowering for type {type_} for arg {arg}")
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def make_function_call(symbol):
|
|
127
|
+
def codegen(context, builder, sig, args):
|
|
128
|
+
assert len(sig.args) == len(args)
|
|
129
|
+
argsTyAndArgs = [make_dx_codegen_one_arg(context, builder, t, a) for (t, a) in zip(sig.args, args, strict=True)]
|
|
130
|
+
argsTy = [t for (t, _) in argsTyAndArgs]
|
|
131
|
+
args = [v for (_, v) in argsTyAndArgs]
|
|
132
|
+
retTy = context.get_value_type(sig.return_type)
|
|
133
|
+
fnTy = ir.FunctionType(retTy, argsTy)
|
|
134
|
+
fn = cgutils.get_or_insert_function(builder.module, fnTy, symbol)
|
|
135
|
+
builder.call(fn, args)
|
|
136
|
+
|
|
137
|
+
return codegen
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class EmptyStructModel(models.StructModel):
|
|
141
|
+
"""Data model that does not take space. Intended to be used with types that
|
|
142
|
+
are presented only at typing stage and not represented in memory."""
|
|
143
|
+
|
|
144
|
+
def __init__(self, dmm, fe_type):
|
|
145
|
+
members = []
|
|
146
|
+
super().__init__(dmm, fe_type, members)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def overload_type_attribute(numba_type, attribute_base, attribute):
|
|
150
|
+
"""Make type attribute available inside jitted code."""
|
|
151
|
+
assert issubclass(numba_type, types.Type)
|
|
152
|
+
|
|
153
|
+
@overload_attribute(numba_type, attribute, inline="always", target="cuda")
|
|
154
|
+
def ol_blas_attribute(blas_numba):
|
|
155
|
+
tp = blas_numba
|
|
156
|
+
if attribute_base != "":
|
|
157
|
+
tp = getattr(tp, attribute_base)
|
|
158
|
+
val = getattr(tp, attribute)
|
|
159
|
+
return lambda blas_numba: val
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
from abc import abstractmethod
|
|
6
|
+
from functools import cached_property
|
|
7
|
+
|
|
8
|
+
from numba.extending import types, models, type_callable, lower_builtin, overload_attribute
|
|
9
|
+
from numba.cuda.models import register_model
|
|
10
|
+
|
|
11
|
+
from nvmath.device.common import OpaqueTensor
|
|
12
|
+
from numba.cuda.extending import make_attribute_wrapper
|
|
13
|
+
|
|
14
|
+
from numba.core import cgutils
|
|
15
|
+
|
|
16
|
+
from llvmlite.ir import IRBuilder
|
|
17
|
+
from numba.core.base import BaseContext
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class LayoutType(types.Type):
|
|
21
|
+
"""
|
|
22
|
+
Type class associated with opaque tensor layouts.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
@property
|
|
26
|
+
@abstractmethod
|
|
27
|
+
def uid(self) -> int:
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
@abstractmethod
|
|
32
|
+
def dtype(self) -> str:
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
@abstractmethod
|
|
37
|
+
def size(self) -> int:
|
|
38
|
+
pass
|
|
39
|
+
|
|
40
|
+
@property
|
|
41
|
+
@abstractmethod
|
|
42
|
+
def dynamic_ld(self) -> bool:
|
|
43
|
+
pass
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@register_model(LayoutType)
|
|
47
|
+
class LayoutModel(models.StructModel):
|
|
48
|
+
def __init__(self, dmm, fe_type: LayoutType):
|
|
49
|
+
members = []
|
|
50
|
+
if fe_type.dynamic_ld:
|
|
51
|
+
members += [("leading_dimension", types.int64)]
|
|
52
|
+
models.StructModel.__init__(self, dmm, fe_type, members)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
make_attribute_wrapper(LayoutType, "leading_dimension", "leading_dimension")
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@overload_attribute(LayoutType, "size", inline="always", strict=False)
|
|
59
|
+
def ol_layout_size(layout: LayoutType):
|
|
60
|
+
assert isinstance(layout, LayoutType)
|
|
61
|
+
size = layout.size
|
|
62
|
+
return lambda _: size
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class OpaqueTensorType(types.Type):
|
|
66
|
+
def __init__(self, buffer_type: types.Array, layout: LayoutType):
|
|
67
|
+
assert layout.dtype == buffer_type.dtype
|
|
68
|
+
super().__init__(f"OpaqueTensor(layout={layout})")
|
|
69
|
+
self._buffer_type = buffer_type
|
|
70
|
+
self._layout = layout
|
|
71
|
+
|
|
72
|
+
@property
|
|
73
|
+
def uid(self):
|
|
74
|
+
return self._layout.uid
|
|
75
|
+
|
|
76
|
+
@property
|
|
77
|
+
def buffer_type(self):
|
|
78
|
+
return self._buffer_type
|
|
79
|
+
|
|
80
|
+
@property
|
|
81
|
+
def layout(self) -> LayoutType:
|
|
82
|
+
return self._layout
|
|
83
|
+
|
|
84
|
+
@cached_property
|
|
85
|
+
def ndim(self):
|
|
86
|
+
return 2
|
|
87
|
+
|
|
88
|
+
@cached_property
|
|
89
|
+
def dtype(self):
|
|
90
|
+
return self.buffer_type.dtype
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@register_model(OpaqueTensorType)
|
|
94
|
+
class OpaqueTensorModel(models.StructModel):
|
|
95
|
+
def __init__(self, dmm, fe_type: OpaqueTensorType):
|
|
96
|
+
members = [
|
|
97
|
+
("buffer", fe_type.buffer_type),
|
|
98
|
+
("layout", fe_type.layout),
|
|
99
|
+
]
|
|
100
|
+
models.StructModel.__init__(self, dmm, fe_type, members)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
make_attribute_wrapper(OpaqueTensorType, "buffer", "buffer")
|
|
104
|
+
make_attribute_wrapper(OpaqueTensorType, "layout", "layout")
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
@type_callable(OpaqueTensor)
|
|
108
|
+
def type_callable_OpaqueTensor(context):
|
|
109
|
+
def typer(buffer_ty, layout_ty):
|
|
110
|
+
if not isinstance(buffer_ty, types.Array):
|
|
111
|
+
return
|
|
112
|
+
if not isinstance(layout_ty, LayoutType):
|
|
113
|
+
return
|
|
114
|
+
return OpaqueTensorType(buffer_ty, layout_ty)
|
|
115
|
+
|
|
116
|
+
return typer
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
@lower_builtin(OpaqueTensor, types.Array, LayoutType)
|
|
120
|
+
def impl_interval(context: BaseContext, builder: IRBuilder, sig, args):
|
|
121
|
+
typ = sig.return_type
|
|
122
|
+
buffer = args[0]
|
|
123
|
+
layout = args[1]
|
|
124
|
+
opaque_tensor = cgutils.create_struct_proxy(typ)(context, builder)
|
|
125
|
+
opaque_tensor.buffer = buffer
|
|
126
|
+
opaque_tensor.layout = layout
|
|
127
|
+
|
|
128
|
+
return opaque_tensor._getvalue()
|