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.
Files changed (174) hide show
  1. nvmath/__init__.pxd +0 -0
  2. nvmath/__init__.py +37 -0
  3. nvmath/_internal/__init__.py +0 -0
  4. nvmath/_internal/layout.py +58 -0
  5. nvmath/_utils.py +363 -0
  6. nvmath/bindings/__init__.pxd +0 -0
  7. nvmath/bindings/__init__.py +44 -0
  8. nvmath/bindings/_internal/__init__.pxd +0 -0
  9. nvmath/bindings/_internal/__init__.py +0 -0
  10. nvmath/bindings/_internal/cublas.cp313-win_amd64.pyd +0 -0
  11. nvmath/bindings/_internal/cublas.pxd +518 -0
  12. nvmath/bindings/_internal/cublasLt.cp313-win_amd64.pyd +0 -0
  13. nvmath/bindings/_internal/cublasLt.pxd +54 -0
  14. nvmath/bindings/_internal/cudss.cp313-win_amd64.pyd +0 -0
  15. nvmath/bindings/_internal/cudss.pxd +44 -0
  16. nvmath/bindings/_internal/cufft.cp313-win_amd64.pyd +0 -0
  17. nvmath/bindings/_internal/cufft.pxd +69 -0
  18. nvmath/bindings/_internal/cufftMp.pxd +77 -0
  19. nvmath/bindings/_internal/curand.cp313-win_amd64.pyd +0 -0
  20. nvmath/bindings/_internal/curand.pxd +42 -0
  21. nvmath/bindings/_internal/cusolver.cp313-win_amd64.pyd +0 -0
  22. nvmath/bindings/_internal/cusolver.pxd +15 -0
  23. nvmath/bindings/_internal/cusolverDn.cp313-win_amd64.pyd +0 -0
  24. nvmath/bindings/_internal/cusolverDn.pxd +386 -0
  25. nvmath/bindings/_internal/cusparse.cp313-win_amd64.pyd +0 -0
  26. nvmath/bindings/_internal/cusparse.pxd +270 -0
  27. nvmath/bindings/_internal/mathdx.cp313-win_amd64.pyd +0 -0
  28. nvmath/bindings/_internal/mathdx.pxd +79 -0
  29. nvmath/bindings/_internal/nvshmem.pxd +29 -0
  30. nvmath/bindings/_internal/utils.cp313-win_amd64.pyd +0 -0
  31. nvmath/bindings/_internal/utils.pxd +186 -0
  32. nvmath/bindings/cublas.cp313-win_amd64.pyd +0 -0
  33. nvmath/bindings/cublas.pxd +545 -0
  34. nvmath/bindings/cublas.pyi +18 -0
  35. nvmath/bindings/cublasLt.cp313-win_amd64.pyd +0 -0
  36. nvmath/bindings/cublasLt.pxd +99 -0
  37. nvmath/bindings/cudss.cp313-win_amd64.pyd +0 -0
  38. nvmath/bindings/cudss.pxd +83 -0
  39. nvmath/bindings/cudss.pyi +249 -0
  40. nvmath/bindings/cufft.cp313-win_amd64.pyd +0 -0
  41. nvmath/bindings/cufft.pxd +114 -0
  42. nvmath/bindings/cufftMp.pxd +124 -0
  43. nvmath/bindings/curand.cp313-win_amd64.pyd +0 -0
  44. nvmath/bindings/curand.pxd +71 -0
  45. nvmath/bindings/cusolver.cp313-win_amd64.pyd +0 -0
  46. nvmath/bindings/cusolver.pxd +60 -0
  47. nvmath/bindings/cusolverDn.cp313-win_amd64.pyd +0 -0
  48. nvmath/bindings/cusolverDn.pxd +410 -0
  49. nvmath/bindings/cusparse.cp313-win_amd64.pyd +0 -0
  50. nvmath/bindings/cusparse.pxd +329 -0
  51. nvmath/bindings/cycublas.cp313-win_amd64.pyd +0 -0
  52. nvmath/bindings/cycublas.pxd +657 -0
  53. nvmath/bindings/cycublasLt.cp313-win_amd64.pyd +0 -0
  54. nvmath/bindings/cycublasLt.pxd +1010 -0
  55. nvmath/bindings/cycudss.cp313-win_amd64.pyd +0 -0
  56. nvmath/bindings/cycudss.pxd +191 -0
  57. nvmath/bindings/cycufft.cp313-win_amd64.pyd +0 -0
  58. nvmath/bindings/cycufft.pxd +320 -0
  59. nvmath/bindings/cycufftMp.pxd +333 -0
  60. nvmath/bindings/cycurand.cp313-win_amd64.pyd +0 -0
  61. nvmath/bindings/cycurand.pxd +146 -0
  62. nvmath/bindings/cycusolver.cp313-win_amd64.pyd +0 -0
  63. nvmath/bindings/cycusolver.pxd +143 -0
  64. nvmath/bindings/cycusolverDn.cp313-win_amd64.pyd +0 -0
  65. nvmath/bindings/cycusolverDn.pxd +414 -0
  66. nvmath/bindings/cycusparse.cp313-win_amd64.pyd +0 -0
  67. nvmath/bindings/cycusparse.pxd +476 -0
  68. nvmath/bindings/cymathdx.cp313-win_amd64.pyd +0 -0
  69. nvmath/bindings/cymathdx.pxd +363 -0
  70. nvmath/bindings/cynvshmem.pxd +126 -0
  71. nvmath/bindings/mathdx.cp313-win_amd64.pyd +0 -0
  72. nvmath/bindings/mathdx.pxd +131 -0
  73. nvmath/bindings/mathdx.pyi +686 -0
  74. nvmath/bindings/nvpl/__init__.pxd +0 -0
  75. nvmath/bindings/nvpl/__init__.py +11 -0
  76. nvmath/bindings/nvpl/_internal/__init__.pxd +0 -0
  77. nvmath/bindings/nvpl/_internal/__init__.py +0 -0
  78. nvmath/bindings/nvpl/_internal/fft.pxd +36 -0
  79. nvmath/bindings/nvpl/cyfft.pxd +87 -0
  80. nvmath/bindings/nvpl/fft.pxd +100 -0
  81. nvmath/bindings/nvshmem.pxd +54 -0
  82. nvmath/device/__init__.py +23 -0
  83. nvmath/device/_deprecated.py +33 -0
  84. nvmath/device/caching.py +51 -0
  85. nvmath/device/common.py +131 -0
  86. nvmath/device/common_backend.py +125 -0
  87. nvmath/device/common_cuda.py +156 -0
  88. nvmath/device/common_mathdx.py +97 -0
  89. nvmath/device/common_numba.py +159 -0
  90. nvmath/device/common_opaque_tensor.py +128 -0
  91. nvmath/device/cublasdx.py +1085 -0
  92. nvmath/device/cublasdx_backend.py +552 -0
  93. nvmath/device/cublasdx_numba.py +528 -0
  94. nvmath/device/cufftdx.py +551 -0
  95. nvmath/device/cufftdx_backend.py +194 -0
  96. nvmath/device/cufftdx_numba.py +123 -0
  97. nvmath/device/curand_kernel.py +9147 -0
  98. nvmath/device/nvrtc.py +95 -0
  99. nvmath/device/patch.py +35 -0
  100. nvmath/device/random.py +417 -0
  101. nvmath/device/random_helpers.py +23 -0
  102. nvmath/device/random_states.py +189 -0
  103. nvmath/device/types.py +11 -0
  104. nvmath/device/vector_types_numba.py +203 -0
  105. nvmath/distributed/__init__.py +117 -0
  106. nvmath/distributed/_internal/__init__.py +0 -0
  107. nvmath/distributed/_internal/nvshmem.py +243 -0
  108. nvmath/distributed/_internal/tensor_ifc_cupy.py +111 -0
  109. nvmath/distributed/_internal/tensor_ifc_numpy.py +53 -0
  110. nvmath/distributed/_internal/tensor_ifc_torch.py +108 -0
  111. nvmath/distributed/_internal/tensor_wrapper.py +59 -0
  112. nvmath/distributed/_utils.py +152 -0
  113. nvmath/distributed/fft/__init__.py +6 -0
  114. nvmath/distributed/fft/_configuration.py +86 -0
  115. nvmath/distributed/fft/fft.py +1737 -0
  116. nvmath/distributed/reshape/__init__.py +6 -0
  117. nvmath/distributed/reshape/_configuration.py +39 -0
  118. nvmath/distributed/reshape/reshape.py +1249 -0
  119. nvmath/fft/__init__.py +7 -0
  120. nvmath/fft/_configuration.py +208 -0
  121. nvmath/fft/_exec_utils.py +116 -0
  122. nvmath/fft/_helpers.py +260 -0
  123. nvmath/fft/fft.py +2346 -0
  124. nvmath/internal/__init__.py +5 -0
  125. nvmath/internal/enum_utils.py +142 -0
  126. nvmath/internal/formatters.py +87 -0
  127. nvmath/internal/mem_limit.py +51 -0
  128. nvmath/internal/package_ifc.py +119 -0
  129. nvmath/internal/package_ifc_cuda.py +43 -0
  130. nvmath/internal/package_ifc_cupy.py +49 -0
  131. nvmath/internal/package_ifc_torch.py +31 -0
  132. nvmath/internal/package_wrapper.py +14 -0
  133. nvmath/internal/tensor_ifc.py +143 -0
  134. nvmath/internal/tensor_ifc_cupy.py +185 -0
  135. nvmath/internal/tensor_ifc_numpy.py +157 -0
  136. nvmath/internal/tensor_ifc_torch.py +115 -0
  137. nvmath/internal/tensor_wrapper.py +160 -0
  138. nvmath/internal/typemaps.py +154 -0
  139. nvmath/internal/utils.py +634 -0
  140. nvmath/linalg/__init__.py +11 -0
  141. nvmath/linalg/_internal/__init__.py +3 -0
  142. nvmath/linalg/_internal/algo_cap_ifc.py +86 -0
  143. nvmath/linalg/_internal/algo_config_ifc.py +87 -0
  144. nvmath/linalg/_internal/enum_to_tuples.py +64 -0
  145. nvmath/linalg/_internal/epilog_protocol.py +738 -0
  146. nvmath/linalg/_internal/matmul_desc_ifc.py +72 -0
  147. nvmath/linalg/_internal/matmul_pref_ifc.py +65 -0
  148. nvmath/linalg/_internal/matrix_layout_ifc.py +59 -0
  149. nvmath/linalg/_internal/typemaps.py +135 -0
  150. nvmath/linalg/_internal/utils.py +96 -0
  151. nvmath/linalg/advanced/__init__.py +8 -0
  152. nvmath/linalg/advanced/_algorithmmod.py +142 -0
  153. nvmath/linalg/advanced/_configuration.py +320 -0
  154. nvmath/linalg/advanced/helpers/__init__.py +5 -0
  155. nvmath/linalg/advanced/helpers/matmul.py +173 -0
  156. nvmath/linalg/advanced/matmulmod.py +2855 -0
  157. nvmath/memory.py +266 -0
  158. nvmath/sparse/__init__.py +18 -0
  159. nvmath/sparse/_internal/__init__.py +21 -0
  160. nvmath/sparse/_internal/common_utils.py +81 -0
  161. nvmath/sparse/_internal/cudss_config_ifc.py +584 -0
  162. nvmath/sparse/_internal/cudss_data_ifc.py +291 -0
  163. nvmath/sparse/_internal/cudss_utils.py +398 -0
  164. nvmath/sparse/_internal/sparse_csr_ifc.py +154 -0
  165. nvmath/sparse/_internal/sparse_format_helpers.py +88 -0
  166. nvmath/sparse/_internal/sparse_tensor_ifc.py +80 -0
  167. nvmath/sparse/advanced/__init__.py +7 -0
  168. nvmath/sparse/advanced/_configuration.py +150 -0
  169. nvmath/sparse/advanced/direct_solver.py +1705 -0
  170. nvmath_python-0.5.0.dist-info/METADATA +122 -0
  171. nvmath_python-0.5.0.dist-info/RECORD +174 -0
  172. nvmath_python-0.5.0.dist-info/WHEEL +5 -0
  173. nvmath_python-0.5.0.dist-info/licenses/LICENSE +177 -0
  174. 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()