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,383 @@
1
+ # Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ import abc
6
+ import contextlib
7
+ import dataclasses
8
+ import logging
9
+ from collections.abc import MutableSequence
10
+ from logging import Logger
11
+ from typing import ClassVar, Final, Generic, Literal, TypeVar
12
+
13
+ from nvmath import memory
14
+ from nvmath.internal import utils
15
+
16
+
17
+ @dataclasses.dataclass(frozen=True, slots=True, kw_only=True)
18
+ class ExecutionCUDA:
19
+ """
20
+ A data class for providing GPU execution options.
21
+
22
+ Attributes:
23
+ device_id: CUDA device ordinal (only used if the operand resides on the CPU). The
24
+ default value is 0.
25
+
26
+ .. seealso::
27
+ :class:`ExecutionCPU`
28
+ """
29
+
30
+ name: ClassVar[Literal["cuda"]] = "cuda"
31
+ device_id: int = 0
32
+
33
+
34
+ @dataclasses.dataclass(frozen=True, slots=True, kw_only=True)
35
+ class ExecutionCPU:
36
+ """
37
+ A data class for providing CPU execution options.
38
+
39
+ Attributes:
40
+ num_threads: The number of CPU threads used to execute the operation.
41
+ If not specified, defaults to the number of CPU cores available to the
42
+ process.
43
+
44
+ .. seealso::
45
+ :class:`ExecutionCUDA`
46
+ """
47
+
48
+ name: ClassVar[Literal["cpu"]] = "cpu"
49
+ num_threads: int | None = None
50
+
51
+
52
+ def copy_operand_perhaps(
53
+ internal_operand: utils.TensorHolder | None,
54
+ operand: utils.TensorHolder,
55
+ stream_holder: utils.StreamHolder | None,
56
+ execution_device_id: int | Literal["cpu"],
57
+ operands_device_id: int | Literal["cpu"],
58
+ ) -> tuple[utils.TensorHolder, utils.TensorHolder | None]:
59
+ """Private implementation of memory space management for tensor operands.
60
+
61
+ The `copy_operand_perhaps` function facilitates transitions of tensor operands between
62
+ different memory spaces, ensuring compatibility with execution requirements. Its role is
63
+ to determine whether a tensor operand needs to be copied to accommodate differing
64
+ execution and operand memory spaces, while preserving the original operand for cases
65
+ requiring in-place operations.
66
+
67
+ Args:
68
+ internal_operand: Represents an internal tensor for in-place
69
+ memory operations, or `None` if not applicable.
70
+
71
+ operand: Tensor to possibly copied to the execution memory space.
72
+
73
+ stream_holder: Manages the CUDA stream for device operations.
74
+
75
+ execution_device_id: Specifies the target execution space.
76
+
77
+ operands_device_id: Specifies the current operand memory space.
78
+
79
+ Returns:
80
+ A tuple containing:
81
+ - The operand copied to the execution space, or the original operand if
82
+ no copy is necessary.
83
+ - The original operand, or `None` if no copy occurred.
84
+
85
+ """
86
+ if execution_device_id == operands_device_id:
87
+ return operand, None
88
+ else:
89
+ # Copy the `operand` to memory that matches the exec space
90
+ # and keep the original `operand` to handle `options.inplace=True`
91
+ if internal_operand is None:
92
+ exec_space_copy = operand.to(execution_device_id, stream_holder)
93
+ return exec_space_copy, operand
94
+ else:
95
+ # In-place copy to existing pointer
96
+ internal_operand.copy_(src=operand, stream_holder=stream_holder)
97
+ return internal_operand, operand
98
+
99
+
100
+ @dataclasses.dataclass(frozen=True, slots=True, kw_only=True)
101
+ class StatefulAPIOptions:
102
+ """A dataclass for providing options to a :class:`StatefulAPI` object.
103
+
104
+ Attributes:
105
+ allocator: An object that supports the :class:`BaseCUDAMemoryManager` protocol, used
106
+ to draw device memory. If an allocator is not provided, a memory allocator from
107
+ the library package will be used (:func:`torch.cuda.caching_allocator_alloc` for
108
+ PyTorch operands, :func:`cupy.cuda.alloc` otherwise).
109
+
110
+ blocking: A flag specifying the behavior of the stream-ordered functions and
111
+ methods. When ``blocking`` is `True`, the stream-ordered methods do not return
112
+ until the operation is complete. When ``blocking`` is ``"auto"``, the methods
113
+ return immediately when the inputs are on the GPU. The stream-ordered methods
114
+ always block when the operands are on the CPU to ensure that the user doesn't
115
+ inadvertently use the result before it becomes available. The default is
116
+ ``"auto"``.
117
+
118
+ logger: Python Logger object. The root logger will be used if a
119
+ logger object is not provided.
120
+
121
+ .. seealso::
122
+ :class:`StatefulAPI`
123
+ """
124
+
125
+ allocator: memory.BaseCUDAMemoryManager | memory.BaseCUDAMemoryManagerAsync | None = None
126
+ blocking: Literal[True, "auto"] = "auto"
127
+ logger: Logger = dataclasses.field(default_factory=logging.getLogger)
128
+
129
+ def __post_init__(self):
130
+ if self.blocking not in (True, "auto"):
131
+ raise ValueError("The value specified for blocking must be either True or 'auto'.")
132
+
133
+ if self.allocator is not None and not isinstance(
134
+ self.allocator, memory.BaseCUDAMemoryManager | memory.BaseCUDAMemoryManagerAsync
135
+ ):
136
+ raise TypeError("The allocator must be an object of type that fulfills the BaseCUDAMemoryManager protocol.")
137
+
138
+
139
+ OptionsPlaceholder = TypeVar("OptionsPlaceholder", bound=StatefulAPIOptions)
140
+
141
+
142
+ class StatefulAPI(contextlib.AbstractContextManager, Generic[OptionsPlaceholder]):
143
+ """A base class for APIs which amortize setup costs across multiple executions.
144
+
145
+ StatefulAPIs separate planning (``plan()``) and setup (``__init__()``) actions from
146
+ execution (``_execute()``), so that plans may be reused with different operands. The
147
+ ``reset_operands()`` method allows changing the operands of the API without replanning
148
+ when the input and execution space do not match (the user does not have a reference to
149
+ the execution space buffers). If the execution and input space match, we expect the
150
+ user to be able update the operands by overwriting their buffers in-place.
151
+ """
152
+
153
+ # options is declared Final in __init__() because mypy issue #8982 is not fixed yet.
154
+ # options: Final[OptionsPlaceholder]
155
+ # See docstring for StatefulAPIOptions
156
+ _allocator: Final[memory.BaseCUDAMemoryManager | memory.BaseCUDAMemoryManagerAsync | None]
157
+ _blocking: Final[bool]
158
+ _logger: Final[logging.Logger]
159
+
160
+ # Metadata related to execution space
161
+ execution: Final[ExecutionCPU | ExecutionCUDA]
162
+ """A class which describes the execution space parameters."""
163
+ _internal_op_package: Final[str]
164
+ """The package of the operands in the execution space."""
165
+ _operands: MutableSequence[utils.TensorHolder]
166
+ """A copy of the operands in execution space."""
167
+ _result_class: Final[type[utils.TensorHolder]]
168
+ """The type of TensorHolder to use for the execution space result."""
169
+
170
+ # Metadata about the input/output tensors
171
+ _operands_backup: MutableSequence[utils.TensorHolder | None]
172
+ """A reference to original operands in their input space."""
173
+ _operands_device_id: Final[int | Literal["cpu"]]
174
+ """The device_id of the input space."""
175
+ _operands_package: Final[str]
176
+ """The package of the operands in the input space."""
177
+
178
+ _call_prologue: Final[str]
179
+ """Stores a message for logging about blocking behavior"""
180
+
181
+ _has_plan: bool
182
+ """True if plan has been called."""
183
+
184
+ @property
185
+ def options(self) -> OptionsPlaceholder:
186
+ """The options object used to construct this class."""
187
+ # This is a workaround for mypy issue #8982, where we cannot declare options as
188
+ # Final in the class definition, but we still want it to appear in the docs as an
189
+ # attribute.
190
+ return self._options
191
+
192
+ def __init__(
193
+ self,
194
+ operands: MutableSequence[utils.TensorHolder],
195
+ *,
196
+ options: OptionsPlaceholder,
197
+ execution: ExecutionCPU | ExecutionCUDA | None | Literal["cuda", "cpu"] = None,
198
+ stream: utils.AnyStream | int | None = None,
199
+ ) -> None:
200
+ """Copy operands to the execution space and setup options.
201
+
202
+ When inheriting from this class, you must create valid operands and options in
203
+ the child class before calling StatefulAPI.__init__( ... ).
204
+ """
205
+ self._options: Final[OptionsPlaceholder] = options
206
+ self._logger = self._options.logger
207
+
208
+ self._logger.info("= SPECIFICATION PHASE =")
209
+
210
+ operands_device_id = utils.get_operands_device_id(operands)
211
+
212
+ match execution, operands_device_id:
213
+ case (None | "cuda", int()):
214
+ execution = ExecutionCUDA(device_id=operands_device_id)
215
+ case ("cuda", "cpu"):
216
+ execution = ExecutionCUDA()
217
+ case (None, "cpu") | ("cpu", _):
218
+ execution = ExecutionCPU()
219
+ case (ExecutionCUDA(), int()):
220
+ # If operands are on a CUDA device, use the same device for execution.
221
+ execution = dataclasses.replace(execution, device_id=operands_device_id)
222
+ case (ExecutionCPU(), _) | (ExecutionCUDA(), "cpu"):
223
+ pass
224
+ case _:
225
+ raise ValueError(
226
+ f"{self.__class__.__name__}.execution must be one of ExecutionCUDA, ExecutionCPU, None, 'cuda', or 'cpu'."
227
+ )
228
+ assert isinstance(execution, (ExecutionCPU, ExecutionCUDA))
229
+ self.execution = execution
230
+
231
+ self._operands_device_id = operands_device_id
232
+ self._operands_package = utils.get_operands_package(operands)
233
+ self._internal_op_package = self._internal_operand_package(self._operands_package)
234
+ exec_stream_holder, operand_stream_holder = self._get_or_create_stream_maybe(stream)
235
+
236
+ self._logger.info(
237
+ f"The input tensors are located on device {operands_device_id}, and the execution space "
238
+ f"is {self.execution.name}, with device {getattr(self.execution, 'device_id', 'cpu')}."
239
+ )
240
+
241
+ self._logger.info(
242
+ f"The specified stream for the {self.__class__.__name__} constructor is "
243
+ f"{(exec_stream_holder or operand_stream_holder) and getattr(exec_stream_holder or operand_stream_holder, 'obj', None)}." # noqa: E501
244
+ )
245
+
246
+ operands_backup: list[utils.TensorHolder | None] = [None] * len(operands)
247
+ for i in range(len(operands)):
248
+ # Copy the operand to execution_space's device if needed.
249
+ operands[i], operands_backup[i] = copy_operand_perhaps(
250
+ None,
251
+ operands[i],
252
+ operand_stream_holder,
253
+ getattr(self.execution, "device_id", "cpu"),
254
+ self._operands_device_id,
255
+ )
256
+ self._operands = operands
257
+ self._operands_backup = operands_backup
258
+
259
+ # The result's package and device.
260
+ self._result_class = self._operands[0].__class__
261
+
262
+ # Set blocking or non-blocking behavior.
263
+ self._blocking = self._options.blocking != "auto" or self._operands_device_id == "cpu" or self.execution.name == "cpu"
264
+ if self._blocking:
265
+ call_prologue = "This call is blocking and will return only after the operation is complete."
266
+ else:
267
+ call_prologue = (
268
+ "This call is non-blocking and will return immediately after the operation is launched on the device."
269
+ )
270
+ self._call_prologue = call_prologue
271
+
272
+ # Set memory allocator.
273
+ allocator: memory.BaseCUDAMemoryManager | memory.BaseCUDAMemoryManagerAsync | None
274
+ match self.execution:
275
+ case ExecutionCUDA():
276
+ allocator = (
277
+ memory._MEMORY_MANAGER[self._internal_op_package](self.execution.device_id, self._logger)
278
+ if self._options.allocator is None
279
+ else self._options.allocator
280
+ )
281
+ case ExecutionCPU() | _:
282
+ allocator = None # currently, the nvpl/fftw does not support custom workspace allocation
283
+ self._allocator = allocator
284
+
285
+ self._has_plan = False
286
+
287
+ def _internal_operand_package(self, package_name: str) -> str:
288
+ if self.execution.name == "cuda":
289
+ return package_name if package_name != "numpy" else "cuda"
290
+ else:
291
+ return package_name if package_name != "cupy" else "cupy_host"
292
+
293
+ def _get_or_create_stream_maybe(
294
+ self, stream: utils.AnyStream
295
+ ) -> tuple[utils.StreamHolder | None, utils.StreamHolder | None]:
296
+ """Return a 2-tuple of Stream | None: one for execution space, one for input space.
297
+
298
+ The first stream should be used for everything in the execution space: doing work,
299
+ allocating workspace, allocating input/output buffers.
300
+
301
+ The second stream should be used whenever data is being moved between the input and
302
+ output spaces: copying data to/from the input/output tensors.
303
+
304
+ NOTE: If two streams are returned, they will be the same stream.
305
+ """
306
+ if self.execution.name == "cuda":
307
+ stream_holder = utils.get_or_create_stream(self.execution.device_id, stream, self._internal_op_package)
308
+ return stream_holder, stream_holder
309
+ elif isinstance(self._operands_device_id, int):
310
+ operand_device_steam = utils.get_or_create_stream(self._operands_device_id, stream, self._operands_package)
311
+ return None, operand_device_steam
312
+ else:
313
+ return None, None
314
+
315
+ # input checks
316
+
317
+ def _check_valid_operands(self, *args, **kwargs):
318
+ """
319
+ Check if the operands are available for the operation.
320
+ """
321
+ what = kwargs["what"]
322
+ if self._operands is None:
323
+ raise RuntimeError(
324
+ f"{what} cannot be performed if the operands have been set to None. Use reset_operands() to set the "
325
+ f"desired input before using performing the {what.lower()}."
326
+ )
327
+
328
+ def _check_planned(self, *args, **kwargs):
329
+ what = kwargs["what"]
330
+ if not self._has_plan:
331
+ raise RuntimeError(f"{what} cannot be performed before plan() has been called.")
332
+
333
+ # execution
334
+
335
+ @abc.abstractmethod
336
+ def _execute(self):
337
+ """Perform the main functionality of this :class:`StatefulAPI` instance without
338
+ safety checks."""
339
+ msg = f"{self.__name__}._execute() is not implemented."
340
+ raise NotImplementedError(msg)
341
+
342
+ @abc.abstractmethod
343
+ def plan(self):
344
+ """Plan the main functionality of this :class:`StatefulAPI` instance."""
345
+ msg = f"{self.__class__.__name__}.plan() is not implemented."
346
+ raise NotImplementedError(msg)
347
+
348
+ @abc.abstractmethod
349
+ def reset_operands(self):
350
+ """Reset the operands held by this :class:`StatefulAPI` instance."""
351
+ msg = f"{self.__class__.__name__}.reset_operands() is not implemented."
352
+ raise NotImplementedError(msg)
353
+
354
+ def free(self):
355
+ """Free resources held by this :class:`StatefulAPI` instance.
356
+
357
+ This method releases references to operands to ensure proper reference counting.
358
+ Subclasses should call super().free() if they override this method to add
359
+ additional cleanup logic.
360
+ """
361
+ # Release references to operands to ensure proper reference counting
362
+ self._operands = []
363
+ self._operands_backup = []
364
+
365
+
366
+ class HasWorkspaceMemory(contextlib.AbstractContextManager):
367
+ """A base class for APIs which need to allocate a working buffer in memory."""
368
+
369
+ def _allocate_workspace_memory_perhaps(self, stream_holder: utils.StreamHolder):
370
+ """
371
+ Allocate workspace memory using the specified allocator, if it hasn't already been
372
+ done.
373
+ """
374
+ raise NotImplementedError
375
+
376
+ def _release_workspace_memory_perhaps(self, release_workspace: bool):
377
+ raise NotImplementedError
378
+
379
+ @abc.abstractmethod
380
+ def free(self):
381
+ """Free the resources of this :class:`StatefulAPI` instance."""
382
+ msg = f"{self.__name__}.free() is not implemented."
383
+ raise NotImplementedError(msg)
nvmath/_utils.py ADDED
@@ -0,0 +1,150 @@
1
+ # Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ import logging
6
+ import re
7
+ import sys
8
+ from enum import IntEnum
9
+ from functools import cache
10
+
11
+ from cuda import pathfinder
12
+
13
+ logger = logging.getLogger()
14
+
15
+ #
16
+ # Note: This module should not depend on anything from the nvmath namespace!
17
+ #
18
+
19
+
20
+ # The (subset of) compute types below are shared by cuStateVec and cuTensorNet
21
+ class ComputeType(IntEnum):
22
+ """An enumeration of CUDA compute types."""
23
+
24
+ COMPUTE_DEFAULT = 0
25
+ COMPUTE_16F = 1 << 0
26
+ COMPUTE_32F = 1 << 2
27
+ COMPUTE_64F = 1 << 4
28
+ COMPUTE_8U = 1 << 6
29
+ COMPUTE_8I = 1 << 8
30
+ COMPUTE_32U = 1 << 7
31
+ COMPUTE_32I = 1 << 9
32
+ COMPUTE_16BF = 1 << 10
33
+ COMPUTE_TF32 = 1 << 12
34
+
35
+
36
+ # TODO: use those exposed by CUDA Python instead, but before removing these
37
+ # duplicates, check if they are fixed to inherit IntEnum instead of Enum.
38
+ class CudaDataType(IntEnum):
39
+ """An enumeration of `cudaDataType_t`."""
40
+
41
+ CUDA_R_16F = 2
42
+ CUDA_C_16F = 6
43
+ CUDA_R_16BF = 14
44
+ CUDA_C_16BF = 15
45
+ CUDA_R_32F = 0
46
+ CUDA_C_32F = 4
47
+ CUDA_R_64F = 1
48
+ CUDA_C_64F = 5
49
+ CUDA_R_4I = 16
50
+ CUDA_C_4I = 17
51
+ CUDA_R_4U = 18
52
+ CUDA_C_4U = 19
53
+ CUDA_R_8I = 3
54
+ CUDA_C_8I = 7
55
+ CUDA_R_8U = 8
56
+ CUDA_C_8U = 9
57
+ CUDA_R_16I = 20
58
+ CUDA_C_16I = 21
59
+ CUDA_R_16U = 22
60
+ CUDA_C_16U = 23
61
+ CUDA_R_32I = 10
62
+ CUDA_C_32I = 11
63
+ CUDA_R_32U = 12
64
+ CUDA_C_32U = 13
65
+ CUDA_R_64I = 24
66
+ CUDA_C_64I = 25
67
+ CUDA_R_64U = 26
68
+ CUDA_C_64U = 27
69
+ CUDA_R_8F_E4M3 = 28
70
+ CUDA_R_8F_E5M2 = 29
71
+ CUDA_R_4F_E2M1 = 33 # FP4 (supported on SM >= 10.0)
72
+
73
+
74
+ class LibraryPropertyType(IntEnum):
75
+ """An enumeration of library version information."""
76
+
77
+ MAJOR_VERSION = 0
78
+ MINOR_VERSION = 1
79
+ PATCH_LEVEL = 2
80
+
81
+
82
+ del IntEnum
83
+
84
+
85
+ PLATFORM_LINUX = sys.platform.startswith("linux")
86
+ PLATFORM_WIN = sys.platform.startswith("win32")
87
+
88
+
89
+ def module_init_force_cupy_lib_load():
90
+ """
91
+ Attempt to preload libraries at module import time. We want to do it before
92
+ cupy, since it does not know how to properly search for libraries:
93
+ https://github.com/cupy/cupy/issues/9127
94
+ Fail silently if preload fails.
95
+ """
96
+ from nvmath.bindings import _internal
97
+
98
+ libs = ("cublas", "cufft", "curand", "cusolverDn", "cusparse", "cutensor")
99
+ for lib in libs:
100
+ try:
101
+ mod = getattr(_internal, lib)
102
+ mod._inspect_function_pointers()
103
+ except (_internal.utils.NotSupportedError, RuntimeError):
104
+ pass
105
+
106
+ try:
107
+ pathfinder.load_nvidia_dynamic_lib("nvrtc")
108
+ except pathfinder.DynamicLibNotFoundError:
109
+ pass
110
+
111
+
112
+ @cache
113
+ def get_nvrtc_build_id(minimal=True) -> int:
114
+ try:
115
+ from cuda.core import ObjectCode, Program, ProgramOptions
116
+ except ImportError:
117
+ from cuda.core.experimental import ObjectCode, Program, ProgramOptions
118
+
119
+ code = r"""
120
+ extern "C" __global__ void get_build_id(int* build_id) {
121
+
122
+ *build_id = __CUDACC_VER_BUILD__;
123
+ }
124
+ """
125
+
126
+ prog = Program(code, "c++", ProgramOptions(std="c++17", minimal=minimal, arch="compute_75"))
127
+ obj = prog.compile("ptx")
128
+ assert isinstance(obj, ObjectCode)
129
+
130
+ pattern = re.compile(r"mov\.u32\s+%\w+,\s+(\d+)")
131
+ m = pattern.search(obj.code.decode())
132
+ assert m is not None
133
+
134
+ return int(m.group(1))
135
+
136
+
137
+ @cache
138
+ def get_nvrtc_version() -> tuple[int, int, int]:
139
+ """
140
+ Returns the NVRTC version as a tuple of (major, minor, build).
141
+ """
142
+ from cuda.bindings import nvrtc
143
+
144
+ err, major, minor = nvrtc.nvrtcVersion()
145
+ if err != nvrtc.nvrtcResult.NVRTC_SUCCESS:
146
+ raise RuntimeError(f"nvrtcVersion error: {err}")
147
+ # minimal support was added in CUDA 12.4
148
+ # https://docs.nvidia.com/cuda/archive/12.4.0/cuda-toolkit-release-notes/index.html#cuda-compilers
149
+ build = get_nvrtc_build_id(minimal=major >= 12 and minor >= 4)
150
+ return major, minor, build
@@ -0,0 +1,51 @@
1
+ # Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ # type: ignore
6
+
7
+ from nvmath.bindings import cublas
8
+ from nvmath.bindings import cublasLt
9
+ from nvmath.bindings import cudss
10
+ from nvmath.bindings import cufft
11
+ from nvmath.bindings import curand
12
+ from nvmath.bindings import cusolver
13
+ from nvmath.bindings import cusolverDn
14
+ from nvmath.bindings import cusparse
15
+ from nvmath.bindings import cusparseLt
16
+ from nvmath.bindings import cutensor
17
+
18
+ try:
19
+ # cufftMp is Linux-only.
20
+ from nvmath.bindings import cufftMp
21
+ except ImportError:
22
+ cufftMp = None
23
+
24
+ try:
25
+ # nvshmem is Linux-only.
26
+ from nvmath.bindings import nvshmem
27
+ except ImportError:
28
+ nvshmem = None
29
+
30
+ try:
31
+ # cublasMp is Linux-only.
32
+ from nvmath.bindings import cublasMp
33
+ except ImportError:
34
+ cublasMp = None
35
+
36
+ __all__ = [
37
+ "cublas",
38
+ "cublasLt",
39
+ "cublasMp",
40
+ "cudss",
41
+ "cufft",
42
+ "cufftMp",
43
+ "curand",
44
+ "cusolver",
45
+ "cusolverDn",
46
+ "cusparse",
47
+ "cusparseLt",
48
+ "cutensor",
49
+ "nvpl",
50
+ "nvshmem",
51
+ ]
File without changes
File without changes