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,141 @@
1
+ # Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ """
6
+ Interface to seamlessly use distributed Torch tensor objects.
7
+ """
8
+
9
+ from __future__ import annotations # allows typehint of class methods to return the self class
10
+
11
+ __all__ = ["TorchDistributedTensor"]
12
+
13
+ import math
14
+
15
+ try:
16
+ import torch
17
+ except ImportError:
18
+ torch = None # type: ignore
19
+
20
+ from collections.abc import Sequence
21
+
22
+ import nvmath.distributed
23
+ from nvmath.distributed._internal.nvshmem import nvshmem_empty_dlpack
24
+ from nvmath.internal.package_ifc import StreamHolder
25
+ from nvmath.internal.tensor_ifc_torch import TorchTensor
26
+ from nvmath.internal.utils import device_ctx
27
+
28
+ from .tensor_ifc import DistributedTensor
29
+
30
+
31
+ # Most methods aren't redefined, because they simply act on the local array
32
+ class TorchDistributedTensor(TorchTensor, DistributedTensor):
33
+ """
34
+ TensorHolder for distributed torch tensors.
35
+ """
36
+
37
+ def __init__(self, tensor):
38
+ super().__init__(tensor)
39
+
40
+ @classmethod
41
+ def empty(
42
+ cls, shape, device_id="cpu", *, dtype="float32", strides=None, stream_holder: StreamHolder | None = None, **context
43
+ ) -> TorchDistributedTensor:
44
+ """
45
+ Create an empty tensor of the specified shape and data type on the specified device
46
+ (None, 'cpu', or device id).
47
+
48
+ Note, that the strides, if specified, should correspond to a dense
49
+ (possibly permuted) tensor and MUST NOT overlap.
50
+ Otherwise, the behaviour is not defined.
51
+ """
52
+ symmetric_memory = context.pop("symmetric_memory", False)
53
+ make_symmetric = context.pop("make_symmetric", False)
54
+ skip_symmetric_check = context.pop("skip_symmetric_check", False)
55
+
56
+ if device_id == "cpu":
57
+ if symmetric_memory or make_symmetric or skip_symmetric_check:
58
+ raise ValueError("symmetric memory options cannot be used when allocating tensor on CPU")
59
+ return super().empty(shape, device_id, dtype=dtype, strides=strides, **context)
60
+
61
+ ctx = nvmath.distributed.get_context()
62
+ assert ctx is not None, "nvmath.distributed has not been initialized"
63
+
64
+ logger = context.get("logger")
65
+
66
+ if not symmetric_memory:
67
+ if make_symmetric or skip_symmetric_check:
68
+ raise ValueError("Use of symmetric memory option with symmetric_memory=False")
69
+ return super().empty(
70
+ shape, device_id=device_id, dtype=dtype, strides=strides, stream_holder=stream_holder, **context
71
+ )
72
+
73
+ dtype = TorchTensor.name_to_dtype[dtype]
74
+
75
+ with device_ctx(device_id):
76
+ size = math.prod(shape, start=dtype.itemsize)
77
+ # TODO: ideally strides should be set in DLPack, but cuda.core doesn't support
78
+ # ndarray yet and instead returns a flat buffer.
79
+ dlpack_buf = nvshmem_empty_dlpack(
80
+ size,
81
+ device_id,
82
+ ctx.process_group,
83
+ make_symmetric=make_symmetric,
84
+ skip_symmetric_check=skip_symmetric_check,
85
+ logger=logger,
86
+ )
87
+ tensor = torch.from_dlpack(dlpack_buf)
88
+ # Buffer may be padded if make_symmetric=True.
89
+ tensor = tensor[:size]
90
+ if strides is None:
91
+ tensor = tensor.view(dtype).view(shape)
92
+ else:
93
+ tensor = torch.as_strided(tensor.view(dtype), shape, strides)
94
+
95
+ return cls(tensor)
96
+
97
+ def to(self, device_id, stream_holder, symmetric_memory: bool = False) -> TorchDistributedTensor:
98
+ """
99
+ In addition to the base class semantics:
100
+ - Source or target device must be the one used to initialize NVSHMEM on this
101
+ process. This implies that copy from one CUDA device to another is not allowed.
102
+ - Memory layout is preserved.
103
+ - Strides must be non-overlapping.
104
+ """
105
+ if not (device_id == "cpu" or isinstance(device_id, int)):
106
+ raise ValueError(f"The device must be specified as an integer or 'cpu', not '{device_id}'.")
107
+
108
+ blocking = (device_id == "cpu") or (self.device_id == "cpu")
109
+
110
+ # To CPU or same device
111
+ if device_id == "cpu" or self.device_id == device_id:
112
+ with stream_holder.ctx:
113
+ tensor = self.tensor.to(device=device_id, non_blocking=not blocking)
114
+ result = TorchDistributedTensor(tensor)
115
+ assert result.is_symmetric_memory == symmetric_memory
116
+ return result
117
+
118
+ # Currently we don't allow copy from one device to another for distributed
119
+ # tensors (see comment in CupyDistributedTensor.to()).
120
+ if self.device_id != "cpu" and self.device_id != device_id:
121
+ raise ValueError("Cannot copy distributed tensor to a different CUDA device")
122
+
123
+ # CPU to GPU
124
+ with stream_holder.ctx:
125
+ tensor_device = TorchDistributedTensor.empty(
126
+ self.shape,
127
+ device_id=device_id,
128
+ dtype=self.dtype,
129
+ strides=self.strides,
130
+ stream_holder=stream_holder,
131
+ make_symmetric=symmetric_memory,
132
+ symmetric_memory=symmetric_memory,
133
+ )
134
+ tensor_device.tensor.copy_(self.tensor, non_blocking=not blocking)
135
+ assert tensor_device.is_symmetric_memory == symmetric_memory
136
+ return tensor_device
137
+
138
+ def reshape(self, shape: Sequence[int], *, copy: bool | None = None) -> TorchDistributedTensor:
139
+ if copy and self.device_id != "cpu":
140
+ raise NotImplementedError("reshape with copy=True is not supported for TorchDistributedTensor on GPU")
141
+ return super().reshape(shape, copy=copy)
@@ -0,0 +1,78 @@
1
+ # Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ """
6
+ Entry point to using tensors from different libraries seamlessly.
7
+ """
8
+
9
+ __all__ = ["wrap_operand", "copy_"]
10
+
11
+ import warnings
12
+ from collections.abc import Sequence
13
+
14
+ from nvmath.internal.tensor_ifc import Tensor, TensorHolder
15
+ from nvmath.internal.tensor_wrapper import (
16
+ infer_tensor_package as base_infer_tensor_package,
17
+ )
18
+ from nvmath.internal.tensor_wrapper import (
19
+ maybe_register_package as base_maybe_register_package,
20
+ )
21
+
22
+ from .tensor_ifc import DistributedTensor
23
+ from .tensor_ifc_numpy import CudaDistributedTensor, NumpyDistributedTensor
24
+
25
+ _TENSOR_TYPES: dict[str, type[DistributedTensor]] = {"numpy": NumpyDistributedTensor, "cuda": CudaDistributedTensor}
26
+
27
+
28
+ def infer_tensor_package(tensor):
29
+ """
30
+ Infer the package that defines this tensor.
31
+ """
32
+ package = base_infer_tensor_package(tensor)
33
+ # Use call_base=False because base_infer_tensor_package already
34
+ # called base_maybe_register_package
35
+ maybe_register_package(package, call_base=False)
36
+ return package
37
+
38
+
39
+ def maybe_register_package(package, call_base=True):
40
+ if call_base:
41
+ base_maybe_register_package(package)
42
+ if package == "torch":
43
+ from .tensor_ifc_torch import TorchDistributedTensor
44
+
45
+ _TENSOR_TYPES[package] = TorchDistributedTensor
46
+ elif package == "cupy":
47
+ from .tensor_ifc_cupy import CupyDistributedTensor, HostDistributedTensor
48
+
49
+ _TENSOR_TYPES["cupy"] = CupyDistributedTensor
50
+ _TENSOR_TYPES["cupy_host"] = HostDistributedTensor
51
+ elif package != "numpy":
52
+ raise AssertionError(f"Internal error: unrecognized package {package}")
53
+
54
+
55
+ def wrap_operand(native_operand: Tensor) -> DistributedTensor[Tensor]:
56
+ """
57
+ Wrap one "native" operand so that package-agnostic API can be used.
58
+ """
59
+ if isinstance(native_operand, TensorHolder):
60
+ msg = (
61
+ "wrap_operand() is being called unnecessarily because the input is already a TensorHolder. "
62
+ "Only public facing APIs should call wrap_operand(). "
63
+ "Internal APIs should assume the operands are TensorHolder already."
64
+ "Trying to wrap a TensorHolder will become an error in the future."
65
+ )
66
+ warnings.warn(msg, DeprecationWarning)
67
+ assert isinstance(native_operand, DistributedTensor)
68
+ return native_operand
69
+ wrapped_operand = _TENSOR_TYPES[infer_tensor_package(native_operand)](native_operand)
70
+ return wrapped_operand
71
+
72
+
73
+ def copy_(src: Sequence[TensorHolder], dest: Sequence[TensorHolder], stream_holder):
74
+ """
75
+ Copy the wrapped operands in dest to the corresponding wrapped operands in src.
76
+ """
77
+ for s, d in zip(src, dest, strict=True):
78
+ d.copy_(s, stream_holder=stream_holder)
@@ -0,0 +1,167 @@
1
+ # Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from __future__ import annotations
6
+
7
+ __all__ = ["allocate_symmetric_memory", "free_symmetric_memory"]
8
+
9
+ from collections.abc import Iterable, Sequence
10
+ from logging import Logger
11
+ from types import ModuleType
12
+ from typing import TYPE_CHECKING, Literal
13
+
14
+ if TYPE_CHECKING:
15
+ import torch
16
+
17
+ import numpy as np
18
+ from numpy.typing import DTypeLike
19
+
20
+ import nvmath.distributed
21
+ from nvmath.distributed._internal import tensor_wrapper
22
+ from nvmath.internal.utils import device_ctx
23
+
24
+ # Supported packages for tensors backed by symmetric memory.
25
+ _SUPPORTED_PACKAGES = ("cupy", "torch")
26
+
27
+
28
+ # TODO: do a general refactor of this function in nvmath
29
+ def calculate_strides(shape: Sequence[int], axis_order: Iterable[int]):
30
+ """
31
+ Calculate the strides for the provided shape and axis order.
32
+ """
33
+ strides = [0] * len(shape)
34
+
35
+ stride = 1
36
+ for axis in axis_order:
37
+ strides[axis] = stride
38
+ stride *= shape[axis]
39
+
40
+ return strides
41
+
42
+
43
+ def allocate_symmetric_memory(
44
+ shape: int | Sequence[int],
45
+ package: ModuleType,
46
+ *,
47
+ dtype: DTypeLike | torch.dtype | None = None,
48
+ axis_order: Literal["C", "F"] | Sequence[int] = "C",
49
+ make_symmetric: bool = False,
50
+ skip_symmetric_check: bool = False,
51
+ logger: Logger | None = None,
52
+ ):
53
+ """Return uninitialized tensor of given shape and type, allocated from the NVSHMEM
54
+ symmetric heap, on the device on which nvmath.distributed was initialized. The
55
+ tensor type is determined by the provided package (e.g. cupy, torch).
56
+ **This is a collective operation and must be called by all processes**.
57
+ Note that the buffer size must be the same on all processes, or you can
58
+ use ``make_symmetric=True`` to pad all buffers to the same max size.
59
+
60
+ Args:
61
+ shape: Shape of the tensor to allocate.
62
+
63
+ package: Python package determining the tensor type (e.g. cupy, torch).
64
+
65
+ dtype: Tensor dtype in a form recognized by the package. If None, will use the
66
+ package's default dtype.
67
+
68
+ axis_order: Axis order. The default is 'C' (row-major ordering).
69
+
70
+ make_symmetric: If buffer sizes do not match across processes, will allocate
71
+ the maximum size on every process to ensure the allocation is symmetric.
72
+ The default is False.
73
+
74
+ skip_symmetric_check: Skip checking that the allocation is symmetric (which
75
+ requires inter-process communication). The default is False.
76
+
77
+ logger (logging.Logger): Python Logger object. The root logger will be used if a
78
+ logger object is not provided.
79
+ """
80
+
81
+ if package.__name__ not in _SUPPORTED_PACKAGES:
82
+ raise ValueError(f"The package must be one of {_SUPPORTED_PACKAGES}. Got {package}.")
83
+
84
+ distributed_ctx = nvmath.distributed.get_context()
85
+ if distributed_ctx is None:
86
+ raise RuntimeError(
87
+ "nvmath.distributed has not been initialized. Refer to "
88
+ "https://docs.nvidia.com/cuda/nvmath-python/latest/distributed-apis/runtime.html"
89
+ " for more information."
90
+ )
91
+ if not distributed_ctx.nvshmem_available:
92
+ raise RuntimeError("nvmath.distributed wasn't initialized with NVSHMEM backend")
93
+
94
+ device_id = distributed_ctx.device_id
95
+
96
+ if isinstance(shape, int):
97
+ shape = (shape,)
98
+
99
+ strides = None
100
+ if axis_order is not None:
101
+ if axis_order == "C":
102
+ strides = calculate_strides(shape, reversed(range(len(shape))))
103
+ elif axis_order == "F":
104
+ strides = calculate_strides(shape, range(len(shape)))
105
+ else:
106
+ strides = calculate_strides(shape, axis_order)
107
+
108
+ if package.__name__ == "cupy":
109
+ from ._internal.tensor_ifc_cupy import CupyDistributedTensor
110
+
111
+ if dtype is None:
112
+ # This mimics numpy and cupy
113
+ dtype = np.float64
114
+
115
+ dtype = np.dtype(dtype).name # type: ignore
116
+ return CupyDistributedTensor.empty(
117
+ shape,
118
+ dtype=dtype,
119
+ device_id=device_id,
120
+ strides=strides,
121
+ symmetric_memory=True,
122
+ make_symmetric=make_symmetric,
123
+ skip_symmetric_check=skip_symmetric_check,
124
+ logger=logger,
125
+ ).tensor
126
+ elif package.__name__ == "torch":
127
+ from ._internal.tensor_ifc_torch import TorchDistributedTensor
128
+
129
+ if dtype is None:
130
+ import torch
131
+
132
+ dtype = torch.get_default_dtype()
133
+
134
+ dtype = str(dtype).split(".")[1]
135
+ return TorchDistributedTensor.empty(
136
+ shape,
137
+ dtype=dtype,
138
+ device_id=device_id,
139
+ strides=strides,
140
+ symmetric_memory=True,
141
+ make_symmetric=make_symmetric,
142
+ skip_symmetric_check=skip_symmetric_check,
143
+ logger=logger,
144
+ ).tensor
145
+
146
+
147
+ def free_symmetric_memory(*tensors) -> None:
148
+ """Frees tensors' data buffer where the buffer was allocated on the NVSHMEM
149
+ symmetric heap. Note that this is only meant to be called on tensors returned
150
+ by ``allocate_symmetric_memory()``.
151
+
152
+ **This is a collective operation and must be called by all processes, with tensors
153
+ in the same order**."""
154
+
155
+ device_id = tensor_wrapper.wrap_operand(tensors[0]).device_id
156
+ if device_id == "cpu":
157
+ raise TypeError("free_symmetric_memory called on CPU array/tensor")
158
+
159
+ with device_ctx(device_id):
160
+ for tensor in tensors:
161
+ wrapped_tensor = tensor_wrapper.wrap_operand(tensor)
162
+ if wrapped_tensor.device_id == "cpu":
163
+ raise TypeError("free_symmetric_memory called on CPU array/tensor")
164
+
165
+ assert wrapped_tensor.device_id == device_id, "Internal error: symmetric memory tensors are not on the same device"
166
+
167
+ wrapped_tensor.free_symmetric()