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,552 @@
1
+ # Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ __all__ = ["LeadingDimension", "TransposeMode", "Arrangement"]
6
+
7
+ from collections import namedtuple
8
+ from functools import lru_cache
9
+ from typing import NamedTuple, Protocol
10
+ from collections.abc import Sequence
11
+
12
+ import numpy as np
13
+
14
+
15
+ from .common import check_in, check_code_type
16
+ from .common_backend import (
17
+ EXECUTION_STR_TO_MATHDX,
18
+ NP_TYPES_TO_MATHDX_PRECISION,
19
+ NVARG_GEN_OPT_LTO,
20
+ build_get_int_traits,
21
+ build_get_str_trait,
22
+ )
23
+ from .common_cuda import CodeType, Dim3, ComputeCapability, ISAVersion
24
+ from .common_backend import DescriptorWrapper
25
+ from .types import REAL_NP_TYPES, INT_NP_TYPES
26
+
27
+ from nvmath.bindings import mathdx
28
+
29
+
30
+ _BLAS_API_STR_TO_MATHDX = {
31
+ "static_leading_dimensions": mathdx.CublasdxApi.SMEM,
32
+ "dynamic_leading_dimensions": mathdx.CublasdxApi.SMEM_DYNAMIC_LD,
33
+ "tensors": mathdx.CublasdxApi.TENSORS,
34
+ }
35
+
36
+ _BLAS_ARRENGEMENT_STR_TO_MATHDX = {a.name.lower(): a for a in mathdx.CublasdxArrangement}
37
+
38
+ _BLAS_TYPE_STR_TO_MATHDX = {t.name.lower(): t for t in mathdx.CublasdxType}
39
+
40
+ _BLAS_TRANSPOSE_STR_TO_MATHDX = {tm.name.lower(): tm for tm in mathdx.CublasdxTransposeMode}
41
+
42
+ _BLAS_FUNCTION_STR_TO_MATHDX = {
43
+ "MM": mathdx.CublasdxFunction.MM,
44
+ }
45
+
46
+ _TENSOR_TYPE_STR_TO_MATHDX = {t.name.lower(): t for t in mathdx.CublasdxTensorType}
47
+
48
+
49
+ class LeadingDimension(namedtuple("LeadingDimension", ["a", "b", "c"])):
50
+ """
51
+ A namedtuple class that encapsulates the three leading dimensions in matrix
52
+ multiplication :math:`C = \\alpha Op(A) Op(B) + \\beta C`.
53
+
54
+ Attributes:
55
+ a (int): The leading dimension of two-dimensional array used to store the matrix
56
+ ``A``.
57
+
58
+ b (int): The leading dimension of two-dimensional array used to store the matrix
59
+ ``B``.
60
+
61
+ c (int): The leading dimension of two-dimensional array used to store the matrix
62
+ ``C``.
63
+ """
64
+
65
+ pass
66
+
67
+
68
+ class TransposeMode(namedtuple("TransposeMode", ["a", "b"])):
69
+ """
70
+ A namedtuple class that encapsulates the transpose mode for input matrices ``A`` and
71
+ ``B`` in matrix multiplication.
72
+
73
+ Attributes:
74
+ a: The operation that needs to be performed with input matrix ``A``, currently
75
+ supports ``'non_transposed'``, ``'transposed'`` and ``'conj_transposed'``.
76
+
77
+ b: The operation that needs to be performed with input matrix ``B``, currently
78
+ supports ``'non_transposed'``, ``'transposed'`` and ``'conj_transposed'``.
79
+ """
80
+
81
+ pass
82
+
83
+
84
+ class Arrangement(NamedTuple):
85
+ """
86
+ A namedtuple class that encapsulates the three arrangements in matrix allocation.
87
+
88
+ Attributes:
89
+ a (str): The arrangement of two-dimensional array used to store the matrix
90
+ ``A``.
91
+
92
+ b (str): The arrangement of two-dimensional array used to store the matrix
93
+ ``B``.
94
+
95
+ c (str): The arrangement of two-dimensional array used to store the matrix
96
+ ``C``.
97
+ """
98
+
99
+ a: str
100
+ b: str
101
+ c: str
102
+
103
+
104
+ class Precision(NamedTuple):
105
+ """
106
+ A namedtuple class that encapsulates the three precisions in matrix
107
+ multiplication :math:`C = \\alpha Op(A) Op(B) + \\beta C`.
108
+
109
+ Attributes:
110
+ a (type): The precision of two-dimensional array used to store the matrix
111
+ ``A``.
112
+
113
+ b (type): The precision of two-dimensional array used to store the matrix
114
+ ``B``.
115
+
116
+ c (type): The precision of two-dimensional array used to store the matrix
117
+ ``C``.
118
+ """
119
+
120
+ a: type[object]
121
+ b: type[object]
122
+ c: type[object]
123
+
124
+
125
+ class Alignment(NamedTuple):
126
+ """
127
+ A type to encapsulate the memory alignment in bytes of the matrix operands
128
+ A, B, and C.
129
+
130
+ Attributes:
131
+ a (int): The alignment of two-dimensional array used to store the matrix
132
+ ``A``.
133
+
134
+ b (int): The alignment of two-dimensional array used to store the matrix
135
+ ``B``.
136
+
137
+ c (int): The alignment of two-dimensional array used to store the matrix
138
+ ``C``.
139
+ """
140
+
141
+ a: int
142
+ b: int
143
+ c: int
144
+
145
+
146
+ class CublasdxTensors(NamedTuple):
147
+ a: int
148
+ b: int
149
+ c: int
150
+
151
+
152
+ class CublasdxTensorAPISymbols(NamedTuple):
153
+ copy_a: str
154
+ copy_b: str
155
+ copy_c: str
156
+ copy_c_back: str
157
+ clear_c: str
158
+ axpby: str
159
+ gemm: str
160
+
161
+
162
+ MAX_ALIGNMENT = Alignment(16, 16, 16)
163
+
164
+
165
+ class CallableGetIntTraits(Protocol):
166
+ def __call__(self, handle: int, trait_type: mathdx.CublasdxTraitType, size: int) -> tuple: ...
167
+
168
+
169
+ class CallableGetStrTrait(Protocol):
170
+ def __call__(self, handle: int, trait_type: mathdx.CublasdxTraitType) -> str: ...
171
+
172
+
173
+ get_int_traits: CallableGetIntTraits = build_get_int_traits(mathdx.cublasdx_get_trait_int64s)
174
+
175
+ get_str_trait: CallableGetStrTrait = build_get_str_trait(mathdx.cublasdx_get_trait_str_size, mathdx.cublasdx_get_trait_str)
176
+
177
+ get_str_device_trait: CallableGetStrTrait = build_get_str_trait(
178
+ mathdx.cublasdx_get_device_function_trait_str_size, mathdx.cublasdx_get_device_function_trait_str
179
+ )
180
+
181
+
182
+ def get_tensor_int_traits(tensors: CublasdxTensors, trait: mathdx.CublasdxTensorTrait):
183
+ return (
184
+ int(mathdx.cublasdx_get_tensor_trait_int64(tensors.a, trait)),
185
+ int(mathdx.cublasdx_get_tensor_trait_int64(tensors.b, trait)),
186
+ int(mathdx.cublasdx_get_tensor_trait_int64(tensors.c, trait)),
187
+ )
188
+
189
+
190
+ _ACCEPTED_PRECISION = REAL_NP_TYPES + INT_NP_TYPES
191
+
192
+
193
+ def validate(
194
+ size,
195
+ data_type,
196
+ precision,
197
+ execution,
198
+ transpose_mode,
199
+ arrangement,
200
+ alignment,
201
+ block_dim,
202
+ code_type,
203
+ function,
204
+ leading_dimension,
205
+ static_block_dim,
206
+ ):
207
+ (m, n, k) = size
208
+ if m <= 0 or n <= 0 or k <= 0:
209
+ raise ValueError(f"m, n, k must be > 0. Got {m}, {n}, {k}")
210
+ if isinstance(precision, Precision):
211
+ for m in ["a", "b", "c"]:
212
+ check_in(f"precision.{m}", getattr(precision, m), _ACCEPTED_PRECISION)
213
+ else:
214
+ raise ValueError(
215
+ f"precision should be an instance of {Precision} or a 3-sequence, and individual fields "
216
+ f"should be one of {_ACCEPTED_PRECISION}. Instead got precision = {precision}"
217
+ )
218
+ check_in("data_type", data_type, ["real", "complex"])
219
+ check_in("execution", execution, ["Block", "Thread"])
220
+ check_in("function", function, ["MM"])
221
+ check_in("static_block_dim", static_block_dim, [True, False])
222
+ if transpose_mode is not None:
223
+ allowed_values = ["non_transposed", "transposed", "conj_transposed"]
224
+ if isinstance(transpose_mode, TransposeMode):
225
+ check_in("transpose_mode.a", transpose_mode.a, allowed_values)
226
+ check_in("transpose_mode.b", transpose_mode.b, allowed_values)
227
+ else:
228
+ raise ValueError(
229
+ f"transpose_mode should be an instance of {TransposeMode} or a 2-tuple, and individual fields "
230
+ f"should be one of {allowed_values}. Instead got transpose_mode = {transpose_mode}"
231
+ )
232
+ if arrangement is not None:
233
+ allowed_values = _BLAS_ARRENGEMENT_STR_TO_MATHDX.keys()
234
+ if isinstance(arrangement, Arrangement):
235
+ check_in("arrangement.a", arrangement.a, allowed_values)
236
+ check_in("arrangement.b", arrangement.b, allowed_values)
237
+ check_in("arrangement.c", arrangement.c, allowed_values)
238
+ else:
239
+ raise ValueError(
240
+ f"arrangement should be an instance of {Arrangement} or a 3-tuple, and individual fields "
241
+ f"should be one of {allowed_values}. Instead got arrangement = {arrangement}"
242
+ )
243
+ if arrangement is not None and transpose_mode is not None:
244
+ raise ValueError("only arrangement or transpose_mode must be provide. Instead got both")
245
+ if arrangement is None and transpose_mode is None:
246
+ raise ValueError("arrangement or transpose_mode must be provide. Instead got nothing")
247
+ if alignment is not None:
248
+ validate_alignment(alignment, precision, data_type)
249
+ if block_dim in (None, "suggested"):
250
+ pass
251
+ elif isinstance(block_dim, Dim3):
252
+ prod = block_dim[0] * block_dim[1] * block_dim[2]
253
+ if prod <= 0 or prod > 1024:
254
+ raise ValueError(
255
+ f"The product of the entries in block_dim should be between 1 and 1024 ; got block_dim = {block_dim}"
256
+ )
257
+ else:
258
+ raise ValueError(f"block_dim should be None, a Dim3 instance or 'suggested'; got block_dim = {block_dim}")
259
+ if code_type is not None:
260
+ check_code_type(code_type)
261
+ if leading_dimension in (None, "suggested") or isinstance(leading_dimension, LeadingDimension):
262
+ pass
263
+ else:
264
+ raise ValueError(
265
+ f"leading_dimension should be None, a LeadingDimension instance or 'suggested'; "
266
+ f"got leading_dimension = {leading_dimension}"
267
+ )
268
+
269
+
270
+ def validate_execute_api(execute_api):
271
+ """
272
+ Validate the execute_api argument.
273
+ """
274
+ check_in("execute_api", execute_api, _BLAS_API_STR_TO_MATHDX.keys())
275
+
276
+
277
+ def validate_tensor_types(tensor_types):
278
+ """
279
+ Validate the tensor_types argument.
280
+ """
281
+ allowed_values = _TENSOR_TYPE_STR_TO_MATHDX.keys()
282
+ if isinstance(tensor_types, Sequence) and len(tensor_types) == 3:
283
+ check_in("tensor_types[0]", tensor_types[0], allowed_values)
284
+ check_in("tensor_types[1]", tensor_types[1], allowed_values)
285
+ check_in("tensor_types[2]", tensor_types[2], allowed_values)
286
+ else:
287
+ raise ValueError(
288
+ f"tensor_types should be a 3-tuple, and individual fields "
289
+ f"should be one of {allowed_values}. Instead got tensor_types = {tensor_types}"
290
+ )
291
+
292
+
293
+ def validate_alignment(alignment: Alignment, precision: Precision, data_type: str, gmem: bool = False):
294
+ """
295
+ Validates alignment. precision and data_type must be already validated.
296
+ """
297
+ name = "alignment" if not gmem else "global_memory_alignment"
298
+ default_a = default_alignment(precision, data_type)
299
+ for m in ["a", "b", "c"]:
300
+ a = getattr(alignment, m)
301
+ max_a = getattr(MAX_ALIGNMENT, m)
302
+ def_a = getattr(default_a, m)
303
+ if a <= 0:
304
+ raise ValueError(f"{name}.{m} must be > 0. Got {a}")
305
+ if a > max_a:
306
+ raise ValueError(f"{name}.{m} must be less than maximum alignment {max_a}. Got {a}")
307
+ if a % def_a != 0:
308
+ raise ValueError(f"{name}.{m} must be a multiple of input value type {def_a}. Got {a}")
309
+
310
+
311
+ def default_alignment(precision: Precision, data_type: str):
312
+ # supported precision's itemsize is always power of two, so we are safe
313
+ mul = 1 if data_type == "real" else 2
314
+
315
+ alignment = tuple(np.dtype(p).itemsize * mul for p in precision)
316
+ return Alignment(*alignment)
317
+
318
+
319
+ @lru_cache
320
+ def generate_MM(
321
+ size: tuple[int, int, int],
322
+ precision: Precision,
323
+ data_type: str,
324
+ function: str,
325
+ transpose_mode: TransposeMode | None,
326
+ arrangement: Arrangement | None,
327
+ alignment: Alignment | None,
328
+ code_type: CodeType | None,
329
+ block_dim: Dim3 | None,
330
+ static_block_dim: bool,
331
+ execution: str,
332
+ leading_dimension: LeadingDimension | None,
333
+ execute_api: str | None = None,
334
+ tensor_types: tuple[str, str, str] | None = None,
335
+ ):
336
+ """
337
+ Generate a cuBLASDx descriptor for matrix multiplication.
338
+
339
+ tenosr_types is only used to create cache properly.
340
+ """
341
+ h = mathdx.cublasdx_create_descriptor()
342
+
343
+ (m, n, k) = size
344
+
345
+ if execute_api is not None:
346
+ mathdx.cublasdx_set_operator_int64(h, mathdx.CublasdxOperatorType.API, _BLAS_API_STR_TO_MATHDX[execute_api])
347
+
348
+ mathdx.cublasdx_set_operator_int64s(h, mathdx.CublasdxOperatorType.SIZE, 3, [m, n, k])
349
+ mathdx.cublasdx_set_operator_int64s(
350
+ h, mathdx.CublasdxOperatorType.PRECISION, len(precision), [NP_TYPES_TO_MATHDX_PRECISION[p] for p in precision]
351
+ )
352
+
353
+ mathdx.cublasdx_set_operator_int64(h, mathdx.CublasdxOperatorType.FUNCTION, _BLAS_FUNCTION_STR_TO_MATHDX[function])
354
+ mathdx.cublasdx_set_operator_int64(h, mathdx.CublasdxOperatorType.EXECUTION, EXECUTION_STR_TO_MATHDX[execution])
355
+ mathdx.cublasdx_set_operator_int64(h, mathdx.CublasdxOperatorType.TYPE, _BLAS_TYPE_STR_TO_MATHDX[data_type])
356
+
357
+ if block_dim:
358
+ mathdx.cublasdx_set_operator_int64s(h, mathdx.CublasdxOperatorType.BLOCK_DIM, 3, block_dim)
359
+
360
+ if static_block_dim:
361
+ mathdx.cublasdx_set_operator_int64(h, mathdx.CublasdxOperatorType.STATIC_BLOCK_DIM, 1)
362
+
363
+ if code_type:
364
+ mathdx.cublasdx_set_operator_int64(
365
+ h, mathdx.CublasdxOperatorType.SM, code_type.cc.major * 100 + code_type.cc.minor * 10
366
+ )
367
+
368
+ if leading_dimension:
369
+ mathdx.cublasdx_set_operator_int64s(
370
+ h, mathdx.CublasdxOperatorType.LEADING_DIMENSION, 3, [leading_dimension.a, leading_dimension.b, leading_dimension.c]
371
+ )
372
+
373
+ if transpose_mode:
374
+ mathdx.cublasdx_set_operator_int64s(
375
+ h,
376
+ mathdx.CublasdxOperatorType.TRANSPOSE_MODE,
377
+ 2,
378
+ [_BLAS_TRANSPOSE_STR_TO_MATHDX[transpose_mode.a], _BLAS_TRANSPOSE_STR_TO_MATHDX[transpose_mode.b]],
379
+ )
380
+
381
+ if arrangement:
382
+ mathdx.cublasdx_set_operator_int64s(
383
+ h,
384
+ mathdx.CublasdxOperatorType.ARRANGEMENT,
385
+ 3,
386
+ [_BLAS_ARRENGEMENT_STR_TO_MATHDX[a] for a in arrangement],
387
+ )
388
+
389
+ if alignment:
390
+ mathdx.cublasdx_set_operator_int64s(
391
+ h,
392
+ mathdx.CublasdxOperatorType.ALIGNMENT,
393
+ 3,
394
+ alignment,
395
+ )
396
+
397
+ return DescriptorWrapper(h, mathdx.cublasdx_destroy_descriptor)
398
+
399
+
400
+ @lru_cache
401
+ def generate_code(handle, version: ComputeCapability, device_functions: tuple | None = None):
402
+ code = mathdx.commondx_create_code()
403
+
404
+ mathdx.commondx_set_code_option_int64(
405
+ code,
406
+ mathdx.CommondxOption.TARGET_SM,
407
+ version.integer,
408
+ )
409
+ mathdx.commondx_set_code_option_str(code, mathdx.CommondxOption.EXTRA_NVTRC_ARGS, NVARG_GEN_OPT_LTO)
410
+ if device_functions:
411
+ mathdx.cublasdx_finalize_device_functions(code, len(device_functions), list(device_functions))
412
+ else:
413
+ mathdx.cublasdx_finalize_code(code, handle)
414
+
415
+ return DescriptorWrapper(code, mathdx.commondx_destroy_code)
416
+
417
+
418
+ @lru_cache
419
+ def generate_tensors(h, tensor_types, gmem_alignment: Alignment | None = None):
420
+ type_mem_a = mathdx.cublasdx_bind_tensor(h, _TENSOR_TYPE_STR_TO_MATHDX[tensor_types[0]])
421
+ type_mem_b = mathdx.cublasdx_bind_tensor(h, _TENSOR_TYPE_STR_TO_MATHDX[tensor_types[1]])
422
+ type_mem_c = mathdx.cublasdx_bind_tensor(h, _TENSOR_TYPE_STR_TO_MATHDX[tensor_types[2]])
423
+
424
+ gmem_a = mathdx.cublasdx_bind_tensor(h, mathdx.CublasdxTensorType.GMEM_A)
425
+ gmem_b = mathdx.cublasdx_bind_tensor(h, mathdx.CublasdxTensorType.GMEM_B)
426
+ gmem_c = mathdx.cublasdx_bind_tensor(h, mathdx.CublasdxTensorType.GMEM_C)
427
+
428
+ if gmem_alignment:
429
+ mathdx.cublasdx_set_tensor_option_int64(
430
+ gmem_a,
431
+ mathdx.CublasdxTensorOption.ALIGNMENT_BYTES,
432
+ gmem_alignment.a,
433
+ )
434
+ mathdx.cublasdx_set_tensor_option_int64(
435
+ gmem_b,
436
+ mathdx.CublasdxTensorOption.ALIGNMENT_BYTES,
437
+ gmem_alignment.b,
438
+ )
439
+ mathdx.cublasdx_set_tensor_option_int64(
440
+ gmem_c,
441
+ mathdx.CublasdxTensorOption.ALIGNMENT_BYTES,
442
+ gmem_alignment.c,
443
+ )
444
+
445
+ tensors = [
446
+ type_mem_a,
447
+ type_mem_b,
448
+ type_mem_c,
449
+ gmem_a,
450
+ gmem_b,
451
+ gmem_c,
452
+ ]
453
+
454
+ mathdx.cublasdx_finalize_tensors(h, len(tensors), tensors)
455
+
456
+ target_tensors = CublasdxTensors(type_mem_a, type_mem_b, type_mem_c)
457
+ gmem_tensors = CublasdxTensors(gmem_a, gmem_b, gmem_c)
458
+
459
+ return gmem_tensors, target_tensors
460
+
461
+
462
+ @lru_cache
463
+ def generate_code_tensors(
464
+ handle,
465
+ version: ISAVersion,
466
+ gmem_tensors: CublasdxTensors,
467
+ target_tensors: CublasdxTensors,
468
+ rmem_c: bool = False,
469
+ ):
470
+ copy_a = mathdx.cublasdx_bind_device_function(
471
+ handle, mathdx.CublasdxDeviceFunctionType.COPY, 2, [gmem_tensors.a, target_tensors.a]
472
+ )
473
+ copy_b = mathdx.cublasdx_bind_device_function(
474
+ handle, mathdx.CublasdxDeviceFunctionType.COPY, 2, [gmem_tensors.b, target_tensors.b]
475
+ )
476
+ copy_c = mathdx.cublasdx_bind_device_function(
477
+ handle, mathdx.CublasdxDeviceFunctionType.COPY, 2, [gmem_tensors.c, target_tensors.c]
478
+ )
479
+ copy_c_back = mathdx.cublasdx_bind_device_function(
480
+ handle, mathdx.CublasdxDeviceFunctionType.COPY, 2, [target_tensors.c, gmem_tensors.c]
481
+ )
482
+ if rmem_c:
483
+ clear_c_fn = mathdx.cublasdx_bind_device_function(
484
+ handle, mathdx.CublasdxDeviceFunctionType.CLEAR, 1, [target_tensors.c]
485
+ )
486
+ axpby_fn = mathdx.cublasdx_bind_device_function(
487
+ handle, mathdx.CublasdxDeviceFunctionType.AXPBY, 2, [target_tensors.c, target_tensors.c]
488
+ )
489
+ gemm = mathdx.cublasdx_bind_device_function(
490
+ handle, mathdx.CublasdxDeviceFunctionType.EXECUTE, 3, [target_tensors.a, target_tensors.b, target_tensors.c]
491
+ )
492
+
493
+ clear_c_sym = get_str_device_trait(clear_c_fn, mathdx.CublasdxDeviceFunctionTrait.SYMBOL) if rmem_c else ""
494
+ axpby_sm = get_str_device_trait(axpby_fn, mathdx.CublasdxDeviceFunctionTrait.SYMBOL) if rmem_c else ""
495
+
496
+ tensor_symbols = CublasdxTensorAPISymbols(
497
+ get_str_device_trait(copy_a, mathdx.CublasdxDeviceFunctionTrait.SYMBOL),
498
+ get_str_device_trait(copy_b, mathdx.CublasdxDeviceFunctionTrait.SYMBOL),
499
+ get_str_device_trait(copy_c, mathdx.CublasdxDeviceFunctionTrait.SYMBOL),
500
+ get_str_device_trait(copy_c_back, mathdx.CublasdxDeviceFunctionTrait.SYMBOL),
501
+ clear_c_sym,
502
+ axpby_sm,
503
+ get_str_device_trait(gemm, mathdx.CublasdxDeviceFunctionTrait.SYMBOL),
504
+ )
505
+
506
+ function_list = [copy_a, copy_b, copy_c, copy_c_back, gemm]
507
+ if rmem_c:
508
+ function_list += [clear_c_fn, axpby_fn]
509
+
510
+ return generate_code(handle, version, tuple(function_list)), tensor_symbols
511
+
512
+
513
+ def generate_copy_wait_lto(compute_capability: ComputeCapability):
514
+ return generate_device_function_lto(
515
+ compute_capability,
516
+ mathdx.CublasdxDeviceFunctionType.COPY_WAIT,
517
+ (),
518
+ )
519
+
520
+
521
+ @lru_cache
522
+ def generate_device_function_lto(compute_capability: ComputeCapability, function_type: mathdx.CublasdxDeviceFunctionType, args):
523
+ arch = compute_capability.integer
524
+ # Create the cuBLASDx descriptor
525
+ h = mathdx.cublasdx_create_descriptor()
526
+ mathdx.cublasdx_set_operator_int64(h, mathdx.CublasdxOperatorType.FUNCTION, mathdx.CublasdxFunction.MM)
527
+ mathdx.cublasdx_set_operator_int64(h, mathdx.CublasdxOperatorType.EXECUTION, mathdx.CommondxExecution.BLOCK)
528
+ mathdx.cublasdx_set_operator_int64(h, mathdx.CublasdxOperatorType.API, mathdx.CublasdxApi.TENSORS)
529
+ mathdx.cublasdx_set_operator_int64(h, mathdx.CublasdxOperatorType.PRECISION, mathdx.CommondxPrecision.F32)
530
+ mathdx.cublasdx_set_operator_int64(h, mathdx.CublasdxOperatorType.SM, arch)
531
+ mathdx.cublasdx_set_operator_int64(h, mathdx.CublasdxOperatorType.TYPE, mathdx.CublasdxType.REAL)
532
+ mathdx.cublasdx_set_operator_int64s(h, mathdx.CublasdxOperatorType.BLOCK_DIM, 3, [32, 1, 1])
533
+ mathdx.cublasdx_set_operator_int64s(h, mathdx.CublasdxOperatorType.SIZE, 3, [1, 1, 1])
534
+
535
+ function = mathdx.cublasdx_bind_device_function(h, function_type, len(args), [*args])
536
+ symbol = get_str_device_trait(function, mathdx.CublasdxDeviceFunctionTrait.SYMBOL)
537
+
538
+ # Compile the device function to lto
539
+ code = mathdx.commondx_create_code()
540
+ mathdx.commondx_set_code_option_int64(code, mathdx.CommondxOption.TARGET_SM, arch)
541
+ mathdx.commondx_set_code_option_str(code, mathdx.CommondxOption.EXTRA_NVTRC_ARGS, NVARG_GEN_OPT_LTO)
542
+ mathdx.cublasdx_finalize_device_functions(code, 1, [function])
543
+
544
+ # Extract the LTOIR
545
+ lto_size = mathdx.commondx_get_code_ltoir_size(code)
546
+ lto = bytearray(lto_size)
547
+ mathdx.commondx_get_code_ltoir(code, lto_size, lto)
548
+
549
+ mathdx.commondx_destroy_code(code)
550
+ mathdx.cublasdx_destroy_descriptor(h)
551
+
552
+ return symbol, bytes(lto)