nvmath-python 0.9.0__cp314-cp314-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 (309) hide show
  1. nvmath/__init__.pxd +0 -0
  2. nvmath/__init__.py +45 -0
  3. nvmath/_internal/__init__.py +0 -0
  4. nvmath/_internal/attribute_ifc_factory.py +330 -0
  5. nvmath/_internal/layout.py +70 -0
  6. nvmath/_internal/templates.py +383 -0
  7. nvmath/_utils.py +150 -0
  8. nvmath/bindings/__init__.py +51 -0
  9. nvmath/bindings/_internal/__init__.pxd +0 -0
  10. nvmath/bindings/_internal/__init__.py +0 -0
  11. nvmath/bindings/_internal/cublas.cp314-win_amd64.pyd +0 -0
  12. nvmath/bindings/_internal/cublas.pxd +530 -0
  13. nvmath/bindings/_internal/cublasLt.cp314-win_amd64.pyd +0 -0
  14. nvmath/bindings/_internal/cublasLt.pxd +59 -0
  15. nvmath/bindings/_internal/cublasMp.pxd +52 -0
  16. nvmath/bindings/_internal/cudss.cp314-win_amd64.pyd +0 -0
  17. nvmath/bindings/_internal/cudss.pxd +47 -0
  18. nvmath/bindings/_internal/cufft.cp314-win_amd64.pyd +0 -0
  19. nvmath/bindings/_internal/cufft.pxd +70 -0
  20. nvmath/bindings/_internal/cufftMp.pxd +77 -0
  21. nvmath/bindings/_internal/curand.cp314-win_amd64.pyd +0 -0
  22. nvmath/bindings/_internal/curand.pxd +42 -0
  23. nvmath/bindings/_internal/cusolver.cp314-win_amd64.pyd +0 -0
  24. nvmath/bindings/_internal/cusolver.pxd +15 -0
  25. nvmath/bindings/_internal/cusolverDn.cp314-win_amd64.pyd +0 -0
  26. nvmath/bindings/_internal/cusolverDn.pxd +406 -0
  27. nvmath/bindings/_internal/cusparse.cp314-win_amd64.pyd +0 -0
  28. nvmath/bindings/_internal/cusparse.pxd +277 -0
  29. nvmath/bindings/_internal/cusparseLt.cp314-win_amd64.pyd +0 -0
  30. nvmath/bindings/_internal/cusparseLt.pxd +48 -0
  31. nvmath/bindings/_internal/cutensor.cp314-win_amd64.pyd +0 -0
  32. nvmath/bindings/_internal/cutensor.pxd +58 -0
  33. nvmath/bindings/_internal/mathdx.cp314-win_amd64.pyd +0 -0
  34. nvmath/bindings/_internal/mathdx.pxd +116 -0
  35. nvmath/bindings/_internal/nvshmem.pxd +29 -0
  36. nvmath/bindings/_internal/utils.cp314-win_amd64.pyd +0 -0
  37. nvmath/bindings/_internal/utils.pxd +179 -0
  38. nvmath/bindings/_internal/utils.pyi +10 -0
  39. nvmath/bindings/cublas.cp314-win_amd64.pyd +0 -0
  40. nvmath/bindings/cublas.pxd +558 -0
  41. nvmath/bindings/cublas.pyi +746 -0
  42. nvmath/bindings/cublasLt.cp314-win_amd64.pyd +0 -0
  43. nvmath/bindings/cublasLt.pxd +109 -0
  44. nvmath/bindings/cublasLt.pyi +1337 -0
  45. nvmath/bindings/cublasMp.pxd +85 -0
  46. nvmath/bindings/cublasMp.pyi +219 -0
  47. nvmath/bindings/cudss.cp314-win_amd64.pyd +0 -0
  48. nvmath/bindings/cudss.pxd +86 -0
  49. nvmath/bindings/cudss.pyi +282 -0
  50. nvmath/bindings/cufft.cp314-win_amd64.pyd +0 -0
  51. nvmath/bindings/cufft.pxd +118 -0
  52. nvmath/bindings/cufft.pyi +241 -0
  53. nvmath/bindings/cufftMp.pxd +124 -0
  54. nvmath/bindings/cufftMp.pyi +260 -0
  55. nvmath/bindings/curand.cp314-win_amd64.pyd +0 -0
  56. nvmath/bindings/curand.pxd +71 -0
  57. nvmath/bindings/curand.pyi +159 -0
  58. nvmath/bindings/cusolver.cp314-win_amd64.pyd +0 -0
  59. nvmath/bindings/cusolver.pxd +62 -0
  60. nvmath/bindings/cusolver.pyi +242 -0
  61. nvmath/bindings/cusolverDn.cp314-win_amd64.pyd +0 -0
  62. nvmath/bindings/cusolverDn.pxd +430 -0
  63. nvmath/bindings/cusolverDn.pyi +416 -0
  64. nvmath/bindings/cusparse.cp314-win_amd64.pyd +0 -0
  65. nvmath/bindings/cusparse.pxd +338 -0
  66. nvmath/bindings/cusparse.pyi +659 -0
  67. nvmath/bindings/cusparseLt.cp314-win_amd64.pyd +0 -0
  68. nvmath/bindings/cusparseLt.pxd +99 -0
  69. nvmath/bindings/cusparseLt.pyi +198 -0
  70. nvmath/bindings/cutensor.cp314-win_amd64.pyd +0 -0
  71. nvmath/bindings/cutensor.pxd +98 -0
  72. nvmath/bindings/cutensor.pyi +294 -0
  73. nvmath/bindings/cycublas.cp314-win_amd64.pyd +0 -0
  74. nvmath/bindings/cycublas.pxd +684 -0
  75. nvmath/bindings/cycublasLt.cp314-win_amd64.pyd +0 -0
  76. nvmath/bindings/cycublasLt.pxd +1055 -0
  77. nvmath/bindings/cycublasMp.pxd +183 -0
  78. nvmath/bindings/cycudss.cp314-win_amd64.pyd +0 -0
  79. nvmath/bindings/cycudss.pxd +224 -0
  80. nvmath/bindings/cycufft.cp314-win_amd64.pyd +0 -0
  81. nvmath/bindings/cycufft.pxd +326 -0
  82. nvmath/bindings/cycufftMp.pxd +334 -0
  83. nvmath/bindings/cycurand.cp314-win_amd64.pyd +0 -0
  84. nvmath/bindings/cycurand.pxd +146 -0
  85. nvmath/bindings/cycusolver.cp314-win_amd64.pyd +0 -0
  86. nvmath/bindings/cycusolver.pxd +154 -0
  87. nvmath/bindings/cycusolverDn.cp314-win_amd64.pyd +0 -0
  88. nvmath/bindings/cycusolverDn.pxd +446 -0
  89. nvmath/bindings/cycusparse.cp314-win_amd64.pyd +0 -0
  90. nvmath/bindings/cycusparse.pxd +470 -0
  91. nvmath/bindings/cycusparseLt.cp314-win_amd64.pyd +0 -0
  92. nvmath/bindings/cycusparseLt.pxd +150 -0
  93. nvmath/bindings/cycutensor.cp314-win_amd64.pyd +0 -0
  94. nvmath/bindings/cycutensor.pxd +192 -0
  95. nvmath/bindings/cymathdx.cp314-win_amd64.pyd +0 -0
  96. nvmath/bindings/cymathdx.pxd +552 -0
  97. nvmath/bindings/cynvshmem.pxd +126 -0
  98. nvmath/bindings/mathdx.cp314-win_amd64.pyd +0 -0
  99. nvmath/bindings/mathdx.pxd +182 -0
  100. nvmath/bindings/mathdx.pyi +1244 -0
  101. nvmath/bindings/nvpl/__init__.pxd +0 -0
  102. nvmath/bindings/nvpl/__init__.py +13 -0
  103. nvmath/bindings/nvpl/_internal/__init__.pxd +0 -0
  104. nvmath/bindings/nvpl/_internal/__init__.py +0 -0
  105. nvmath/bindings/nvpl/_internal/blas.cp314-win_amd64.pyd +0 -0
  106. nvmath/bindings/nvpl/_internal/blas.pxd +125 -0
  107. nvmath/bindings/nvpl/_internal/fft.cp314-win_amd64.pyd +0 -0
  108. nvmath/bindings/nvpl/_internal/fft.pxd +36 -0
  109. nvmath/bindings/nvpl/blas.cp314-win_amd64.pyd +0 -0
  110. nvmath/bindings/nvpl/blas.pxd +85 -0
  111. nvmath/bindings/nvpl/blas.pyi +122 -0
  112. nvmath/bindings/nvpl/cyblas.cp314-win_amd64.pyd +0 -0
  113. nvmath/bindings/nvpl/cyblas.pxd +166 -0
  114. nvmath/bindings/nvpl/cyfft.cp314-win_amd64.pyd +0 -0
  115. nvmath/bindings/nvpl/cyfft.pxd +92 -0
  116. nvmath/bindings/nvpl/fft.cp314-win_amd64.pyd +0 -0
  117. nvmath/bindings/nvpl/fft.pxd +100 -0
  118. nvmath/bindings/nvpl/fft.pyi +100 -0
  119. nvmath/bindings/nvshmem.pxd +54 -0
  120. nvmath/bindings/nvshmem.pyi +179 -0
  121. nvmath/device/__init__.py +21 -0
  122. nvmath/device/_deprecated.py +33 -0
  123. nvmath/device/common.py +313 -0
  124. nvmath/device/common_backend.py +131 -0
  125. nvmath/device/common_cuda.py +201 -0
  126. nvmath/device/common_numba.py +310 -0
  127. nvmath/device/common_opaque_tensor.py +201 -0
  128. nvmath/device/cublasdx.py +1805 -0
  129. nvmath/device/cublasdx_backend.py +807 -0
  130. nvmath/device/cublasdx_numba.py +1612 -0
  131. nvmath/device/cufftdx.py +510 -0
  132. nvmath/device/cufftdx_backend.py +196 -0
  133. nvmath/device/cufftdx_numba.py +196 -0
  134. nvmath/device/curand_kernel.py +9147 -0
  135. nvmath/device/cusolverdx.py +2690 -0
  136. nvmath/device/cusolverdx_backend.py +440 -0
  137. nvmath/device/cusolverdx_numba.py +1624 -0
  138. nvmath/device/llvm_array.py +29 -0
  139. nvmath/device/random.py +445 -0
  140. nvmath/device/random_helpers.py +23 -0
  141. nvmath/device/random_states.py +187 -0
  142. nvmath/device/types.py +147 -0
  143. nvmath/device/vector_types_numba.py +203 -0
  144. nvmath/distributed/__init__.py +205 -0
  145. nvmath/distributed/_internal/__init__.py +0 -0
  146. nvmath/distributed/_internal/nvshmem.py +302 -0
  147. nvmath/distributed/_internal/tensor_ifc.py +67 -0
  148. nvmath/distributed/_internal/tensor_ifc_cupy.py +62 -0
  149. nvmath/distributed/_internal/tensor_ifc_host_device.py +165 -0
  150. nvmath/distributed/_internal/tensor_ifc_numpy.py +41 -0
  151. nvmath/distributed/_internal/tensor_ifc_torch.py +141 -0
  152. nvmath/distributed/_internal/tensor_wrapper.py +78 -0
  153. nvmath/distributed/_utils.py +167 -0
  154. nvmath/distributed/distribution.py +770 -0
  155. nvmath/distributed/fft/__init__.py +7 -0
  156. nvmath/distributed/fft/_configuration.py +79 -0
  157. nvmath/distributed/fft/fft.py +2801 -0
  158. nvmath/distributed/linalg/__init__.py +12 -0
  159. nvmath/distributed/linalg/_internal/__init__.py +3 -0
  160. nvmath/distributed/linalg/_internal/epilog_protocol.py +496 -0
  161. nvmath/distributed/linalg/_internal/matmul_desc_ifc.py +28 -0
  162. nvmath/distributed/linalg/advanced/__init__.py +8 -0
  163. nvmath/distributed/linalg/advanced/_configuration.py +166 -0
  164. nvmath/distributed/linalg/advanced/matmulmod.py +2908 -0
  165. nvmath/distributed/process_group.py +408 -0
  166. nvmath/distributed/reshape/__init__.py +6 -0
  167. nvmath/distributed/reshape/_configuration.py +39 -0
  168. nvmath/distributed/reshape/reshape.py +1256 -0
  169. nvmath/fft/__init__.py +7 -0
  170. nvmath/fft/_configuration.py +208 -0
  171. nvmath/fft/_exec_utils.py +109 -0
  172. nvmath/fft/_helpers.py +237 -0
  173. nvmath/fft/fft.py +2903 -0
  174. nvmath/internal/__init__.pxd +3 -0
  175. nvmath/internal/__init__.py +10 -0
  176. nvmath/internal/_bindings.cp314-win_amd64.pyd +0 -0
  177. nvmath/internal/_bindings.pxd +12 -0
  178. nvmath/internal/_device_utils.py +54 -0
  179. nvmath/internal/enum_utils.py +142 -0
  180. nvmath/internal/formatters.py +87 -0
  181. nvmath/internal/mem_limit.py +51 -0
  182. nvmath/internal/memory.cp314-win_amd64.pyd +0 -0
  183. nvmath/internal/memory.pxd +10 -0
  184. nvmath/internal/memory.pyi +46 -0
  185. nvmath/internal/ndbuffer/__init__.pxd +3 -0
  186. nvmath/internal/ndbuffer/__init__.py +7 -0
  187. nvmath/internal/ndbuffer/copy_kernel/args.h +34 -0
  188. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/array_view.h +52 -0
  189. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/elementwise.h +68 -0
  190. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/grid_indexer.h +69 -0
  191. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/transposed.h +240 -0
  192. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/type_utils.h +39 -0
  193. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/utils.h +132 -0
  194. nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/vec.h +159 -0
  195. nvmath/internal/ndbuffer/copy_kernel/elementwise.h +53 -0
  196. nvmath/internal/ndbuffer/copy_kernel/transposed.h +58 -0
  197. nvmath/internal/ndbuffer/copy_kernel.cp314-win_amd64.pyd +0 -0
  198. nvmath/internal/ndbuffer/copy_kernel.pxd +9 -0
  199. nvmath/internal/ndbuffer/copy_kernel.pyi +9 -0
  200. nvmath/internal/ndbuffer/data_layout.cp314-win_amd64.pyd +0 -0
  201. nvmath/internal/ndbuffer/data_layout.pxd +72 -0
  202. nvmath/internal/ndbuffer/data_layout.pyi +23 -0
  203. nvmath/internal/ndbuffer/jit.cp314-win_amd64.pyd +0 -0
  204. nvmath/internal/ndbuffer/jit.pxd +7 -0
  205. nvmath/internal/ndbuffer/jit.pyi +6 -0
  206. nvmath/internal/ndbuffer/ndbuffer.cp314-win_amd64.pyd +0 -0
  207. nvmath/internal/ndbuffer/ndbuffer.pxd +36 -0
  208. nvmath/internal/ndbuffer/ndbuffer.pyi +41 -0
  209. nvmath/internal/ndbuffer/package_utils.cp314-win_amd64.pyd +0 -0
  210. nvmath/internal/ndbuffer/package_utils.pxd +11 -0
  211. nvmath/internal/ndbuffer/package_utils.pyi +12 -0
  212. nvmath/internal/package_ifc.py +147 -0
  213. nvmath/internal/package_ifc_cuda.py +49 -0
  214. nvmath/internal/package_ifc_cupy.py +49 -0
  215. nvmath/internal/package_ifc_torch.py +31 -0
  216. nvmath/internal/package_wrapper.py +14 -0
  217. nvmath/internal/tensor_ifc.py +194 -0
  218. nvmath/internal/tensor_ifc_cupy.py +241 -0
  219. nvmath/internal/tensor_ifc_ndbuffer.py +153 -0
  220. nvmath/internal/tensor_ifc_numpy.py +183 -0
  221. nvmath/internal/tensor_ifc_torch.py +176 -0
  222. nvmath/internal/tensor_wrapper.py +157 -0
  223. nvmath/internal/typemaps.py +162 -0
  224. nvmath/internal/utils.py +771 -0
  225. nvmath/linalg/__init__.py +46 -0
  226. nvmath/linalg/_internal/__init__.py +3 -0
  227. nvmath/linalg/_internal/algo_cap_ifc.py +82 -0
  228. nvmath/linalg/_internal/algo_config_ifc.py +43 -0
  229. nvmath/linalg/_internal/batch.py +217 -0
  230. nvmath/linalg/_internal/enum_to_tuples.py +64 -0
  231. nvmath/linalg/_internal/epilog_protocol.py +766 -0
  232. nvmath/linalg/_internal/layout.py +624 -0
  233. nvmath/linalg/_internal/matmul_desc_ifc.py +28 -0
  234. nvmath/linalg/_internal/matmul_pref_ifc.py +27 -0
  235. nvmath/linalg/_internal/matrix_layout_ifc.py +26 -0
  236. nvmath/linalg/_internal/typemaps.py +144 -0
  237. nvmath/linalg/_internal/utils.py +134 -0
  238. nvmath/linalg/advanced/__init__.py +8 -0
  239. nvmath/linalg/advanced/_algorithmmod.py +149 -0
  240. nvmath/linalg/advanced/_configuration.py +349 -0
  241. nvmath/linalg/advanced/helpers/__init__.py +5 -0
  242. nvmath/linalg/advanced/helpers/matmul.py +1348 -0
  243. nvmath/linalg/advanced/matmulmod.py +3937 -0
  244. nvmath/linalg/generic/__init__.py +43 -0
  245. nvmath/linalg/generic/_configuration/__init__.py +37 -0
  246. nvmath/linalg/generic/_configuration/layout.py +263 -0
  247. nvmath/linalg/generic/_configuration/match.py +609 -0
  248. nvmath/linalg/generic/_configuration/qualifiers.py +494 -0
  249. nvmath/linalg/generic/_configuration/wrap.py +217 -0
  250. nvmath/linalg/generic/_dtype.py +15 -0
  251. nvmath/linalg/generic/matmulmod.py +1060 -0
  252. nvmath/memory.py +282 -0
  253. nvmath/sparse/__init__.py +38 -0
  254. nvmath/sparse/_internal/__init__.py +21 -0
  255. nvmath/sparse/_internal/common_utils.py +144 -0
  256. nvmath/sparse/_internal/cudss_config_ifc.py +741 -0
  257. nvmath/sparse/_internal/cudss_data_ifc.py +399 -0
  258. nvmath/sparse/_internal/cudss_utils.py +445 -0
  259. nvmath/sparse/_internal/cusparse_utils.py +382 -0
  260. nvmath/sparse/_internal/sparse_bsc_ifc.py +300 -0
  261. nvmath/sparse/_internal/sparse_bsr_ifc.py +303 -0
  262. nvmath/sparse/_internal/sparse_coo_ifc.py +254 -0
  263. nvmath/sparse/_internal/sparse_csc_ifc.py +266 -0
  264. nvmath/sparse/_internal/sparse_csr_ifc.py +266 -0
  265. nvmath/sparse/_internal/sparse_dia_ifc.py +239 -0
  266. nvmath/sparse/_internal/sparse_format_helpers.py +601 -0
  267. nvmath/sparse/_internal/sparse_tensor_ifc.py +121 -0
  268. nvmath/sparse/_internal/sparse_ust_ifc.py +146 -0
  269. nvmath/sparse/_internal/utils.py +56 -0
  270. nvmath/sparse/advanced/__init__.py +7 -0
  271. nvmath/sparse/advanced/_configuration.py +230 -0
  272. nvmath/sparse/advanced/direct_solver.py +1884 -0
  273. nvmath/sparse/generic/__init__.py +7 -0
  274. nvmath/sparse/generic/_configuration.py +129 -0
  275. nvmath/sparse/generic/_helpers.py +137 -0
  276. nvmath/sparse/generic/_thunks.py +21 -0
  277. nvmath/sparse/generic/matmulmod.py +2426 -0
  278. nvmath/sparse/ust/__init__.py +7 -0
  279. nvmath/sparse/ust/_converters.py +378 -0
  280. nvmath/sparse/ust/_drawer.py +552 -0
  281. nvmath/sparse/ust/_emitter.py +553 -0
  282. nvmath/sparse/ust/_jit.py +212 -0
  283. nvmath/sparse/ust/_kernel.py +346 -0
  284. nvmath/sparse/ust/_semiring.py +71 -0
  285. nvmath/sparse/ust/_utils.py +102 -0
  286. nvmath/sparse/ust/interfaces/__init__.py +0 -0
  287. nvmath/sparse/ust/interfaces/torch_interface.py +476 -0
  288. nvmath/sparse/ust/semiring_ops.py +71 -0
  289. nvmath/sparse/ust/tensor.py +1027 -0
  290. nvmath/sparse/ust/tensor_drawer.py +552 -0
  291. nvmath/sparse/ust/tensor_emitter.py +558 -0
  292. nvmath/sparse/ust/tensor_format.py +935 -0
  293. nvmath/sparse/ust/tensor_jit.py +212 -0
  294. nvmath/sparse/ust/tensor_kernel.py +348 -0
  295. nvmath/sparse/ust/tensor_utils.py +380 -0
  296. nvmath/tensor/__init__.py +6 -0
  297. nvmath/tensor/_configuration.py +95 -0
  298. nvmath/tensor/_internal/__init__.py +3 -0
  299. nvmath/tensor/_internal/cutensor_config_ifc.py +247 -0
  300. nvmath/tensor/_internal/cutensor_utils.py +162 -0
  301. nvmath/tensor/_internal/data.py +43 -0
  302. nvmath/tensor/_internal/einsum_parser.py +444 -0
  303. nvmath/tensor/_internal/typemaps.py +96 -0
  304. nvmath/tensor/contract.py +1861 -0
  305. nvmath_python-0.9.0.dist-info/METADATA +127 -0
  306. nvmath_python-0.9.0.dist-info/RECORD +309 -0
  307. nvmath_python-0.9.0.dist-info/WHEEL +5 -0
  308. nvmath_python-0.9.0.dist-info/licenses/LICENSE +177 -0
  309. nvmath_python-0.9.0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,807 @@
