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,234 @@
1
+ # Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ """
6
+ Interface to seamlessly use Cupy ndarray objects.
7
+ """
8
+
9
+ __all__ = ["CupyTensor", "HostTensor"]
10
+
11
+ from collections.abc import Sequence
12
+
13
+ import cupy
14
+ import numpy as np
15
+ from cuda.core import Buffer
16
+
17
+ from . import utils
18
+ from .ndbuffer import NDBuffer
19
+ from .package_ifc import StreamHolder
20
+ from .tensor_ifc import TensorHolder
21
+ from .tensor_ifc_ndbuffer import NDBufferTensor
22
+
23
+
24
+ class HostTensor(NDBufferTensor):
25
+ """
26
+ Wraps ndbuffer with data residing on the host.
27
+ It serves as a host counterpart for CupyTensor.
28
+ """
29
+
30
+ name = "cupy_host"
31
+ host_tensor_class: type["HostTensor"] # set at the end of the file
32
+ device_tensor_class: type["CupyTensor"] # set at the end of the file
33
+
34
+ def __init__(self, tensor):
35
+ super().__init__(tensor)
36
+
37
+ @classmethod
38
+ def create_host_from(cls, tensor: TensorHolder, stream_holder: StreamHolder):
39
+ src_nd = tensor.asndbuffer()
40
+ # empty_like (and not empty_numpy_like) is used as we don't need
41
+ # full-fledged numpy array (with proper layout)
42
+ dst_nd = NDBuffer.empty_like(src_nd, device_id="cpu")
43
+ dst_nd.copy_(src_nd, stream=stream_holder)
44
+ return cls(dst_nd)
45
+
46
+ def to(self, device_id, stream_holder):
47
+ if device_id == "cpu":
48
+ return self
49
+ elif isinstance(device_id, int):
50
+ return self.device_tensor_class.create_from_host(self, device_id, stream_holder)
51
+ else:
52
+ raise ValueError(f"The device must be specified as an integer or 'cpu', not '{device_id}'.")
53
+
54
+
55
+ class _CupyAllocatorAdapter:
56
+ def allocate(self, size, stream):
57
+ # we accept the stream, because the ndbuffer.empty_like
58
+ # passes it to the allocator, but we don't use it:
59
+ # cupy.cuda.alloc does not accept the stream, we make sure to set
60
+ # the correct current stream when calling ndbuffer.empty_like
61
+ alloc = cupy.cuda.alloc(size)
62
+ return Buffer.from_handle(alloc.ptr, size, owner=alloc)
63
+
64
+
65
+ _cupy_allocator = _CupyAllocatorAdapter()
66
+
67
+
68
+ class CupyTensor(TensorHolder[cupy.ndarray]):
69
+ """
70
+ TensorHolder for cupy ndarrays.
71
+ """
72
+
73
+ name = "cupy"
74
+ module = cupy
75
+ name_to_dtype = TensorHolder.create_name_dtype_map(
76
+ conversion_function=lambda name: np.dtype(name), exception_type=TypeError
77
+ )
78
+ host_tensor_class: type["HostTensor"] # set at the end of the file
79
+ device_tensor_class: type["CupyTensor"] # set at the end of the file
80
+
81
+ def __init__(self, tensor):
82
+ super().__init__(tensor)
83
+
84
+ @property
85
+ def data_ptr(self):
86
+ return self.tensor.data.ptr
87
+
88
+ @property
89
+ def device(self):
90
+ return "cuda"
91
+
92
+ @property
93
+ def device_id(self):
94
+ return self.tensor.device.id
95
+
96
+ @property
97
+ def dtype(self):
98
+ """Name of the data type"""
99
+ return self.tensor.dtype.name
100
+
101
+ @property
102
+ def itemsize(self):
103
+ return self.tensor.itemsize
104
+
105
+ @property
106
+ def shape(self):
107
+ return tuple(self.tensor.shape)
108
+
109
+ @property
110
+ def size(self):
111
+ return self.tensor.size
112
+
113
+ @property
114
+ def strides(self):
115
+ return tuple(stride_in_bytes // self.tensor.itemsize for stride_in_bytes in self.tensor.strides)
116
+
117
+ @classmethod
118
+ def empty(
119
+ cls, shape, device_id="cpu", *, dtype="float32", strides=None, stream_holder: StreamHolder | None = None, **context
120
+ ):
121
+ """
122
+ Create an empty tensor of the specified shape and data type.
123
+
124
+ Note, that the strides, if specified, MUST correspond to a dense (possibly permuted)
125
+ tensor, otherwise the created tensor may be corrupted.
126
+ """
127
+ assert isinstance(device_id, int), "Internal Error: Cupy tensors must be allocated with an integer device_id."
128
+ dtype = CupyTensor.name_to_dtype[dtype]
129
+
130
+ # When using the strides, we need an explicit allocation (see below).
131
+ # If the strides are simple enough, we can still avoid this overhead.
132
+ order = "C"
133
+ if strides is not None:
134
+ if len(strides) == 1 and strides[0] == 1:
135
+ strides = None
136
+ elif len(strides) == 2:
137
+ if strides[0] == 1 and strides[1] == shape[0]:
138
+ strides = None
139
+ order = "F"
140
+ elif strides[0] == shape[1] and strides[1] == 1:
141
+ strides = None
142
+
143
+ assert isinstance(stream_holder, StreamHolder), "Internal Error: CupyTensors must be allocated on a stream."
144
+ with utils.device_ctx(device_id), stream_holder.ctx:
145
+ if strides:
146
+ # need an explicit allocation due to cupy/cupy#7818
147
+ size = dtype.itemsize
148
+ for s in shape:
149
+ size = size * s
150
+ ptr = cupy.cuda.alloc(size)
151
+ # when strides is not None, it should be of unit counts not bytes
152
+ strides = tuple(s * dtype.itemsize for s in strides)
153
+ tensor = cupy.ndarray(shape, dtype=dtype, strides=strides, memptr=ptr)
154
+ else:
155
+ tensor = cupy.ndarray(shape, dtype=dtype, order=order)
156
+
157
+ return cls(tensor)
158
+
159
+ @classmethod
160
+ def create_from_host(cls, tensor: TensorHolder, device_id: int, stream_holder: StreamHolder):
161
+ with utils.device_ctx(device_id), stream_holder.ctx:
162
+ src_nd = tensor.asndbuffer()
163
+ dst_nd = NDBuffer.empty_like(src_nd, device_id=device_id, stream=stream_holder, memory_resource=_cupy_allocator)
164
+ dst_nd.copy_(src_nd, stream=stream_holder)
165
+ dst = cupy.ndarray(dst_nd.shape, dtype=dst_nd.dtype_name, strides=dst_nd.strides_in_bytes, memptr=dst_nd.data.owner)
166
+ return cls(dst)
167
+
168
+ def asndbuffer(self):
169
+ return NDBuffer.from_cupy(self.tensor)
170
+
171
+ def to(self, device_id, stream_holder):
172
+ if device_id == "cpu":
173
+ with utils.device_ctx(self.device_id):
174
+ return self.host_tensor_class.create_host_from(self, stream_holder)
175
+ elif device_id == self.device_id:
176
+ return self
177
+ elif isinstance(device_id, int):
178
+ raise ValueError(f"Unsupported copy between different devices {self.device_id} and {device_id}.")
179
+ raise ValueError(f"The device must be specified as an integer or 'cpu', not '{device_id}'.")
180
+
181
+ def copy_(self, src, stream_holder):
182
+ """
183
+ Inplace copy of src (copy the data from src into self).
184
+ """
185
+ with utils.device_ctx(self.device_id):
186
+ self.asndbuffer().copy_(src.asndbuffer(), stream=stream_holder)
187
+
188
+ def istensor(self):
189
+ """
190
+ Check if the object is ndarray-like.
191
+ """
192
+ return isinstance(self.tensor, cupy.ndarray)
193
+
194
+ def reshape(self, shape: Sequence[int], *, copy: bool | None = None):
195
+ if copy:
196
+ raise NotImplementedError("reshape with copy=True not implemented")
197
+ if copy is False:
198
+ try:
199
+ reshaped_tensor = self.tensor.view()
200
+ reshaped_tensor.shape = shape
201
+ except AttributeError as e:
202
+ raise ValueError(
203
+ f"Could not reshape cupy array without copy: current shape={self.shape}, new shape={shape}"
204
+ ) from e
205
+ else:
206
+ reshaped_tensor = self.tensor.reshape(shape)
207
+ return self.__class__(reshaped_tensor)
208
+
209
+ def memory_buffer(self):
210
+ """Creates a view of the memory buffer as a 1D tensor."""
211
+ m = cupy.cuda.UnownedMemory(self.data_ptr, self.size * self.itemsize, owner=self.tensor, device_id=self.device_id)
212
+ p = cupy.cuda.MemoryPointer(m, 0)
213
+ # TODO: ensure tensor is dense for now, and later support linear
214
+ # memory with constant stride.
215
+ t = cupy.ndarray(shape=(self.size,), dtype=self.dtype, memptr=p)
216
+ return CupyTensor(t)
217
+
218
+ def memory_buffer_to_tensor(self, shape, strides):
219
+ """
220
+ Creates a N-D tensor view of the memory buffer according to the specified
221
+ shape and strides.
222
+ """
223
+ assert len(self.shape) == 1, "Internal error."
224
+ m = cupy.cuda.UnownedMemory(self.data_ptr, self.size * self.itemsize, owner=self.tensor)
225
+ p = cupy.cuda.MemoryPointer(m, 0)
226
+ strides = [s * self.itemsize for s in strides]
227
+ t = cupy.ndarray(shape=shape, dtype=self.dtype, memptr=p, strides=strides)
228
+ return CupyTensor(t)
229
+
230
+
231
+ CupyTensor.host_tensor_class = HostTensor
232
+ HostTensor.host_tensor_class = HostTensor
233
+ CupyTensor.device_tensor_class = CupyTensor
234
+ HostTensor.device_tensor_class = CupyTensor
@@ -0,0 +1,147 @@
1
+ # Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ """
6
+ TensorHolder implementation that adapts ndbuffer for use with
7
+ the tensor_ifc interface. The class is meant for internal use only
8
+ (e.g. for internal operands of host APIs), but the NDBufferTensor
9
+ or underlying ndbuffer should never be returned to the user, because
10
+ 1. the ndbuffer is opaque, i.e. it missies most of typical tensor functionality, and
11
+ 2. we make no guarantees about the ndbuffer's API stability.
12
+ """
13
+
14
+ __all__ = ["NDBufferTensor"]
15
+
16
+ from collections.abc import Sequence
17
+
18
+ from . import ndbuffer, typemaps, utils
19
+ from .ndbuffer import NDBuffer, StridedLayout
20
+ from .package_ifc import StreamHolder
21
+ from .tensor_ifc import TensorHolder
22
+
23
+
24
+ class NDBufferTensor(TensorHolder[NDBuffer]):
25
+ """
26
+ TensorHolder for ndbuffer ndarrays.
27
+ """
28
+
29
+ name = "ndbuffer"
30
+ module = ndbuffer
31
+ name_to_dtype = TensorHolder.create_name_dtype_map(conversion_function=lambda name: name, exception_type=TypeError)
32
+
33
+ def __init__(self, tensor):
34
+ super().__init__(tensor)
35
+
36
+ @property
37
+ def data_ptr(self):
38
+ return self.tensor.data_ptr
39
+
40
+ @property
41
+ def device(self):
42
+ return self.tensor.device
43
+
44
+ @property
45
+ def device_id(self):
46
+ return self.tensor.device_id
47
+
48
+ @property
49
+ def dtype(self):
50
+ """Name of the data type"""
51
+ return self.tensor.dtype_name
52
+
53
+ @property
54
+ def itemsize(self):
55
+ return self.tensor.itemsize
56
+
57
+ @property
58
+ def shape(self):
59
+ return self.tensor.shape
60
+
61
+ @property
62
+ def size(self):
63
+ return self.tensor.size
64
+
65
+ @property
66
+ def strides(self):
67
+ return self.tensor.strides
68
+
69
+ @classmethod
70
+ def empty(
71
+ cls, shape, device_id="cpu", *, dtype="float32", strides=None, stream_holder: StreamHolder | None = None, **context
72
+ ):
73
+ """
74
+ Create an empty tensor of the specified shape and data type.
75
+
76
+ Note, that the strides, if specified, MUST correspond to a dense (possibly permuted)
77
+ tensor, otherwise the created tensor may be corrupted.
78
+ """
79
+ layout = StridedLayout(shape, strides, typemaps.NAME_TO_ITEM_SIZE[dtype])
80
+ if device_id == "cpu":
81
+ tensor = NDBuffer.empty(layout, dtype, "cpu", stream=stream_holder, **context)
82
+ else:
83
+ assert isinstance(device_id, int), "Internal Error: Cuda tensors must be allocated with an integer device_id."
84
+ with utils.device_ctx(device_id):
85
+ tensor = NDBuffer.empty(layout, dtype, device_id, stream=stream_holder, **context)
86
+ return cls(tensor)
87
+
88
+ def asndbuffer(self):
89
+ return self.tensor
90
+
91
+ def to(self, device_id, stream_holder):
92
+ src_device_id = self.tensor.device_id
93
+ if src_device_id == device_id:
94
+ return self
95
+
96
+ if stream_holder is None:
97
+ raise ValueError("Stream holder is required for h2d/d2h transfers.")
98
+
99
+ if device_id == "cpu":
100
+ with utils.device_ctx(src_device_id):
101
+ tensor = NDBuffer.empty_like(self.tensor, device_id="cpu", stream=stream_holder)
102
+ tensor.copy_(self.tensor, stream=stream_holder)
103
+ else:
104
+ with utils.device_ctx(device_id):
105
+ tensor = NDBuffer.empty_like(self.tensor, device_id=device_id, stream=stream_holder)
106
+ tensor.copy_(self.tensor, stream=stream_holder)
107
+
108
+ return NDBufferTensor(tensor)
109
+
110
+ def copy_(self, src, stream_holder):
111
+ """
112
+ Inplace copy of src (copy the data from src into self).
113
+ """
114
+ device_id = self.tensor.device_id
115
+ src_nd = src.asndbuffer()
116
+ if device_id == "cpu":
117
+ device_id = src_nd.device_id
118
+ if device_id == "cpu":
119
+ self.tensor.copy_(src_nd, stream=stream_holder)
120
+ else:
121
+ with utils.device_ctx(device_id):
122
+ self.tensor.copy_(src_nd, stream=stream_holder)
123
+
124
+ def istensor(self):
125
+ """
126
+ Check if the object is ndarray-like.
127
+ """
128
+ return isinstance(self.tensor, NDBuffer)
129
+
130
+ def reshape(self, shape: Sequence[int], *, copy: bool | None = None):
131
+ if copy:
132
+ raise NotImplementedError("Reshape with copy is not supported for ndbuffer")
133
+ return self.__class__(self.tensor.reshape(shape))
134
+
135
+ def memory_buffer(self):
136
+ """Creates a view of the memory buffer as a 1D tensor."""
137
+ layout = StridedLayout.dense(self.size, itemsize=self.itemsize)
138
+ return self.__class__(self.tensor.as_strided(layout))
139
+
140
+ def memory_buffer_to_tensor(self, shape, strides):
141
+ """
142
+ Creates a N-D tensor view of the memory buffer according to the specified
143
+ shape and strides.
144
+ """
145
+ assert len(self.shape) == 1, "Internal error."
146
+ layout = StridedLayout(shape, strides, itemsize=self.itemsize)
147
+ return self.__class__(self.tensor.as_strided(layout))
@@ -0,0 +1,184 @@
1
+ # Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ """
6
+ Interface to seamlessly use Numpy ndarray objects.
7
+ """
8
+
9
+ __all__ = ["NumpyTensor", "CudaTensor"]
10
+
11
+ from collections.abc import Sequence
12
+
13
+ import numpy
14
+ import numpy.typing as npt
15
+
16
+ from nvmath.internal.tensor_ifc_ndbuffer import NDBufferTensor
17
+
18
+ from . import utils
19
+ from .ndbuffer import NDBuffer
20
+ from .package_ifc import StreamHolder
21
+ from .tensor_ifc import TensorHolder
22
+
23
+
24
+ class CudaTensor(NDBufferTensor):
25
+ """
26
+ Wraps ndbuffer with data residing on the GPU.
27
+ It serves as a CUDA counterpart for NumpyTensor.
28
+ """
29
+
30
+ name = "cuda"
31
+ host_tensor_class: type["NumpyTensor"] # set once NumpyTensor is defined
32
+ device_tensor_class: type["CudaTensor"] # set once CudaTensor is defined
33
+
34
+ def __init__(self, tensor):
35
+ super().__init__(tensor)
36
+
37
+ @classmethod
38
+ def create_from_host(cls, tensor: TensorHolder, device_id: int, stream_holder: StreamHolder):
39
+ with utils.device_ctx(device_id):
40
+ src_ndbuffer = tensor.asndbuffer()
41
+ dst_ndbuffer = NDBuffer.empty_like(src_ndbuffer, device_id=device_id, stream=stream_holder)
42
+ dst_ndbuffer.copy_(src_ndbuffer, stream=stream_holder)
43
+ return cls(dst_ndbuffer)
44
+
45
+ def to(self, device_id, stream_holder):
46
+ if device_id == "cpu":
47
+ with utils.device_ctx(self.device_id):
48
+ dst = self.host_tensor_class.create_host_from(self, stream_holder)
49
+ return dst
50
+ elif device_id == self.device_id:
51
+ return self
52
+ elif isinstance(device_id, int):
53
+ raise ValueError(f"Unsupported copy between different devices {self.device_id} and {device_id}.")
54
+ else:
55
+ raise ValueError(f"The device must be specified as an integer or 'cpu', not '{device_id}'.")
56
+
57
+
58
+ class NumpyTensor(TensorHolder[npt.NDArray]):
59
+ """
60
+ TensorHolder for numpy ndarrays.
61
+ """
62
+
63
+ name = "numpy"
64
+ module = numpy
65
+ name_to_dtype = TensorHolder.create_name_dtype_map(
66
+ conversion_function=lambda name: numpy.dtype(name), exception_type=TypeError
67
+ )
68
+
69
+ host_tensor_class: type["NumpyTensor"] # set once NumpyTensor is defined
70
+ device_tensor_class: type["CudaTensor"] # set once CudaTensor is defined
71
+
72
+ def __init__(self, tensor):
73
+ super().__init__(tensor)
74
+
75
+ @property
76
+ def data_ptr(self):
77
+ return self.tensor.ctypes.data
78
+
79
+ @property
80
+ def device(self):
81
+ return "cpu"
82
+
83
+ @property
84
+ def device_id(self):
85
+ return "cpu"
86
+
87
+ @property
88
+ def dtype(self):
89
+ """Name of the data type"""
90
+ return self.tensor.dtype.name
91
+
92
+ @property
93
+ def itemsize(self):
94
+ return self.tensor.itemsize
95
+
96
+ @classmethod
97
+ def empty(cls, shape, device_id="cpu", *, dtype="float32", strides=None, **context):
98
+ """
99
+ Create an empty tensor of the specified shape and data type.
100
+ """
101
+ assert device_id == "cpu", "Internal Error: Numpy tensors must be allocated with device_id='cpu'"
102
+ dtype = NumpyTensor.name_to_dtype[dtype]
103
+ # when strides is not None, it should be of unit counts not bytes
104
+ return cls(
105
+ cls.module.ndarray(shape, dtype=dtype, strides=(tuple(s * dtype.itemsize for s in strides) if strides else None))
106
+ )
107
+
108
+ @classmethod
109
+ def create_host_from(cls, tensor: TensorHolder, stream_holder: StreamHolder):
110
+ src_nd = tensor.asndbuffer()
111
+ dst_nd = NDBuffer.empty_like(src_nd, device_id="cpu", stream=stream_holder)
112
+ dst_nd.copy_(src_nd, stream=stream_holder)
113
+ return cls(dst_nd.as_numpy())
114
+
115
+ @property
116
+ def shape(self):
117
+ return tuple(self.tensor.shape)
118
+
119
+ @property
120
+ def size(self):
121
+ return self.tensor.size
122
+
123
+ @property
124
+ def strides(self):
125
+ return tuple(stride_in_bytes // self.tensor.itemsize for stride_in_bytes in self.tensor.strides)
126
+
127
+ def asndbuffer(self):
128
+ return NDBuffer.from_numpy(self.tensor)
129
+
130
+ def to(self, device_id, stream_holder):
131
+ if device_id == "cpu":
132
+ return self
133
+ elif isinstance(device_id, int):
134
+ dst = self.device_tensor_class.create_from_host(self, device_id, stream_holder)
135
+ return dst
136
+ else:
137
+ raise ValueError(f"The device must be specified as an integer or 'cpu', not '{device_id}'.")
138
+
139
+ def copy_(self, src, stream_holder):
140
+ match src.name:
141
+ case "numpy":
142
+ numpy.copyto(self.tensor, src.tensor)
143
+ case _:
144
+ with utils.device_ctx(src.device_id):
145
+ self.asndbuffer().copy_(src.asndbuffer(), stream=stream_holder)
146
+
147
+ def istensor(self):
148
+ """
149
+ Check if the object is ndarray-like.
150
+ """
151
+ return isinstance(self.tensor, numpy.ndarray)
152
+
153
+ def reshape(self, shape: Sequence[int], *, copy: bool | None = None):
154
+ if int(numpy.__version__.split(".")[0]) < 2:
155
+ return self.__class__(numpy.reshape(self.tensor, shape))
156
+ else:
157
+ return self.__class__(numpy.reshape(self.tensor, shape, copy=copy))
158
+
159
+ def memory_buffer(self):
160
+ """Creates a view of the memory buffer as a 1D tensor."""
161
+ t = self.tensor
162
+ # TODO: ensure tensor is dense for now, and later support linear
163
+ # memory with constant stride.
164
+ v = NumpyTensor(t.ravel(order="K"))
165
+ assert v.data_ptr == self.data_ptr, "Internal error."
166
+ return v
167
+
168
+ def memory_buffer_to_tensor(self, shape, strides):
169
+ """
170
+ Creates a N-D tensor view of the memory buffer according to the specified
171
+ shape and strides.
172
+ """
173
+ assert len(self.shape) == 1, "Internal error."
174
+ t = self.tensor
175
+ strides = [s * self.itemsize for s in strides]
176
+ v = NumpyTensor(numpy.lib.stride_tricks.as_strided(t, shape=shape, strides=strides))
177
+ assert v.data_ptr == self.data_ptr, "Internal error."
178
+ return v
179
+
180
+
181
+ NumpyTensor.host_tensor_class = NumpyTensor
182
+ CudaTensor.host_tensor_class = NumpyTensor
183
+ NumpyTensor.device_tensor_class = CudaTensor
184
+ CudaTensor.device_tensor_class = CudaTensor