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,212 @@
1
+ # Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ """
6
+ This module defines a JIT runtime for the universal sparse tensor (UST).
7
+ """
8
+
9
+ __all__ = ["launch_kernel"]
10
+
11
+ import re
12
+ from collections.abc import Sequence
13
+
14
+ from nvmath.internal import utils
15
+
16
+ # TODO: support cuda.core >=0.5.0
17
+ try:
18
+ from cuda.core import (
19
+ LaunchConfig,
20
+ Linker,
21
+ LinkerOptions,
22
+ ObjectCode,
23
+ Program,
24
+ ProgramOptions,
25
+ launch,
26
+ )
27
+ except ImportError:
28
+ from cuda.core.experimental import (
29
+ LaunchConfig,
30
+ Linker,
31
+ LinkerOptions,
32
+ ObjectCode,
33
+ Program,
34
+ ProgramOptions,
35
+ launch,
36
+ )
37
+
38
+
39
+ def _check_numba_available():
40
+ try:
41
+ import numba # noqa: F401
42
+ except ModuleNotFoundError as e:
43
+ raise RuntimeError("Numba is required to compile user-defined Python functions provided to the UST APIs.") from e
44
+
45
+
46
+ def compile_python_function(
47
+ function,
48
+ function_name,
49
+ signature,
50
+ *,
51
+ representation="ltoir",
52
+ compute_capability=None,
53
+ ):
54
+ """
55
+ Compile the Python function to an intermediate representation using Numba.
56
+
57
+ Args:
58
+ function: The Python function to compile.
59
+ function_name: The symbol to use for the function name.
60
+ signature: the function signature as a sequence (return_type, *parameter_types). The
61
+ type names should correspond to the C type names recognized by Numba.
62
+ representation: the intermediate representation ("ltoir", "ptx").
63
+ compute_capability: the device compute capability. If not specified, the
64
+ current devices CC will be used.
65
+
66
+ Returns:
67
+ The compiled IR.
68
+ """
69
+
70
+ _check_numba_available()
71
+
72
+ import numba
73
+ import numba.cuda
74
+
75
+ user_return_type, *user_arg_types = signature
76
+
77
+ return_type = getattr(numba.cuda.types.types, user_return_type)
78
+
79
+ arg_types = []
80
+ for arg_type in user_arg_types:
81
+ m = re.match(r"(\w+)((\[:\])|( *(\*)))?", arg_type)
82
+ assert m is not None, "Internal error."
83
+ t = getattr(numba.cuda.types.types, m.group(1))
84
+ if m.group(2) is not None:
85
+ if m.group(3) == "[:]":
86
+ t = t[:]
87
+ elif m.group(5) == "*":
88
+ t = numba.cuda.types.types.voidptr
89
+ else:
90
+ raise AssertionError("Internal error.")
91
+ arg_types.append(t)
92
+
93
+ signature = numba.core.typing.signature(return_type, *arg_types)
94
+
95
+ return numba.cuda.compile(
96
+ function,
97
+ signature,
98
+ debug=None,
99
+ lineinfo=False,
100
+ device=True,
101
+ fastmath=False,
102
+ cc=compute_capability,
103
+ opt=True,
104
+ abi="c",
105
+ abi_info={"abi_name": function_name},
106
+ output=representation,
107
+ forceinline=False,
108
+ launch_bounds=None,
109
+ )[0]
110
+
111
+
112
+ def compile_cpp_and_link(
113
+ *,
114
+ src_code=None,
115
+ object_code=None,
116
+ function_name,
117
+ compiler_options=None,
118
+ linker_options=None,
119
+ intermediate_type="ltoir",
120
+ target_type="cubin",
121
+ ):
122
+ """
123
+ Compile the source code (if provided) and link with the intermediate code (if provided).
124
+
125
+ Args:
126
+ src_code: A string or sequence of strings containing the C++ source code.
127
+ object_code: A byte-string or sequence of byte-string objects to be linked
128
+ along with the source code.
129
+ function_name: symbol name to use for the compiled and linked function.
130
+ compiler_options: the compiler options to use as a
131
+ :class:`cuda.core.ProgramOptions` object. Alternatively, a dictionary containing
132
+ the options can be provided.
133
+ linker_options: the linker options to use as a
134
+ :class:`cuda.core.LinkerOptions` object. Alternatively, a dictionary containing
135
+ the options can be provided.
136
+
137
+ Returns:
138
+ The linked kernel.
139
+ """
140
+
141
+ assert not (src_code is None and object_code is None), "Internal error."
142
+
143
+ compiler_options = utils.check_or_create_options(ProgramOptions, compiler_options, "Compiler Options")
144
+ linker_options = utils.check_or_create_options(LinkerOptions, linker_options, "Linker Options")
145
+
146
+ if isinstance(src_code, str):
147
+ src_code = [src_code]
148
+ else:
149
+ if src_code is not None and not isinstance(src_code, Sequence):
150
+ raise TypeError("The source code type 'type(src_code)' must be a string or a sequence of strings.")
151
+
152
+ # Handle the case where no source code is provided.
153
+ if src_code is None:
154
+ src_code = []
155
+
156
+ # Compile source code to LTO-IR.
157
+ compiled_code = [Program(s, "c++", options=compiler_options).compile(intermediate_type) for s in src_code]
158
+
159
+ if isinstance(object_code, bytes):
160
+ object_code = [object_code]
161
+ else:
162
+ if object_code is not None and not isinstance(object_code, Sequence):
163
+ raise TypeError(
164
+ "The intermediate code type 'type(object_code)' must be a byte-string or a sequence of byte-strings."
165
+ )
166
+
167
+ assert intermediate_type == "ltoir", "Internal error."
168
+
169
+ # Handle the case where no object code is provided.
170
+ if object_code is None:
171
+ object_code = []
172
+
173
+ object_code = [ObjectCode.from_ltoir(o) for o in object_code]
174
+
175
+ # Link all objects together.
176
+ linker = Linker(*(compiled_code + object_code), options=linker_options)
177
+ linked_code = linker.link(target_type=target_type)
178
+
179
+ # Extract kernel entry by function name.
180
+ return linked_code.get_kernel(function_name)
181
+
182
+
183
+ # TODO: take grid instead of problem size.
184
+ def launch_kernel(kernel, parameters, problem_size, *, device_id, stream_holder, blocking=True):
185
+ """
186
+ Launch the kernel on the specified device and stream.
187
+
188
+ Args:
189
+ kernel: the CUDA kernel to launch.
190
+ parameters: the kernel arguments as a sequence or None.
191
+ problem_size: the size of the problem (work to divide among threads).
192
+ device_id: the device ID on which to launch the kernel.
193
+ stream_holder: a `nvmath.internal.utils.StreamHolder` object encapsulating the
194
+ stream to use.
195
+ blocking: if True, the call blocks.
196
+ """
197
+
198
+ if problem_size == 0:
199
+ return
200
+
201
+ # Prepare grid.
202
+ threads_per_block = min(1024, problem_size)
203
+ batch_size = (problem_size + threads_per_block - 1) // threads_per_block
204
+ grid = LaunchConfig(grid=batch_size, block=threads_per_block)
205
+
206
+ # Launch the kernel.
207
+ with utils.device_ctx(device_id):
208
+ launch(stream_holder.obj, grid, kernel, *parameters)
209
+
210
+ # TODO: make this non-blocking by default.
211
+ if blocking:
212
+ stream_holder.obj.sync()
@@ -0,0 +1,348 @@
1
+ # Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ """
6
+ This module defines a kernel generator for various sparse tensor operations.
7
+ """
8
+
9
+ __all__ = [
10
+ "KernelGen",
11
+ ]
12
+
13
+ import time
14
+
15
+ from cuda import pathfinder
16
+
17
+ from ._utils import COMPLEX_PRECISION, Cache, type_str
18
+ from .semiring_ops import (
19
+ epilog_impl,
20
+ prolog_a_impl,
21
+ prolog_b_impl,
22
+ prolog_c_impl,
23
+ prolog_epilog_decl,
24
+ semiring_add_impl,
25
+ semiring_atomic_add_impl,
26
+ semiring_mul_impl,
27
+ semiring_ops_decl,
28
+ )
29
+ from .tensor_emitter import emit_matmul
30
+ from .tensor_jit import compile_cpp_and_link
31
+
32
+ # Maps matmul(a,b,c) to pre-defined kernel source code. All kernels should adhere to the
33
+ # parameter passing conventions for each of the three UST parameters.
34
+ _tensor_matmul_kernels = {
35
+ # (format_a, format_b, format_c, transpose_a, transpose_b)
36
+ ("DIAI", "DenseVector", "DenseVector", False, False): """
37
+ extern "C" __global__ void matmul(
38
+ const POS* __restrict__ pos0,
39
+ const CRD* __restrict__ diags,
40
+ const VAL* __restrict__ A,
41
+ unsigned long m,
42
+ unsigned long n,
43
+ unsigned long l0,
44
+ unsigned long l1,
45
+ const VAL *__restrict__ B,
46
+ VAL *__restrict__ C) {
47
+ const unsigned long tidx = threadIdx.x;
48
+ const unsigned long bidx = blockIdx.x;
49
+ const unsigned long i = bidx * blockDim.x + tidx;
50
+ if (i < m) {
51
+ CTP acc = prolog_c(static_cast<CTP>(C[i]));
52
+ const POS numDiags = pos0[1];
53
+ for (unsigned long d = 0, di = i; d < numDiags; d++, di += m) {
54
+ const long j = i + diags[d];
55
+ if (0 <= j && j < n) {
56
+ acc = add(acc, mul(prolog_a(static_cast<CTP>(A[di])),
57
+ prolog_b(static_cast<CTP>(B[j]))));
58
+ }
59
+ }
60
+ C[i] = static_cast<VAL>(epilog(acc));
61
+ }
62
+ }
63
+ """,
64
+ ("DIAJ", "DenseVector", "DenseVector", False, False): """
65
+ extern "C" __global__ void matmul(
66
+ const POS* __restrict__ pos0,
67
+ const CRD* __restrict__ diags,
68
+ const VAL* __restrict__ A,
69
+ unsigned long m,
70
+ unsigned long n,
71
+ unsigned long l0,
72
+ unsigned long l1,
73
+ const VAL *__restrict__ B,
74
+ VAL *__restrict__ C) {
75
+ const unsigned long tidx = threadIdx.x;
76
+ const unsigned long bidx = blockIdx.x;
77
+ const unsigned long i = bidx * blockDim.x + tidx;
78
+ if (i < m) {
79
+ CTP acc = prolog_c(static_cast<CTP>(C[i]));
80
+ const POS numDiags = pos0[1];
81
+ for (unsigned long d = 0, di = 0; d < numDiags; d++, di += n) {
82
+ const long j = i + diags[d];
83
+ if (0 <= j && j < n) {
84
+ acc = add(acc, mul(static_cast<CTP>(prolog_a(A[di + j])),
85
+ static_cast<CTP>(prolog_b(B[j]))));
86
+ }
87
+ }
88
+ C[i] = static_cast<VAL>(epilog(acc));
89
+ }
90
+ }
91
+ """,
92
+ }
93
+
94
+
95
+ def _set_user_or_default_code(*, user_code, default_code, default_prolog, src_code_list, obj_code_list):
96
+ """
97
+ Args:
98
+ user_code: The user-provided LTO-IR as a bytes object or CUDA C++ source code
99
+ string.
100
+ default_code: The CUDA C++ source code that will be used if the user-provided
101
+ code is None.
102
+ default_prolog: The prolog to the CUDA C++ source code that will be used if the
103
+ user-provided code is None.
104
+ src_code_list: The list to which the source code will be appended to.
105
+ obj_code_list: The list to which the LTO-IR code will be appended to.
106
+
107
+ Returns:
108
+ The pair (src_code_list, obj_code_list)
109
+ """
110
+
111
+ if user_code is not None:
112
+ if isinstance(user_code, str):
113
+ target = src_code_list
114
+ elif isinstance(user_code, bytes):
115
+ target = obj_code_list
116
+ else:
117
+ raise AssertionError("Internal error.")
118
+ target.append(user_code)
119
+ return src_code_list, obj_code_list
120
+
121
+ assert default_code is not None and isinstance(default_code, str), "Internal error."
122
+
123
+ source_code = f"{default_prolog} {default_code}"
124
+ src_code_list.append(source_code)
125
+
126
+ return src_code_list, obj_code_list
127
+
128
+
129
+ class KernelGen:
130
+ """
131
+ This class defines a kernel generator for various sparse tensor operations.
132
+ The generated kernels can be JITted on-demand. Caching avoids recompilation
133
+ on subsequent uses.
134
+
135
+ The generation uses:
136
+ (1) kernel lookup from a collection of pre-defined kernels
137
+ (2) kernel generated by a sparse emitter
138
+
139
+ Clients can easily add new pre-defined kernels in the table above (for example,
140
+ by hand optimizing the automatically generated cuda code from the sparse emitter).
141
+ """
142
+
143
+ def __init__(self, debug=False):
144
+ self._matmul_kernels_cache = Cache()
145
+ self._debug = debug
146
+
147
+ def generate_matmul(
148
+ self,
149
+ a,
150
+ b,
151
+ c,
152
+ compute_type,
153
+ prologs=None,
154
+ epilog=None,
155
+ semiring=None,
156
+ transpose_a=False,
157
+ transpose_b=False,
158
+ arch=None,
159
+ ):
160
+ """
161
+ Matmul semantics:
162
+
163
+ Dot Product: If both inputs are 1-dimensional, it computes the dot
164
+ product (inner product).
165
+
166
+ Matrix-Vector Product: If the first input is a 2D tensor (matrix) and
167
+ the second is a 1D tensor (vector), it performs a matrix-vector
168
+ multiplication.
169
+
170
+ Vector-Matrix Product: If the first input is a 1D tensor and the second
171
+ is a 2D tensor, it performs a vector-matrix multiplication.
172
+
173
+ Matrix-Matrix Product: If both inputs are 2D tensors, it performs
174
+ standard matrix multiplication, requiring the number of columns in
175
+ the first matrix to equal the number of rows in the second.
176
+
177
+ Batched Matrix Product: If either input has more than two dimensions,
178
+ the extra leading dimensions are treated as "batch dimensions" and it
179
+ performs a batched matrix multiplication over the last two dimensions.
180
+ """
181
+
182
+ format_a = a.tensor_format.name
183
+ format_b = b.tensor_format.name
184
+ format_c = c.tensor_format.name
185
+ vtp = type_str(a.dtype)
186
+ itp = type_str(a.index_type)
187
+ # Get user code.
188
+ if semiring is None:
189
+ user_mul, user_add, user_atomic_add = None, None, None
190
+ else:
191
+ user_mul, user_add, user_atomic_add = semiring.get("mul"), semiring.get("add"), semiring.get("atomic_add")
192
+ if prologs is None:
193
+ user_prolog_a, user_prolog_b, user_prolog_c = None, None, None
194
+ else:
195
+ user_prolog_a, user_prolog_b, user_prolog_c = prologs.get("a"), prologs.get("b"), prologs.get("c")
196
+ # Try cache lookup.
197
+ key = (
198
+ format_a,
199
+ format_b,
200
+ format_c,
201
+ vtp,
202
+ itp,
203
+ compute_type,
204
+ user_mul,
205
+ user_add,
206
+ user_atomic_add,
207
+ user_prolog_a,
208
+ user_prolog_b,
209
+ user_prolog_c,
210
+ epilog,
211
+ transpose_a,
212
+ transpose_b,
213
+ arch,
214
+ )
215
+ kernel = self._matmul_kernels_cache.get(key)
216
+ if kernel is None:
217
+ # Nothing in cache, try kernel lookup.
218
+ typeless_key = (format_a, format_b, format_c, transpose_a, transpose_b)
219
+ code = _tensor_matmul_kernels.get(typeless_key)
220
+
221
+ # Prepare prolog.
222
+ ctp = type_str(compute_type)
223
+ if a.dtype in ["float8_e4m3fn", "float8_e5m2"]:
224
+ prolog = f"#include <cuda_fp8.h>\nusing ATP = {ctp};\nusing CTP = {ctp};\n" # TODO: ATP=vtp
225
+ elif a.dtype == "float16":
226
+ prolog = f"#include <cuda_fp16.h>\nusing ATP = {vtp};\nusing CTP = {ctp};\n"
227
+ elif a.dtype == "bfloat16":
228
+ prolog = f"#include <cuda_bf16.h>\nusing ATP = {vtp};\nusing CTP = {ctp};\n"
229
+ elif a.dtype in ["complex64", "complex128"]:
230
+ prolog = f"#include <cuda/std/complex>\nusing ATP = {COMPLEX_PRECISION[a.dtype]};\nusing CTP = {ctp};\n"
231
+ else:
232
+ prolog = f"using ATP = {vtp};\nusing CTP = {ctp};\n"
233
+
234
+ # Use kernel lookup or emitter.
235
+ if code is not None:
236
+ # (1) Kernel lookup successful. Inject types into the typeless kernel.
237
+ source = (
238
+ f"{prolog}\nusing VAL = {vtp};\nusing POS = {itp};\n"
239
+ f"using CRD = {itp};\n{semiring_ops_decl}{prolog_epilog_decl}{code}"
240
+ )
241
+ else:
242
+ if user_prolog_c is not None or epilog is not None:
243
+ raise NotImplementedError(
244
+ "The code generation (emitter) path does not currently support \
245
+ prolog for the `c` operand or epilog."
246
+ )
247
+ # (2) Sparse emitter. Emits proper types.
248
+ source = emit_matmul(a, b, c, ctp, transpose_a, transpose_b)
249
+
250
+ # The source and object code lists.
251
+ src_code_list, obj_code_list = [source], []
252
+
253
+ # User-provided or default semiring mul operation.
254
+ src_code_list, obj_code_list = _set_user_or_default_code(
255
+ user_code=user_mul,
256
+ default_code=semiring_mul_impl,
257
+ default_prolog=prolog,
258
+ src_code_list=src_code_list,
259
+ obj_code_list=obj_code_list,
260
+ )
261
+
262
+ # User-provided or default semiring add operation.
263
+ src_code_list, obj_code_list = _set_user_or_default_code(
264
+ user_code=user_add,
265
+ default_code=semiring_add_impl,
266
+ default_prolog=prolog,
267
+ src_code_list=src_code_list,
268
+ obj_code_list=obj_code_list,
269
+ )
270
+
271
+ # User-provided or default semiring atomic add operation.
272
+ src_code_list, obj_code_list = _set_user_or_default_code(
273
+ user_code=user_atomic_add,
274
+ default_code=semiring_atomic_add_impl,
275
+ default_prolog=prolog,
276
+ src_code_list=src_code_list,
277
+ obj_code_list=obj_code_list,
278
+ )
279
+
280
+ # User-provided or default prolog operation on A.
281
+ src_code_list, obj_code_list = _set_user_or_default_code(
282
+ user_code=user_prolog_a,
283
+ default_code=prolog_a_impl,
284
+ default_prolog=prolog,
285
+ src_code_list=src_code_list,
286
+ obj_code_list=obj_code_list,
287
+ )
288
+
289
+ # User-provided or default prolog operation on B.
290
+ src_code_list, obj_code_list = _set_user_or_default_code(
291
+ user_code=user_prolog_b,
292
+ default_code=prolog_b_impl,
293
+ default_prolog=prolog,
294
+ src_code_list=src_code_list,
295
+ obj_code_list=obj_code_list,
296
+ )
297
+
298
+ # User-provided or default prolog operation on C.
299
+ src_code_list, obj_code_list = _set_user_or_default_code(
300
+ user_code=user_prolog_c,
301
+ default_code=prolog_c_impl,
302
+ default_prolog=prolog,
303
+ src_code_list=src_code_list,
304
+ obj_code_list=obj_code_list,
305
+ )
306
+
307
+ # User-provided or default epilog operation.
308
+ src_code_list, obj_code_list = _set_user_or_default_code(
309
+ user_code=epilog,
310
+ default_code=epilog_impl,
311
+ default_prolog=prolog,
312
+ src_code_list=src_code_list,
313
+ obj_code_list=obj_code_list,
314
+ )
315
+
316
+ if self._debug:
317
+ print("\n==> Compiling matmul()\n")
318
+ for s in src_code_list:
319
+ print(s)
320
+ print("/////////////////////\n")
321
+ t1 = time.perf_counter_ns()
322
+
323
+ # Compile and link matmul function. Cache the result.
324
+ complex_path = pathfinder.find_nvidia_header_directory("cccl")
325
+ narrow_prec_path = pathfinder.find_nvidia_header_directory("cudart")
326
+ compiler_options = {
327
+ "std": "c++17",
328
+ "link_time_optimization": True,
329
+ "arch": arch,
330
+ "include_path": [complex_path, narrow_prec_path],
331
+ }
332
+ linker_options = {"link_time_optimization": True}
333
+ kernel = compile_cpp_and_link(
334
+ src_code=src_code_list,
335
+ object_code=obj_code_list,
336
+ function_name="matmul",
337
+ compiler_options=compiler_options,
338
+ linker_options=linker_options,
339
+ )
340
+ assert kernel is not None, "Internal error."
341
+ self._matmul_kernels_cache[key] = kernel
342
+
343
+ if self._debug:
344
+ t2 = time.perf_counter_ns()
345
+ tt = (t2 - t1) / 1000.0 # ns -> us
346
+ print(f"<== Compiled matmul() in {tt:10.2f} us.\n")
347
+
348
+ return kernel