1
+ # Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ __all__ = ["LeadingDimension", "TransposeMode", "Arrangement", "Alignment", "Precision"]
6
+
7
+ import weakref
8
+ from collections import namedtuple
9
+ from collections.abc import Sequence
10
+ from functools import lru_cache
11
+ from typing import NamedTuple, Protocol
12
+
13
+ import numpy as np
14
+
15
+ from nvmath.bindings import mathdx
16
+
17
+ from .common import check_in, check_sm
18
+ from .common_backend import (
19
+ EXECUTION_STR_TO_MATHDX,
20
+ NP_TYPES_TO_MATHDX_PRECISION,
21
+ NP_TYPES_TO_MATHDX_TYPES,
22
+ NVARG_GEN_OPT_LTO,
23
+ DescriptorWrapper,
24
+ build_get_int_traits,
25
+ build_get_str_trait,
26
+ get_isa_version,
27
+ get_lto,
28
+ get_mathdx_sm,
29
+ set_code_target_sm,
30
+ )
31
+ from .common_cuda import Code, CodeType, ComputeCapability, Dim3, ISAVersion
32
+ from .types import INT_NP_TYPES, REAL_NP_TYPES
33
+
34
+ try:
35
+ from cuda.core import (
36
+ Kernel,
37
+ Linker,
38
+ LinkerOptions,
39
+ ObjectCode,
40
+ Program,
41
+ ProgramOptions,
42
+ )
43
+ except ImportError:
44
+ from cuda.core.experimental import (
45
+ Kernel,
46
+ Linker,
47
+ LinkerOptions,
48
+ ObjectCode,
49
+ Program,
50
+ ProgramOptions,
51
+ )
52
+
53
+
54
+ _BLAS_API_STR_TO_MATHDX = {
55
+ "static_leading_dimensions": mathdx.CublasdxApi.SMEM,
56
+ "dynamic_leading_dimensions": mathdx.CublasdxApi.SMEM_DYNAMIC_LD,
57
+ "tensors": mathdx.CublasdxApi.TENSORS,
58
+ }
59
+
60
+ _BLAS_ARRENGEMENT_STR_TO_MATHDX = {a.name.lower(): a for a in mathdx.CublasdxArrangement}
61
+
62
+ _BLAS_TYPE_STR_TO_MATHDX = {t.name.lower(): t for t in mathdx.CublasdxType}
63
+
64
+ _BLAS_TRANSPOSE_STR_TO_MATHDX = {tm.name.lower(): tm for tm in mathdx.CublasdxTransposeMode}
65
+
66
+ _BLAS_FUNCTION_STR_TO_MATHDX = {
67
+ "MM": mathdx.CublasdxFunction.MM,
68
+ }
69
+
70
+ _TENSOR_TYPE_STR_TO_MATHDX = {t.name.lower(): t for t in mathdx.CublasdxTensorType}
71
+
72
+
73
+ def check_blas_sm(sm, library_name: str, var_name: str = "sm"):
74
+ check_sm(sm, library_name, var_name)
75
+ if sm.arch == "a" and sm.integer not in {900, 1000, 1030, 1100}:
76
+ raise ValueError(f"SM modifiers other than generic are only supported for SM 900, 1000, 1030, 1100, got {sm}")
77
+
78
+
79
+ class LeadingDimension(namedtuple("LeadingDimension", ["a", "b", "c"])):
80
+ """
81
+ A namedtuple class that encapsulates the three leading dimensions in matrix
82
+ multiplication :math:`C = \\alpha Op(A) Op(B) + \\beta C`.
83
+
84
+ Attributes:
85
+ a (int): The leading dimension of two-dimensional array used to store the matrix
86
+ ``A``.
87
+
88
+ b (int): The leading dimension of two-dimensional array used to store the matrix
89
+ ``B``.
90
+
91
+ c (int): The leading dimension of two-dimensional array used to store the matrix
92
+ ``C``.
93
+ """
94
+
95
+ __slots__ = ()
96
+
97
+
98
+ class TransposeMode(namedtuple("TransposeMode", ["a", "b"])):
99
+ """
100
+ A namedtuple class that encapsulates the transpose mode for input matrices ``A`` and
101
+ ``B`` in matrix multiplication.
102
+
103
+ Attributes:
104
+ a: The operation that needs to be performed with input matrix ``A``, currently
105
+ supports ``'non_transposed'``, ``'transposed'`` and ``'conj_transposed'``.
106
+
107
+ b: The operation that needs to be performed with input matrix ``B``, currently
108
+ supports ``'non_transposed'``, ``'transposed'`` and ``'conj_transposed'``.
109
+ """
110
+
111
+ __slots__ = ()
112
+
113
+
114
+ class Arrangement(NamedTuple):
115
+ """
116
+ A namedtuple class that encapsulates the three arrangements in matrix allocation.
117
+
118
+ Attributes:
119
+ a (str): The arrangement of two-dimensional array used to store the matrix
120
+ ``A``.
121
+
122
+ b (str): The arrangement of two-dimensional array used to store the matrix
123
+ ``B``.
124
+
125
+ c (str): The arrangement of two-dimensional array used to store the matrix
126
+ ``C``.
127
+ """
128
+
129
+ a: str
130
+ b: str
131
+ c: str
132
+
133
+
134
+ class Precision(NamedTuple):
135
+ """
136
+ A namedtuple class that encapsulates the three precisions in matrix
137
+ multiplication :math:`C = \\alpha Op(A) Op(B) + \\beta C`.
138
+
139
+ Attributes:
140
+ a (type): The precision of two-dimensional array used to store the matrix
141
+ ``A``.
142
+
143
+ b (type): The precision of two-dimensional array used to store the matrix
144
+ ``B``.
145
+
146
+ c (type): The precision of two-dimensional array used to store the matrix
147
+ ``C``.
148
+ """
149
+
150
+ a: type[object]
151
+ b: type[object]
152
+ c: type[object]
153
+
154
+
155
+ class Alignment(NamedTuple):
156
+ """
157
+ A type to encapsulate the memory alignment in bytes of the matrix operands
158
+ A, B, and C.
159
+
160
+ Attributes:
161
+ a (int): The alignment of two-dimensional array used to store the matrix
162
+ ``A``.
163
+
164
+ b (int): The alignment of two-dimensional array used to store the matrix
165
+ ``B``.
166
+
167
+ c (int): The alignment of two-dimensional array used to store the matrix
168
+ ``C``.
169
+ """
170
+
171
+ a: int
172
+ b: int
173
+ c: int
174
+
175
+
176
+ class CublasdxTensors(NamedTuple):
177
+ a: int
178
+ b: int
179
+ c: int
180
+
181
+
182
+ class CublasdxTensorsResponse:
183
+ target: CublasdxTensors
184
+
185
+ def __init__(self, target: CublasdxTensors):
186
+ self.target = target
187
+
188
+
189
+ MAX_ALIGNMENT = Alignment(16, 16, 16)
190
+
191
+
192
+ class CallableGetIntTraits(Protocol):
193
+ def __call__(self, handle: int, trait_type: mathdx.CublasdxTraitType, size: int) -> tuple: ...
194
+
195
+
196
+ class CallableGetStrTrait(Protocol):
197
+ def __call__(self, handle: int, trait_type: mathdx.CublasdxTraitType) -> str: ...
198
+
199
+
200
+ get_int_traits: CallableGetIntTraits = build_get_int_traits(mathdx.cublasdx_get_trait_int64s)
201
+
202
+ get_str_trait: CallableGetStrTrait = build_get_str_trait(mathdx.cublasdx_get_trait_str_size, mathdx.cublasdx_get_trait_str)
203
+
204
+ get_str_device_trait: CallableGetStrTrait = build_get_str_trait(
205
+ mathdx.cublasdx_get_device_function_trait_str_size, mathdx.cublasdx_get_device_function_trait_str
206
+ )
207
+
208
+
209
+ def get_tensor_int_traits(tensors: CublasdxTensors, trait: mathdx.CublasdxTensorTrait):
210
+ return (
211
+ int(mathdx.cublasdx_get_tensor_trait_int64(tensors.a, trait)),
212
+ int(mathdx.cublasdx_get_tensor_trait_int64(tensors.b, trait)),
213
+ int(mathdx.cublasdx_get_tensor_trait_int64(tensors.c, trait)),
214
+ )
215
+
216
+
217
+ _ACCEPTED_PRECISION = REAL_NP_TYPES + INT_NP_TYPES
218
+
219
+
220
+ def validate(
221
+ size,
222
+ data_type,
223
+ precision,
224
+ execution,
225
+ transpose_mode,
226
+ arrangement,
227
+ alignment,
228
+ block_dim,
229
+ sm,
230
+ function,
231
+ leading_dimension,
232
+ static_block_dim,
233
+ with_pipeline,
234
+ enable_input_streaming,
235
+ ):
236
+ (m, n, k) = size
237
+ if m <= 0 or n <= 0 or k <= 0:
238
+ raise ValueError(f"m, n, k must be > 0. Got {m}, {n}, {k}")
239
+ if isinstance(precision, Precision):
240
+ for m in ["a", "b", "c"]:
241
+ check_in(f"precision.{m}", getattr(precision, m), _ACCEPTED_PRECISION)
242
+ else:
243
+ raise ValueError(
244
+ f"precision should be an instance of {Precision} or a 3-sequence, and individual fields "
245
+ f"should be one of {_ACCEPTED_PRECISION}. Instead got precision = {precision}"
246
+ )
247
+ check_blas_sm(sm, "sm")
248
+ check_in("data_type", data_type, ["real", "complex"])
249
+ check_in("execution", execution, ["Block", "Thread"])
250
+ check_in("function", function, ["MM"])
251
+ check_in("static_block_dim", static_block_dim, [True, False])
252
+ if transpose_mode is not None:
253
+ allowed_values = ["non_transposed", "transposed", "conj_transposed"]
254
+ if isinstance(transpose_mode, TransposeMode):
255
+ check_in("transpose_mode.a", transpose_mode.a, allowed_values)
256
+ check_in("transpose_mode.b", transpose_mode.b, allowed_values)
257
+ else:
258
+ raise ValueError(
259
+ f"transpose_mode should be an instance of {TransposeMode} or a 2-tuple, and individual fields "
260
+ f"should be one of {allowed_values}. Instead got transpose_mode = {transpose_mode}"
261
+ )
262
+ if arrangement is not None:
263
+ allowed_values = _BLAS_ARRENGEMENT_STR_TO_MATHDX.keys()
264
+ if isinstance(arrangement, Arrangement):
265
+ check_in("arrangement.a", arrangement.a, allowed_values)
266
+ check_in("arrangement.b", arrangement.b, allowed_values)
267
+ check_in("arrangement.c", arrangement.c, allowed_values)
268
+ else:
269
+ raise ValueError(
270
+ f"arrangement should be an instance of {Arrangement} or a 3-tuple, and individual fields "
271
+ f"should be one of {allowed_values}. Instead got arrangement = {arrangement}"
272
+ )
273
+ if arrangement is not None and transpose_mode is not None:
274
+ raise ValueError("only arrangement or transpose_mode must be provide. Instead got both")
275
+ if arrangement is None and transpose_mode is None:
276
+ raise ValueError("arrangement or transpose_mode must be provide. Instead got nothing")
277
+ if alignment is not None:
278
+ validate_alignment(alignment, precision, data_type)
279
+ if block_dim in (None, "suggested"):
280
+ pass
281
+ elif isinstance(block_dim, Dim3):
282
+ prod = block_dim[0] * block_dim[1] * block_dim[2]
283
+ if prod <= 0 or prod > 1024:
284
+ raise ValueError(
285
+ f"The product of the entries in block_dim should be between 1 and 1024 ; got block_dim = {block_dim}"
286
+ )
287
+ else:
288
+ raise ValueError(f"block_dim should be None, a Dim3 instance or 'suggested'; got block_dim = {block_dim}")
289
+ if leading_dimension in (None, "suggested") or isinstance(leading_dimension, LeadingDimension):
290
+ pass
291
+ else:
292
+ raise ValueError(
293
+ f"leading_dimension should be None, a LeadingDimension instance or 'suggested'; "
294
+ f"got leading_dimension = {leading_dimension}"
295
+ )
296
+ if not isinstance(with_pipeline, bool):
297
+ raise ValueError(f"with_pipeline should be a bool; got with_pipeline = {with_pipeline}")
298
+ if not isinstance(enable_input_streaming, bool):
299
+ raise ValueError(f"enable_input_streaming should be a bool; got enable_input_streaming = {enable_input_streaming}")
300
+
301
+
302
+ def validate_execute_api(execute_api):
303
+ """
304
+ Validate the execute_api argument.
305
+ """
306
+ check_in("execute_api", execute_api, _BLAS_API_STR_TO_MATHDX.keys())
307
+
308
+
309
+ def validate_tensor_types(tensor_types):
310
+ """
311
+ Validate the tensor_types argument.
312
+ """
313
+ allowed_values = _TENSOR_TYPE_STR_TO_MATHDX.keys()
314
+ if isinstance(tensor_types, Sequence) and len(tensor_types) == 3:
315
+ check_in("tensor_types[0]", tensor_types[0], allowed_values)
316
+ check_in("tensor_types[1]", tensor_types[1], allowed_values)
317
+ check_in("tensor_types[2]", tensor_types[2], allowed_values)
318
+ else:
319
+ raise ValueError(
320
+ f"tensor_types should be a 3-tuple, and individual fields "
321
+ f"should be one of {allowed_values}. Instead got tensor_types = {tensor_types}"
322
+ )
323
+
324
+
325
+ def validate_alignment(alignment: Alignment, precision: Precision, data_type: str, gmem: bool = False):
326
+ """
327
+ Validates alignment. precision and data_type must be already validated.
328
+ """
329
+ name = "alignment" if not gmem else "global_memory_alignment"
330
+ default_a = default_alignment(precision, data_type)
331
+ for m in ["a", "b", "c"]:
332
+ a = getattr(alignment, m)
333
+ max_a = getattr(MAX_ALIGNMENT, m)
334
+ def_a = getattr(default_a, m)
335
+ if a <= 0:
336
+ raise ValueError(f"{name}.{m} must be > 0. Got {a}")
337
+ if a > max_a:
338
+ raise ValueError(f"{name}.{m} must be less than maximum alignment {max_a}. Got {a}")
339
+ if a % def_a != 0:
340
+ raise ValueError(f"{name}.{m} must be a multiple of input value type {def_a}. Got {a}")
341
+
342
+
343
+ def default_alignment(precision: Precision, data_type: str):
344
+ # supported precision's itemsize is always power of two, so we are safe
345
+ mul = 1 if data_type == "real" else 2
346
+
347
+ alignment = tuple(np.dtype(p).itemsize * mul for p in precision)
348
+ return Alignment(*alignment)
349
+
350
+
351
+ @lru_cache
352
+ def generate_MM(
353
+ size: tuple[int, int, int],
354
+ precision: Precision,
355
+ data_type: str,
356
+ function: str,
357
+ transpose_mode: TransposeMode | None,
358
+ arrangement: Arrangement | None,
359
+ alignment: Alignment | None,
360
+ sm: ComputeCapability,
361
+ block_dim: Dim3 | None,
362
+ static_block_dim: bool,
363
+ execution: str,
364
+ leading_dimension: LeadingDimension | None = None,
365
+ execute_api: str | None = None,
366
+ tensor_types: tuple[str, str, str] | None = None,
367
+ with_pipeline: bool = False,
368
+ enable_input_streaming: bool = False,
369
+ ):
370
+ """
371
+ Generate a cuBLASDx descriptor for matrix multiplication.
372
+
373
+ tenosr_types is only used to create cache properly.
374
+ """
375
+ h = mathdx.cublasdx_create_descriptor()
376
+
377
+ (m, n, k) = size
378
+
379
+ # TODO: remove once libmathdx supports it
380
+ if execute_api is None:
381
+ execute_api = "static_leading_dimensions"
382
+
383
+ if execute_api is not None:
384
+ mathdx.cublasdx_set_operator_int64(h, mathdx.CublasdxOperatorType.API, _BLAS_API_STR_TO_MATHDX[execute_api])
385
+
386
+ mathdx.cublasdx_set_operator_int64s(h, mathdx.CublasdxOperatorType.SIZE, 3, [m, n, k])
387
+ mathdx.cublasdx_set_operator_int64s(
388
+ h, mathdx.CublasdxOperatorType.PRECISION, len(precision), [NP_TYPES_TO_MATHDX_PRECISION[p] for p in precision]
389
+ )
390
+
391
+ mathdx.cublasdx_set_operator_int64(h, mathdx.CublasdxOperatorType.FUNCTION, _BLAS_FUNCTION_STR_TO_MATHDX[function])
392
+ mathdx.cublasdx_set_operator_int64(h, mathdx.CublasdxOperatorType.EXECUTION, EXECUTION_STR_TO_MATHDX[execution])
393
+ mathdx.cublasdx_set_operator_int64(h, mathdx.CublasdxOperatorType.TYPE, _BLAS_TYPE_STR_TO_MATHDX[data_type])
394
+
395
+ sm_mathdx = get_mathdx_sm(sm)
396
+ mathdx.cublasdx_set_operator_int64s(h, mathdx.CublasdxOperatorType.SM, len(sm_mathdx), sm_mathdx)
397
+
398
+ if block_dim:
399
+ mathdx.cublasdx_set_operator_int64s(h, mathdx.CublasdxOperatorType.BLOCK_DIM, 3, block_dim)
400
+
401
+ if static_block_dim:
402
+ mathdx.cublasdx_set_operator_int64(h, mathdx.CublasdxOperatorType.STATIC_BLOCK_DIM, 1)
403
+
404
+ if leading_dimension:
405
+ mathdx.cublasdx_set_operator_int64s(
406
+ h, mathdx.CublasdxOperatorType.LEADING_DIMENSION, 3, [leading_dimension.a, leading_dimension.b, leading_dimension.c]
407
+ )
408
+
409
+ if transpose_mode:
410
+ mathdx.cublasdx_set_operator_int64s(
411
+ h,
412
+ mathdx.CublasdxOperatorType.TRANSPOSE_MODE,
413
+ 2,
414
+ [_BLAS_TRANSPOSE_STR_TO_MATHDX[transpose_mode.a], _BLAS_TRANSPOSE_STR_TO_MATHDX[transpose_mode.b]],
415
+ )
416
+
417
+ if arrangement:
418
+ mathdx.cublasdx_set_operator_int64s(
419
+ h,
420
+ mathdx.CublasdxOperatorType.ARRANGEMENT,
421
+ 3,
422
+ [_BLAS_ARRENGEMENT_STR_TO_MATHDX[a] for a in arrangement],
423
+ )
424
+
425
+ if alignment:
426
+ mathdx.cublasdx_set_operator_int64s(
427
+ h,
428
+ mathdx.CublasdxOperatorType.ALIGNMENT,
429
+ 3,
430
+ alignment,
431
+ )
432
+
433
+ if with_pipeline:
434
+ mathdx.cublasdx_set_operator_int64(h, mathdx.CublasdxOperatorType.WITH_PIPELINE, 1)
435
+
436
+ if enable_input_streaming:
437
+ mathdx.cublasdx_set_operator_int64(h, mathdx.CublasdxOperatorType.ENABLE_INPUT_STREAMING, 1)
438
+
439
+ return DescriptorWrapper(h, mathdx.cublasdx_destroy_descriptor)
440
+
441
+
442
+ @lru_cache
443
+ def generate_device_pipeline(
444
+ handle,
445
+ depth: int,
446
+ value_type_a: mathdx.CommondxValueType,
447
+ value_type_b: mathdx.CommondxValueType,
448
+ shape_a: list[int],
449
+ shape_b: list[int],
450
+ strides_a: list[int],
451
+ strides_b: list[int],
452
+ ) -> DescriptorWrapper:
453
+ assert len(shape_a) == len(strides_a)
454
+ assert len(shape_b) == len(strides_b)
455
+
456
+ big_gmem_a = mathdx.cublasdx_create_tensor_strided(
457
+ mathdx.CublasdxMemorySpace.GMEM, value_type_a, 0, len(shape_a), shape_a, strides_a
458
+ )
459
+ big_gmem_b = mathdx.cublasdx_create_tensor_strided(
460
+ mathdx.CublasdxMemorySpace.GMEM, value_type_b, 0, len(shape_b), shape_b, strides_b
461
+ )
462
+
463
+ device_pipeline = mathdx.cublasdx_create_device_pipeline(
464
+ handle,
465
+ mathdx.CublasdxDevicePipelineType.SUGGESTED,
466
+ depth,
467
+ # FIXED for accumulator, HEURISTIC for epilogue
468
+ mathdx.CublasdxBlockSizeStrategy.FIXED,
469
+ big_gmem_a,
470
+ big_gmem_b,
471
+ )
472
+
473
+ tensors = [big_gmem_a, big_gmem_b]
474
+ pipelines = [device_pipeline]
475
+
476
+ mathdx.cublasdx_finalize_pipelines(len(pipelines), pipelines)
477
+ mathdx.cublasdx_finalize_tensors(len(tensors), tensors)
478
+
479
+ return DescriptorWrapper(device_pipeline, mathdx.cublasdx_destroy_pipeline)
480
+
481
+
482
+ @lru_cache
483
+ def generate_tile_pipeline(
484
+ handle,
485
+ device_pipeline_handle,
486
+ ):
487
+ tile_pipeline = mathdx.cublasdx_create_tile_pipeline(
488
+ handle,
489
+ mathdx.CublasdxTilePipelineType.PIPELINE_DEFAULT,
490
+ device_pipeline_handle,
491
+ )
492
+
493
+ pipelines = [tile_pipeline]
494
+
495
+ mathdx.cublasdx_finalize_pipelines(len(pipelines), pipelines)
496
+
497
+ return DescriptorWrapper(tile_pipeline, mathdx.cublasdx_destroy_pipeline)
498
+
499
+
500
+ @lru_cache
501
+ def generate_code(handle, version: ComputeCapability, device_functions: tuple | None = None):
502
+ code = mathdx.commondx_create_code()
503
+
504
+ set_code_target_sm(code, version)
505
+ mathdx.commondx_set_code_option_str(code, mathdx.CommondxOption.EXTRA_NVRTC_ARGS, NVARG_GEN_OPT_LTO)
506
+ if device_functions:
507
+ mathdx.cublasdx_finalize_device_functions(code, len(device_functions), list(device_functions))
508
+ else:
509
+ mathdx.cublasdx_finalize_code(code, handle)
510
+
511
+ return DescriptorWrapper(code, mathdx.commondx_destroy_code)
512
+
513
+
514
+ @lru_cache
515
+ def generate_tensor(h: int, tensor_type: str, gmem_alignment: int | None = None) -> DescriptorWrapper:
516
+ tensor = mathdx.cublasdx_create_tensor(h, _TENSOR_TYPE_STR_TO_MATHDX[tensor_type])
517
+
518
+ if gmem_alignment is not None:
519
+ try:
520
+ mathdx.cublasdx_set_tensor_option_int64(
521
+ tensor,
522
+ mathdx.CublasdxTensorOption.ALIGNMENT_BYTES,
523
+ gmem_alignment,
524
+ )
525
+ except Exception:
526
+ print(f"[WARN] Failed to set {tensor_type} tensor alignment {gmem_alignment}")
527
+
528
+ mathdx.cublasdx_finalize_tensors(1, [tensor])
529
+
530
+ return DescriptorWrapper(tensor, mathdx.cublasdx_destroy_tensor)
531
+
532
+
533
+ @lru_cache
534
+ def generate_tensor_like(h: int, src_tensor: int, dtype: np.number) -> DescriptorWrapper:
535
+ dx_type = NP_TYPES_TO_MATHDX_TYPES[dtype]
536
+ dst_tensor = mathdx.cublasdx_make_tensor_like(src_tensor, dx_type)
537
+ mathdx.cublasdx_finalize_tensors(1, [dst_tensor])
538
+
539
+ return DescriptorWrapper(dst_tensor, mathdx.cublasdx_destroy_tensor)
540
+
541
+
542
+ @lru_cache
543
+ def get_tensor_traits(tensor: int) -> tuple[int, int, int, int]:
544
+ """Get tensor traits: (uid, logical_size, storage_bytes, alignment)"""
545
+ return (
546
+ int(mathdx.cublasdx_get_tensor_trait_int64(tensor, mathdx.CublasdxTensorTrait.UID)),
547
+ int(mathdx.cublasdx_get_tensor_trait_int64(tensor, mathdx.CublasdxTensorTrait.LOGICAL_SIZE)),
548
+ int(mathdx.cublasdx_get_tensor_trait_int64(tensor, mathdx.CublasdxTensorTrait.STORAGE_BYTES)),
549
+ int(mathdx.cublasdx_get_tensor_trait_int64(tensor, mathdx.CublasdxTensorTrait.ALIGNMENT_BYTES)),
550
+ )
551
+
552
+
553
+ def generate_function_code(
554
+ MM_handler: int, function_type: mathdx.CublasdxDeviceFunctionType, args: Sequence[int], version: ISAVersion
555
+ ):
556
+ function_handler = mathdx.cublasdx_create_device_function(MM_handler, function_type, len(args), list(args))
557
+ symbol = get_str_device_trait(function_handler, mathdx.CublasdxDeviceFunctionTrait.SYMBOL)
558
+ code = generate_code(MM_handler, version, (function_handler,))
559
+
560
+ return code, symbol
561
+
562
+
563
+ @lru_cache
564
+ def generate_function_with_pipelines_code(
565
+ MM_handler: int,
566
+ function_type: mathdx.CublasdxDeviceFunctionType,
567
+ tensors: tuple[int],
568
+ pipelines: tuple[int],
569
+ version: ISAVersion,
570
+ ):
571
+ function_handler = mathdx.cublasdx_create_device_function_with_pipelines(
572
+ MM_handler,
573
+ function_type,
574
+ len(tensors),
575
+ list(tensors),
576
+ len(pipelines),
577
+ list(pipelines),
578
+ )
579
+ symbol = get_str_device_trait(function_handler, mathdx.CublasdxDeviceFunctionTrait.SYMBOL)
580
+ code = generate_code(MM_handler, version, (function_handler,))
581
+
582
+ return code, symbol
583
+
584
+
585
+ def get_function_code(
586
+ MM_handler: int,
587
+ function_type: mathdx.CublasdxDeviceFunctionType,
588
+ args: Sequence[int],
589
+ code_type: CodeType,
590
+ ):
591
+ code, symbol = generate_function_code(MM_handler, function_type, args, code_type.cc)
592
+
593
+ # Compile
594
+ lto_fn = get_lto(code.descriptor)
595
+ isa_version = get_isa_version(code.descriptor)
596
+
597
+ lto = Code(code_type, isa_version, lto_fn)
598
+
599
+ return lto, symbol
600
+
601
+
602
+ @lru_cache
603
+ def generate_tensors(h, tensor_types):
604
+ type_mem_a = mathdx.cublasdx_create_tensor(h, _TENSOR_TYPE_STR_TO_MATHDX[tensor_types[0]])
605
+ type_mem_b = mathdx.cublasdx_create_tensor(h, _TENSOR_TYPE_STR_TO_MATHDX[tensor_types[1]])
606
+ type_mem_c = mathdx.cublasdx_create_tensor(h, _TENSOR_TYPE_STR_TO_MATHDX[tensor_types[2]])
607
+
608
+ tensors = [
609
+ type_mem_a,
610
+ type_mem_b,
611
+ type_mem_c,
612
+ ]
613
+
614
+ mathdx.cublasdx_finalize_tensors(len(tensors), tensors)
615
+
616
+ target_tensors = CublasdxTensors(type_mem_a, type_mem_b, type_mem_c)
617
+ resp = CublasdxTensorsResponse(target_tensors)
618
+
619
+ weakref.finalize(resp, destroy_tensors, resp.target)
620
+
621
+ return resp
622
+
623
+
624
+ def destroy_tensors(tensors: CublasdxTensors):
625
+ mathdx.cublasdx_destroy_tensor(tensors.a)
626
+ mathdx.cublasdx_destroy_tensor(tensors.b)
627
+ mathdx.cublasdx_destroy_tensor(tensors.c)
628
+
629
+
630
+ def generate_copy_wait_lto(compute_capability: ComputeCapability):
631
+ return generate_device_function_lto(
632
+ compute_capability,
633
+ mathdx.CublasdxDeviceFunctionType.COPY_WAIT,
634
+ (),
635
+ )
636
+
637
+
638
+ @lru_cache
639
+ def generate_device_function_lto(compute_capability: ComputeCapability, function_type: mathdx.CublasdxDeviceFunctionType, args):
640
+ # Create the cuBLASDx descriptor
641
+ h = mathdx.cublasdx_create_descriptor()
642
+ mathdx.cublasdx_set_operator_int64(h, mathdx.CublasdxOperatorType.FUNCTION, mathdx.CublasdxFunction.MM)
643
+ mathdx.cublasdx_set_operator_int64(h, mathdx.CublasdxOperatorType.EXECUTION, mathdx.CommondxExecution.BLOCK)
644
+ mathdx.cublasdx_set_operator_int64(h, mathdx.CublasdxOperatorType.API, mathdx.CublasdxApi.TENSORS)
645
+ mathdx.cublasdx_set_operator_int64(h, mathdx.CublasdxOperatorType.PRECISION, mathdx.CommondxPrecision.F32)
646
+ sm_mathdx = get_mathdx_sm(compute_capability)
647
+ mathdx.cublasdx_set_operator_int64s(h, mathdx.CublasdxOperatorType.SM, len(sm_mathdx), sm_mathdx)
648
+ mathdx.cublasdx_set_operator_int64(h, mathdx.CublasdxOperatorType.TYPE, mathdx.CublasdxType.REAL)
649
+ mathdx.cublasdx_set_operator_int64s(h, mathdx.CublasdxOperatorType.BLOCK_DIM, 3, [32, 1, 1])
650
+ mathdx.cublasdx_set_operator_int64s(h, mathdx.CublasdxOperatorType.SIZE, 3, [1, 1, 1])
651
+
652
+ function = mathdx.cublasdx_create_device_function(h, function_type, len(args), [*args])
653
+ symbol = get_str_device_trait(function, mathdx.CublasdxDeviceFunctionTrait.SYMBOL)
654
+
655
+ # Compile the device function to lto
656
+ code = mathdx.commondx_create_code()
657
+ set_code_target_sm(code, compute_capability)
658
+ mathdx.commondx_set_code_option_str(code, mathdx.CommondxOption.EXTRA_NVRTC_ARGS, NVARG_GEN_OPT_LTO)
659
+ mathdx.cublasdx_finalize_device_functions(code, 1, [function])
660
+
661
+ # Extract the LTOIR
662
+ lto_size = mathdx.commondx_get_code_ltoir_size(code)
663
+ lto = bytearray(lto_size)
664
+ mathdx.commondx_get_code_ltoir(code, lto_size, lto)
665
+
666
+ mathdx.commondx_destroy_code(code)
667
+ mathdx.cublasdx_destroy_device_function(function)
668
+ mathdx.cublasdx_destroy_descriptor(h)
669
+
670
+ return symbol, bytes(lto)
671
+
672
+
673
+ def _compile_blas_device_pipeline_init(
674
+ mm_descriptor: int,
675
+ pipeline_descriptor: int,
676
+ code_type: CodeType,
677
+ ) -> tuple[Code, str]:
678
+ assert isinstance(code_type, CodeType)
679
+
680
+ code, symbol = generate_function_with_pipelines_code(
681
+ mm_descriptor,
682
+ mathdx.CublasdxDeviceFunctionType.CREATE,
683
+ (),
684
+ (pipeline_descriptor,),
685
+ code_type.cc,
686
+ )
687
+
688
+ # Compile
689
+ lto_fn = get_lto(code.descriptor)
690
+ isa_version = get_isa_version(code.descriptor)
691
+
692
+ lto = Code(code_type, isa_version, lto_fn)
693
+
694
+ return lto, symbol
695
+
696
+
697
+ @lru_cache
698
+ def _compile_blas_device_pipeline_init_kernel(
699
+ mm_descriptor: int,
700
+ pipeline_descriptor: int,
701
+ code_type: CodeType,
702
+ ) -> Kernel:
703
+ lto, sym = _compile_blas_device_pipeline_init(mm_descriptor, pipeline_descriptor, code_type=code_type)
704
+ init_pipeline_func = ObjectCode.from_ltoir(lto.data)
705
+
706
+ # CUDA C source code for our kernel
707
+ init_pipeline_source = (
708
+ f"#define create_dev_pipe {sym}\n"
709
+ + """
710
+ struct libmathdx_tensor_0s_0s { void* ptr; };
711
+ struct libmathdx_pipeline { void* ptr; };
712
+
713
+ extern "C" __device__ void create_dev_pipe(libmathdx_pipeline, libmathdx_tensor_0s_0s, libmathdx_tensor_0s_0s);
714
+
715
+ extern "C" __global__ void create_device_pipeline(void* device_pipeline_ptr, void* ga_storage, void* gb_storage) {
716
+ auto ga = libmathdx_tensor_0s_0s { ga_storage };
717
+ auto gb = libmathdx_tensor_0s_0s { gb_storage };
718
+ auto device_pipeline = libmathdx_pipeline { device_pipeline_ptr };
719
+ create_dev_pipe(device_pipeline, ga, gb);
720
+ }
721
+ """
722
+ )
723
+
724
+ # Compiler arguments
725
+ arch = f"sm_{code_type.cc.major}{code_type.cc.minor}{code_type.cc.arch}"
726
+ program_options = ProgramOptions(link_time_optimization=True, arch=arch)
727
+ linker_options = LinkerOptions(link_time_optimization=True, arch=arch)
728
+
729
+ # Compile the CUDA code into a program
730
+ program = Program(init_pipeline_source, code_type="c++", options=program_options)
731
+ compiled_program = program.compile(target_type="ltoir")
732
+
733
+ linker = Linker(compiled_program, init_pipeline_func, options=linker_options)
734
+ linked_program = linker.link("cubin")
735
+
736
+ # Get the specific kernel function we want to use
737
+ kernel = linked_program.get_kernel("create_device_pipeline")
738
+
739
+ return kernel
740
+
741
+
742
+ def _compile_blas_device_pipeline_destroy(
743
+ mm_descriptor: int,
744
+ pipeline_descriptor: int,
745
+ code_type: CodeType,
746
+ ) -> tuple[Code, str]:
747
+ code, symbol = generate_function_with_pipelines_code(
748
+ mm_descriptor,
749
+ mathdx.CublasdxDeviceFunctionType.DESTROY,
750
+ (),
751
+ (pipeline_descriptor,),
752
+ code_type.cc,
753
+ )
754
+
755
+ # Compile
756
+ lto_fn = get_lto(code.descriptor)
757
+ isa_version = get_isa_version(code.descriptor)
758
+
759
+ lto = Code(code_type, isa_version, lto_fn)
760
+
761
+ return lto, symbol
762
+
763
+
764
+ @lru_cache
765
+ def _compile_blas_device_pipeline_destroy_kernel(
766
+ mm_descriptor: int,
767
+ pipeline_descriptor: int,
768
+ code_type: CodeType,
769
+ ) -> Kernel:
770
+ lto, sym = _compile_blas_device_pipeline_destroy(
771
+ mm_descriptor=mm_descriptor,
772
+ pipeline_descriptor=pipeline_descriptor,
773
+ code_type=code_type,
774
+ )
775
+ destroy_pipeline_func = ObjectCode.from_ltoir(lto.data)
776
+
777
+ # CUDA C source code for our kernel
778
+ destroy_pipeline_source = (
779
+ f"#define destroy_dev_pipe {sym}\n"
780
+ + """
781
+ struct libmathdx_pipeline { void* ptr; };
782
+
783
+ extern "C" __device__ void destroy_dev_pipe(libmathdx_pipeline);
784
+
785
+ extern "C" __global__ void destroy_device_pipeline(void* device_pipeline_ptr) {
786
+ auto device_pipeline = libmathdx_pipeline { device_pipeline_ptr };
787
+ destroy_dev_pipe(device_pipeline);
788
+ }
789
+ """
790
+ )
791
+
792
+ # Compiler arguments
793
+ arch = f"sm_{code_type.cc.major}{code_type.cc.minor}{code_type.cc.arch}"
794
+ program_options = ProgramOptions(link_time_optimization=True, arch=arch)
795
+ linker_options = LinkerOptions(link_time_optimization=True, arch=arch)
796
+
797
+ # Compile the CUDA code into a program
798
+ program = Program(destroy_pipeline_source, code_type="c++", options=program_options)
799
+ compiled_program = program.compile(target_type="ltoir")
800
+
801
+ linker = Linker(compiled_program, destroy_pipeline_func, options=linker_options)
802
+ linked_program = linker.link("cubin")
803
+
804
+ # Get the specific kernel function we want to use
805
+ kernel = linked_program.get_kernel("destroy_device_pipeline")
806
+
807
+ return kernel