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