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.
- nvmath/__init__.pxd +0 -0
- nvmath/__init__.py +45 -0
- nvmath/_internal/__init__.py +0 -0
- nvmath/_internal/attribute_ifc_factory.py +330 -0
- nvmath/_internal/layout.py +70 -0
- nvmath/_internal/templates.py +383 -0
- nvmath/_utils.py +150 -0
- nvmath/bindings/__init__.py +51 -0
- nvmath/bindings/_internal/__init__.pxd +0 -0
- nvmath/bindings/_internal/__init__.py +0 -0
- nvmath/bindings/_internal/cublas.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cublas.pxd +530 -0
- nvmath/bindings/_internal/cublasLt.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cublasLt.pxd +59 -0
- nvmath/bindings/_internal/cublasMp.pxd +52 -0
- nvmath/bindings/_internal/cudss.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cudss.pxd +47 -0
- nvmath/bindings/_internal/cufft.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cufft.pxd +70 -0
- nvmath/bindings/_internal/cufftMp.pxd +77 -0
- nvmath/bindings/_internal/curand.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/curand.pxd +42 -0
- nvmath/bindings/_internal/cusolver.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cusolver.pxd +15 -0
- nvmath/bindings/_internal/cusolverDn.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cusolverDn.pxd +406 -0
- nvmath/bindings/_internal/cusparse.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cusparse.pxd +277 -0
- nvmath/bindings/_internal/cusparseLt.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cusparseLt.pxd +48 -0
- nvmath/bindings/_internal/cutensor.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cutensor.pxd +58 -0
- nvmath/bindings/_internal/mathdx.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/mathdx.pxd +116 -0
- nvmath/bindings/_internal/nvshmem.pxd +29 -0
- nvmath/bindings/_internal/utils.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/utils.pxd +179 -0
- nvmath/bindings/_internal/utils.pyi +10 -0
- nvmath/bindings/cublas.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/cublas.pxd +558 -0
- nvmath/bindings/cublas.pyi +746 -0
- nvmath/bindings/cublasLt.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/cublasLt.pxd +109 -0
- nvmath/bindings/cublasLt.pyi +1337 -0
- nvmath/bindings/cublasMp.pxd +85 -0
- nvmath/bindings/cublasMp.pyi +219 -0
- nvmath/bindings/cudss.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/cudss.pxd +86 -0
- nvmath/bindings/cudss.pyi +282 -0
- nvmath/bindings/cufft.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/cufft.pxd +118 -0
- nvmath/bindings/cufft.pyi +241 -0
- nvmath/bindings/cufftMp.pxd +124 -0
- nvmath/bindings/cufftMp.pyi +260 -0
- nvmath/bindings/curand.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/curand.pxd +71 -0
- nvmath/bindings/curand.pyi +159 -0
- nvmath/bindings/cusolver.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/cusolver.pxd +62 -0
- nvmath/bindings/cusolver.pyi +242 -0
- nvmath/bindings/cusolverDn.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/cusolverDn.pxd +430 -0
- nvmath/bindings/cusolverDn.pyi +416 -0
- nvmath/bindings/cusparse.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/cusparse.pxd +338 -0
- nvmath/bindings/cusparse.pyi +659 -0
- nvmath/bindings/cusparseLt.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/cusparseLt.pxd +99 -0
- nvmath/bindings/cusparseLt.pyi +198 -0
- nvmath/bindings/cutensor.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/cutensor.pxd +98 -0
- nvmath/bindings/cutensor.pyi +294 -0
- nvmath/bindings/cycublas.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/cycublas.pxd +684 -0
- nvmath/bindings/cycublasLt.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/cycublasLt.pxd +1055 -0
- nvmath/bindings/cycublasMp.pxd +183 -0
- nvmath/bindings/cycudss.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/cycudss.pxd +224 -0
- nvmath/bindings/cycufft.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/cycufft.pxd +326 -0
- nvmath/bindings/cycufftMp.pxd +334 -0
- nvmath/bindings/cycurand.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/cycurand.pxd +146 -0
- nvmath/bindings/cycusolver.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/cycusolver.pxd +154 -0
- nvmath/bindings/cycusolverDn.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/cycusolverDn.pxd +446 -0
- nvmath/bindings/cycusparse.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/cycusparse.pxd +470 -0
- nvmath/bindings/cycusparseLt.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/cycusparseLt.pxd +150 -0
- nvmath/bindings/cycutensor.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/cycutensor.pxd +192 -0
- nvmath/bindings/cymathdx.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/cymathdx.pxd +552 -0
- nvmath/bindings/cynvshmem.pxd +126 -0
- nvmath/bindings/mathdx.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/mathdx.pxd +182 -0
- nvmath/bindings/mathdx.pyi +1244 -0
- nvmath/bindings/nvpl/__init__.pxd +0 -0
- nvmath/bindings/nvpl/__init__.py +13 -0
- nvmath/bindings/nvpl/_internal/__init__.pxd +0 -0
- nvmath/bindings/nvpl/_internal/__init__.py +0 -0
- nvmath/bindings/nvpl/_internal/blas.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/nvpl/_internal/blas.pxd +125 -0
- nvmath/bindings/nvpl/_internal/fft.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/nvpl/_internal/fft.pxd +36 -0
- nvmath/bindings/nvpl/blas.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/nvpl/blas.pxd +85 -0
- nvmath/bindings/nvpl/blas.pyi +122 -0
- nvmath/bindings/nvpl/cyblas.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/nvpl/cyblas.pxd +166 -0
- nvmath/bindings/nvpl/cyfft.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/nvpl/cyfft.pxd +92 -0
- nvmath/bindings/nvpl/fft.cp314-win_amd64.pyd +0 -0
- nvmath/bindings/nvpl/fft.pxd +100 -0
- nvmath/bindings/nvpl/fft.pyi +100 -0
- nvmath/bindings/nvshmem.pxd +54 -0
- nvmath/bindings/nvshmem.pyi +179 -0
- nvmath/device/__init__.py +21 -0
- nvmath/device/_deprecated.py +33 -0
- nvmath/device/common.py +313 -0
- nvmath/device/common_backend.py +131 -0
- nvmath/device/common_cuda.py +201 -0
- nvmath/device/common_numba.py +310 -0
- nvmath/device/common_opaque_tensor.py +201 -0
- nvmath/device/cublasdx.py +1805 -0
- nvmath/device/cublasdx_backend.py +807 -0
- nvmath/device/cublasdx_numba.py +1612 -0
- nvmath/device/cufftdx.py +510 -0
- nvmath/device/cufftdx_backend.py +196 -0
- nvmath/device/cufftdx_numba.py +196 -0
- nvmath/device/curand_kernel.py +9147 -0
- nvmath/device/cusolverdx.py +2690 -0
- nvmath/device/cusolverdx_backend.py +440 -0
- nvmath/device/cusolverdx_numba.py +1624 -0
- nvmath/device/llvm_array.py +29 -0
- nvmath/device/random.py +445 -0
- nvmath/device/random_helpers.py +23 -0
- nvmath/device/random_states.py +187 -0
- nvmath/device/types.py +147 -0
- nvmath/device/vector_types_numba.py +203 -0
- nvmath/distributed/__init__.py +205 -0
- nvmath/distributed/_internal/__init__.py +0 -0
- nvmath/distributed/_internal/nvshmem.py +302 -0
- nvmath/distributed/_internal/tensor_ifc.py +67 -0
- nvmath/distributed/_internal/tensor_ifc_cupy.py +62 -0
- nvmath/distributed/_internal/tensor_ifc_host_device.py +165 -0
- nvmath/distributed/_internal/tensor_ifc_numpy.py +41 -0
- nvmath/distributed/_internal/tensor_ifc_torch.py +141 -0
- nvmath/distributed/_internal/tensor_wrapper.py +78 -0
- nvmath/distributed/_utils.py +167 -0
- nvmath/distributed/distribution.py +770 -0
- nvmath/distributed/fft/__init__.py +7 -0
- nvmath/distributed/fft/_configuration.py +79 -0
- nvmath/distributed/fft/fft.py +2801 -0
- nvmath/distributed/linalg/__init__.py +12 -0
- nvmath/distributed/linalg/_internal/__init__.py +3 -0
- nvmath/distributed/linalg/_internal/epilog_protocol.py +496 -0
- nvmath/distributed/linalg/_internal/matmul_desc_ifc.py +28 -0
- nvmath/distributed/linalg/advanced/__init__.py +8 -0
- nvmath/distributed/linalg/advanced/_configuration.py +166 -0
- nvmath/distributed/linalg/advanced/matmulmod.py +2908 -0
- nvmath/distributed/process_group.py +408 -0
- nvmath/distributed/reshape/__init__.py +6 -0
- nvmath/distributed/reshape/_configuration.py +39 -0
- nvmath/distributed/reshape/reshape.py +1256 -0
- nvmath/fft/__init__.py +7 -0
- nvmath/fft/_configuration.py +208 -0
- nvmath/fft/_exec_utils.py +109 -0
- nvmath/fft/_helpers.py +237 -0
- nvmath/fft/fft.py +2903 -0
- nvmath/internal/__init__.pxd +3 -0
- nvmath/internal/__init__.py +10 -0
- nvmath/internal/_bindings.cp314-win_amd64.pyd +0 -0
- nvmath/internal/_bindings.pxd +12 -0
- nvmath/internal/_device_utils.py +54 -0
- nvmath/internal/enum_utils.py +142 -0
- nvmath/internal/formatters.py +87 -0
- nvmath/internal/mem_limit.py +51 -0
- nvmath/internal/memory.cp314-win_amd64.pyd +0 -0
- nvmath/internal/memory.pxd +10 -0
- nvmath/internal/memory.pyi +46 -0
- nvmath/internal/ndbuffer/__init__.pxd +3 -0
- nvmath/internal/ndbuffer/__init__.py +7 -0
- nvmath/internal/ndbuffer/copy_kernel/args.h +34 -0
- nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/array_view.h +52 -0
- nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/elementwise.h +68 -0
- nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/grid_indexer.h +69 -0
- nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/transposed.h +240 -0
- nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/type_utils.h +39 -0
- nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/utils.h +132 -0
- nvmath/internal/ndbuffer/copy_kernel/copy_kernel_impl/vec.h +159 -0
- nvmath/internal/ndbuffer/copy_kernel/elementwise.h +53 -0
- nvmath/internal/ndbuffer/copy_kernel/transposed.h +58 -0
- nvmath/internal/ndbuffer/copy_kernel.cp314-win_amd64.pyd +0 -0
- nvmath/internal/ndbuffer/copy_kernel.pxd +9 -0
- nvmath/internal/ndbuffer/copy_kernel.pyi +9 -0
- nvmath/internal/ndbuffer/data_layout.cp314-win_amd64.pyd +0 -0
- nvmath/internal/ndbuffer/data_layout.pxd +72 -0
- nvmath/internal/ndbuffer/data_layout.pyi +23 -0
- nvmath/internal/ndbuffer/jit.cp314-win_amd64.pyd +0 -0
- nvmath/internal/ndbuffer/jit.pxd +7 -0
- nvmath/internal/ndbuffer/jit.pyi +6 -0
- nvmath/internal/ndbuffer/ndbuffer.cp314-win_amd64.pyd +0 -0
- nvmath/internal/ndbuffer/ndbuffer.pxd +36 -0
- nvmath/internal/ndbuffer/ndbuffer.pyi +41 -0
- nvmath/internal/ndbuffer/package_utils.cp314-win_amd64.pyd +0 -0
- nvmath/internal/ndbuffer/package_utils.pxd +11 -0
- nvmath/internal/ndbuffer/package_utils.pyi +12 -0
- nvmath/internal/package_ifc.py +147 -0
- nvmath/internal/package_ifc_cuda.py +49 -0
- nvmath/internal/package_ifc_cupy.py +49 -0
- nvmath/internal/package_ifc_torch.py +31 -0
- nvmath/internal/package_wrapper.py +14 -0
- nvmath/internal/tensor_ifc.py +194 -0
- nvmath/internal/tensor_ifc_cupy.py +241 -0
- nvmath/internal/tensor_ifc_ndbuffer.py +153 -0
- nvmath/internal/tensor_ifc_numpy.py +183 -0
- nvmath/internal/tensor_ifc_torch.py +176 -0
- nvmath/internal/tensor_wrapper.py +157 -0
- nvmath/internal/typemaps.py +162 -0
- nvmath/internal/utils.py +771 -0
- nvmath/linalg/__init__.py +46 -0
- nvmath/linalg/_internal/__init__.py +3 -0
- nvmath/linalg/_internal/algo_cap_ifc.py +82 -0
- nvmath/linalg/_internal/algo_config_ifc.py +43 -0
- nvmath/linalg/_internal/batch.py +217 -0
- nvmath/linalg/_internal/enum_to_tuples.py +64 -0
- nvmath/linalg/_internal/epilog_protocol.py +766 -0
- nvmath/linalg/_internal/layout.py +624 -0
- nvmath/linalg/_internal/matmul_desc_ifc.py +28 -0
- nvmath/linalg/_internal/matmul_pref_ifc.py +27 -0
- nvmath/linalg/_internal/matrix_layout_ifc.py +26 -0
- nvmath/linalg/_internal/typemaps.py +144 -0
- nvmath/linalg/_internal/utils.py +134 -0
- nvmath/linalg/advanced/__init__.py +8 -0
- nvmath/linalg/advanced/_algorithmmod.py +149 -0
- nvmath/linalg/advanced/_configuration.py +349 -0
- nvmath/linalg/advanced/helpers/__init__.py +5 -0
- nvmath/linalg/advanced/helpers/matmul.py +1348 -0
- nvmath/linalg/advanced/matmulmod.py +3937 -0
- nvmath/linalg/generic/__init__.py +43 -0
- nvmath/linalg/generic/_configuration/__init__.py +37 -0
- nvmath/linalg/generic/_configuration/layout.py +263 -0
- nvmath/linalg/generic/_configuration/match.py +609 -0
- nvmath/linalg/generic/_configuration/qualifiers.py +494 -0
- nvmath/linalg/generic/_configuration/wrap.py +217 -0
- nvmath/linalg/generic/_dtype.py +15 -0
- nvmath/linalg/generic/matmulmod.py +1060 -0
- nvmath/memory.py +282 -0
- nvmath/sparse/__init__.py +38 -0
- nvmath/sparse/_internal/__init__.py +21 -0
- nvmath/sparse/_internal/common_utils.py +144 -0
- nvmath/sparse/_internal/cudss_config_ifc.py +741 -0
- nvmath/sparse/_internal/cudss_data_ifc.py +399 -0
- nvmath/sparse/_internal/cudss_utils.py +445 -0
- nvmath/sparse/_internal/cusparse_utils.py +382 -0
- nvmath/sparse/_internal/sparse_bsc_ifc.py +300 -0
- nvmath/sparse/_internal/sparse_bsr_ifc.py +303 -0
- nvmath/sparse/_internal/sparse_coo_ifc.py +254 -0
- nvmath/sparse/_internal/sparse_csc_ifc.py +266 -0
- nvmath/sparse/_internal/sparse_csr_ifc.py +266 -0
- nvmath/sparse/_internal/sparse_dia_ifc.py +239 -0
- nvmath/sparse/_internal/sparse_format_helpers.py +601 -0
- nvmath/sparse/_internal/sparse_tensor_ifc.py +121 -0
- nvmath/sparse/_internal/sparse_ust_ifc.py +146 -0
- nvmath/sparse/_internal/utils.py +56 -0
- nvmath/sparse/advanced/__init__.py +7 -0
- nvmath/sparse/advanced/_configuration.py +230 -0
- nvmath/sparse/advanced/direct_solver.py +1884 -0
- nvmath/sparse/generic/__init__.py +7 -0
- nvmath/sparse/generic/_configuration.py +129 -0
- nvmath/sparse/generic/_helpers.py +137 -0
- nvmath/sparse/generic/_thunks.py +21 -0
- nvmath/sparse/generic/matmulmod.py +2426 -0
- nvmath/sparse/ust/__init__.py +7 -0
- nvmath/sparse/ust/_converters.py +378 -0
- nvmath/sparse/ust/_drawer.py +552 -0
- nvmath/sparse/ust/_emitter.py +553 -0
- nvmath/sparse/ust/_jit.py +212 -0
- nvmath/sparse/ust/_kernel.py +346 -0
- nvmath/sparse/ust/_semiring.py +71 -0
- nvmath/sparse/ust/_utils.py +102 -0
- nvmath/sparse/ust/interfaces/__init__.py +0 -0
- nvmath/sparse/ust/interfaces/torch_interface.py +476 -0
- nvmath/sparse/ust/semiring_ops.py +71 -0
- nvmath/sparse/ust/tensor.py +1027 -0
- nvmath/sparse/ust/tensor_drawer.py +552 -0
- nvmath/sparse/ust/tensor_emitter.py +558 -0
- nvmath/sparse/ust/tensor_format.py +935 -0
- nvmath/sparse/ust/tensor_jit.py +212 -0
- nvmath/sparse/ust/tensor_kernel.py +348 -0
- nvmath/sparse/ust/tensor_utils.py +380 -0
- nvmath/tensor/__init__.py +6 -0
- nvmath/tensor/_configuration.py +95 -0
- nvmath/tensor/_internal/__init__.py +3 -0
- nvmath/tensor/_internal/cutensor_config_ifc.py +247 -0
- nvmath/tensor/_internal/cutensor_utils.py +162 -0
- nvmath/tensor/_internal/data.py +43 -0
- nvmath/tensor/_internal/einsum_parser.py +444 -0
- nvmath/tensor/_internal/typemaps.py +96 -0
- nvmath/tensor/contract.py +1861 -0
- nvmath_python-0.9.0.dist-info/METADATA +127 -0
- nvmath_python-0.9.0.dist-info/RECORD +309 -0
- nvmath_python-0.9.0.dist-info/WHEEL +5 -0
- nvmath_python-0.9.0.dist-info/licenses/LICENSE +177 -0
- nvmath_python-0.9.0.dist-info/top_level.txt +2 -0
nvmath/device/types.py
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"Complex",
|
|
7
|
+
"Vector",
|
|
8
|
+
"complex32",
|
|
9
|
+
"complex64",
|
|
10
|
+
"complex128",
|
|
11
|
+
"half2",
|
|
12
|
+
"half4",
|
|
13
|
+
"np_float16x2",
|
|
14
|
+
"np_float16x4",
|
|
15
|
+
"REAL_NP_TYPES",
|
|
16
|
+
"INT_NP_TYPES",
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
import warnings
|
|
20
|
+
|
|
21
|
+
import numpy as np
|
|
22
|
+
|
|
23
|
+
from ._deprecated import deprecated
|
|
24
|
+
|
|
25
|
+
np_float16x2 = np.dtype([("x", np.float16), ("y", np.float16)], align=True)
|
|
26
|
+
np_float16x4 = np.dtype([("x", np.float16), ("y", np.float16), ("z", np.float16), ("w", np.float16)], align=True)
|
|
27
|
+
|
|
28
|
+
REAL_NP_TYPES: list = [np.float16, np.float32, np.float64]
|
|
29
|
+
INT_NP_TYPES: list = [np.int8, np.int16, np.int32, np.int64, np.uint8, np.uint16, np.uint32, np.uint64]
|
|
30
|
+
|
|
31
|
+
_alignment_warning_msg = (
|
|
32
|
+
"You are using the host counterpart of a dtype that is under-aligned "
|
|
33
|
+
"compared to what the device function expects. In most cases this will "
|
|
34
|
+
"work, since device memory is typically allocated with at least 256-byte "
|
|
35
|
+
"alignment. For details, please review the alignment guidelines at "
|
|
36
|
+
"https://nvidia.com/docs/nvmath/alignment"
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class Complex:
|
|
41
|
+
"""
|
|
42
|
+
Complex type that can be used to represent complex numbers both
|
|
43
|
+
on host and device side. Numpy does not provide a built-in complex type with
|
|
44
|
+
16-bit real and imaginary parts, so we define our own dtype for that case.
|
|
45
|
+
For 32-bit and 64-bit complex numbers, we can use the built-in numpy dtypes.
|
|
46
|
+
However on device side we expect those types to be aligned to the full size
|
|
47
|
+
of the complex type, so the array defined on host and device side will have
|
|
48
|
+
different type and alignment. :py:const:`np_float16x2`,
|
|
49
|
+
:py:const:`numpy.dtype(numpy.complex64)` and
|
|
50
|
+
:py:const:`numpy.dtype(numpy.complex128)` are the host side dtypes and
|
|
51
|
+
:py:const:`float16x2_type`, :py:const:`float32x2_type` and
|
|
52
|
+
:py:const:`float64x2_type` are the device side types.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
def __init__(self, real_dtype):
|
|
56
|
+
self._real_dtype = real_dtype
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def real_dtype(self):
|
|
60
|
+
return self._real_dtype
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def dtype(self):
|
|
64
|
+
warnings.warn(_alignment_warning_msg, UserWarning, stacklevel=2)
|
|
65
|
+
if self._real_dtype == np.float16:
|
|
66
|
+
return np_float16x2
|
|
67
|
+
elif self._real_dtype == np.float32:
|
|
68
|
+
return np.dtype(np.complex64)
|
|
69
|
+
assert self._real_dtype == np.float64
|
|
70
|
+
return np.dtype(np.complex128)
|
|
71
|
+
|
|
72
|
+
@property
|
|
73
|
+
def _numba_type(self):
|
|
74
|
+
from .vector_types_numba import float16x2_type, float32x2_type, float64x2_type
|
|
75
|
+
|
|
76
|
+
if self.real_dtype == np.float16:
|
|
77
|
+
return float16x2_type
|
|
78
|
+
if self.real_dtype == np.float32:
|
|
79
|
+
return float32x2_type
|
|
80
|
+
assert self.real_dtype == np.float64
|
|
81
|
+
return float64x2_type
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
@deprecated("This is a numba fallback behavior and will be removed in future releases, please use numba types directly")
|
|
85
|
+
def make(self):
|
|
86
|
+
return self._numba_type.make
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
complex32 = Complex(np.float16)
|
|
90
|
+
complex64 = Complex(np.float32)
|
|
91
|
+
complex128 = Complex(np.float64)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class Vector:
|
|
95
|
+
"""
|
|
96
|
+
Vector type that can be used to represent vector numbers both
|
|
97
|
+
on host and device side. Host side representation uses numpy structured
|
|
98
|
+
dtypes to represent the vector components, while device side representation
|
|
99
|
+
uses custom numba types. This difference is necessary because device
|
|
100
|
+
functions expect alignment of the vector types to be the same as the size of
|
|
101
|
+
the vector, which is not the case for numpy structured dtypes.
|
|
102
|
+
:py:const:`np_float16x2` and :py:const:`np_float16x4` are the host side
|
|
103
|
+
dtypes and :py:const:`float16x2_type` and :py:const:`float16x4_type` are the
|
|
104
|
+
device side types.
|
|
105
|
+
"""
|
|
106
|
+
|
|
107
|
+
def __init__(self, real_dtype, size):
|
|
108
|
+
if size not in (2, 4):
|
|
109
|
+
raise ValueError(f"Unsupported vector size {size}, only 2 and 4 are supported")
|
|
110
|
+
if real_dtype != np.float16:
|
|
111
|
+
raise ValueError(f"Unsupported vector real dtype {real_dtype}, only float16 is supported")
|
|
112
|
+
self._real_dtype = real_dtype
|
|
113
|
+
self._size = size
|
|
114
|
+
|
|
115
|
+
@property
|
|
116
|
+
def real_dtype(self):
|
|
117
|
+
return self._real_dtype
|
|
118
|
+
|
|
119
|
+
@property
|
|
120
|
+
def size(self):
|
|
121
|
+
return self._size
|
|
122
|
+
|
|
123
|
+
@property
|
|
124
|
+
def dtype(self):
|
|
125
|
+
warnings.warn(_alignment_warning_msg, UserWarning, stacklevel=2)
|
|
126
|
+
if self._size == 2:
|
|
127
|
+
return np_float16x2
|
|
128
|
+
assert self._size == 4
|
|
129
|
+
return np_float16x4
|
|
130
|
+
|
|
131
|
+
@property
|
|
132
|
+
def _numba_type(self):
|
|
133
|
+
from .vector_types_numba import float16x2_type, float16x4_type
|
|
134
|
+
|
|
135
|
+
if self._size == 2:
|
|
136
|
+
return float16x2_type
|
|
137
|
+
assert self._size == 4
|
|
138
|
+
return float16x4_type
|
|
139
|
+
|
|
140
|
+
@property
|
|
141
|
+
@deprecated("This is a numba fallback behavior and will be removed in future releases, please use numba types directly")
|
|
142
|
+
def make(self):
|
|
143
|
+
return self._numba_type.make
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
half2 = Vector(np.float16, 2)
|
|
147
|
+
half4 = Vector(np.float16, 4)
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"float16x2",
|
|
7
|
+
"float16x4",
|
|
8
|
+
"float32x2",
|
|
9
|
+
"float64x2",
|
|
10
|
+
"float16x2_type",
|
|
11
|
+
"float16x4_type",
|
|
12
|
+
"float32x2_type",
|
|
13
|
+
"float64x2_type",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
import typing
|
|
17
|
+
|
|
18
|
+
from llvmlite import ir
|
|
19
|
+
from numba.core import types
|
|
20
|
+
from numba.core.typeconv import Conversion
|
|
21
|
+
from numba.core.typing.templates import AttributeTemplate
|
|
22
|
+
from numba.cuda.cudadecl import registry as cuda_registry
|
|
23
|
+
from numba.cuda.cudaimpl import lower_attr as cuda_lower_attr
|
|
24
|
+
from numba.cuda.extending import as_numba_type, lower_builtin, lower_cast, overload, register_model, type_callable
|
|
25
|
+
from numba.extending import models
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def make_vector(
|
|
29
|
+
float_bitwidth: int, numba_float_type: types.scalars.Float, llvm_float_type, vector_length: typing.Literal[2, 4]
|
|
30
|
+
):
|
|
31
|
+
assert vector_length == 2 or vector_length == 4
|
|
32
|
+
vector_bitwidth = vector_length * float_bitwidth
|
|
33
|
+
|
|
34
|
+
# User visible types and functions
|
|
35
|
+
class vector:
|
|
36
|
+
def __init__(self, *args):
|
|
37
|
+
pass
|
|
38
|
+
|
|
39
|
+
def create(input):
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
# FE types
|
|
43
|
+
class vectorType(types.Number):
|
|
44
|
+
def __init__(self):
|
|
45
|
+
super().__init__(name=f"vector({numba_float_type.name}x{vector_length})")
|
|
46
|
+
self.dtype = numba_float_type
|
|
47
|
+
self.count = vector_length
|
|
48
|
+
self.bitwidth = vector_bitwidth
|
|
49
|
+
self.make = vector
|
|
50
|
+
|
|
51
|
+
def can_convert_from(self, typingctx, other):
|
|
52
|
+
if vector_length == 2 and isinstance(other, types.Complex):
|
|
53
|
+
if other.bitwidth == vector_bitwidth:
|
|
54
|
+
return Conversion.exact
|
|
55
|
+
elif other.bitwidth < vector_bitwidth:
|
|
56
|
+
return Conversion.safe
|
|
57
|
+
elif other.bitwidth > vector_bitwidth:
|
|
58
|
+
return Conversion.unsafe
|
|
59
|
+
|
|
60
|
+
def can_convert_to(self, typingctx, other):
|
|
61
|
+
if vector_length == 2 and isinstance(other, types.Complex):
|
|
62
|
+
if other.bitwidth == vector_bitwidth:
|
|
63
|
+
return Conversion.exact
|
|
64
|
+
elif other.bitwidth < vector_bitwidth:
|
|
65
|
+
return Conversion.unsafe
|
|
66
|
+
elif other.bitwidth > vector_bitwidth:
|
|
67
|
+
return Conversion.safe
|
|
68
|
+
|
|
69
|
+
def __name__(self):
|
|
70
|
+
return f"vector({numba_float_type.name}x{vector_length})"
|
|
71
|
+
|
|
72
|
+
vector_type = vectorType()
|
|
73
|
+
|
|
74
|
+
types.number_domain = types.number_domain | frozenset([vector_type])
|
|
75
|
+
|
|
76
|
+
# Type inference (Python --> FE type)
|
|
77
|
+
as_numba_type.register(vector, vector_type)
|
|
78
|
+
|
|
79
|
+
# How to build a vectorType from individual elements
|
|
80
|
+
@type_callable(vector)
|
|
81
|
+
def type(context):
|
|
82
|
+
def typer(x, y=None, z=None, w=None):
|
|
83
|
+
if (
|
|
84
|
+
(vector_length == 2 and isinstance(x, types.Complex) and y is None and z is None and w is None)
|
|
85
|
+
or (vector_length == 2 and all(isinstance(v, types.Float) for v in [x, y]) and z is None and w is None)
|
|
86
|
+
or (vector_length == 4 and all(isinstance(v, types.Float) for v in [x, y, z, w]))
|
|
87
|
+
):
|
|
88
|
+
return vector_type
|
|
89
|
+
|
|
90
|
+
return typer
|
|
91
|
+
|
|
92
|
+
# How to represent vectorType in Memory?
|
|
93
|
+
@register_model(vectorType)
|
|
94
|
+
class vectorTypeModel(models.PrimitiveModel):
|
|
95
|
+
def __init__(self, dmm, fe_type):
|
|
96
|
+
be_type = ir.IntType(vector_bitwidth)
|
|
97
|
+
super().__init__(dmm, fe_type, be_type)
|
|
98
|
+
|
|
99
|
+
# How to build a vectorType from individual float values?
|
|
100
|
+
@lower_builtin(vector, *(vector_length * [types.Float])) # FIXME
|
|
101
|
+
def vector_ctor(context, builder, sig, args):
|
|
102
|
+
typ = sig.return_type
|
|
103
|
+
args = list(args)
|
|
104
|
+
assert len(args) == vector_length
|
|
105
|
+
for i in range(vector_length):
|
|
106
|
+
args[i] = context.cast(builder, args[i], sig.args[i], numba_float_type)
|
|
107
|
+
|
|
108
|
+
vt = ir.VectorType(llvm_float_type, vector_length)
|
|
109
|
+
val = ir.Constant(vt, ir.Undefined)
|
|
110
|
+
|
|
111
|
+
for i in range(vector_length):
|
|
112
|
+
val = builder.insert_element(val, args[i], context.get_constant(types.int32, i))
|
|
113
|
+
|
|
114
|
+
return builder.bitcast(val, context.get_value_type(typ))
|
|
115
|
+
|
|
116
|
+
# How to access .x, .y, .z, .w
|
|
117
|
+
@cuda_registry.register_attr
|
|
118
|
+
class complex_attrs(AttributeTemplate):
|
|
119
|
+
key = vectorType
|
|
120
|
+
|
|
121
|
+
def resolve_x(self, mod):
|
|
122
|
+
return numba_float_type
|
|
123
|
+
|
|
124
|
+
def resolve_y(self, mod):
|
|
125
|
+
return numba_float_type
|
|
126
|
+
|
|
127
|
+
def resolve_z(self, mod):
|
|
128
|
+
return numba_float_type
|
|
129
|
+
|
|
130
|
+
def resolve_w(self, mod):
|
|
131
|
+
return numba_float_type
|
|
132
|
+
|
|
133
|
+
def complex_get(context, builder, typ, val, i):
|
|
134
|
+
vt = ir.VectorType(llvm_float_type, vector_length)
|
|
135
|
+
vec = builder.bitcast(val, vt)
|
|
136
|
+
index = context.get_constant(types.int32, i)
|
|
137
|
+
return builder.extract_element(vec, index)
|
|
138
|
+
|
|
139
|
+
# This cannot be done with a loop
|
|
140
|
+
@cuda_lower_attr(vectorType, "x")
|
|
141
|
+
def complex_get_x(context, builder, typ, val):
|
|
142
|
+
return complex_get(context, builder, typ, val, 0)
|
|
143
|
+
|
|
144
|
+
@cuda_lower_attr(vectorType, "y")
|
|
145
|
+
def complex_get_y(context, builder, typ, val):
|
|
146
|
+
return complex_get(context, builder, typ, val, 1)
|
|
147
|
+
|
|
148
|
+
if vector_length == 4:
|
|
149
|
+
|
|
150
|
+
@cuda_lower_attr(vectorType, "z")
|
|
151
|
+
def complex_get_z(context, builder, typ, val):
|
|
152
|
+
return complex_get(context, builder, typ, val, 2)
|
|
153
|
+
|
|
154
|
+
@cuda_lower_attr(vectorType, "w")
|
|
155
|
+
def complex_get_w(context, builder, typ, val):
|
|
156
|
+
return complex_get(context, builder, typ, val, 3)
|
|
157
|
+
|
|
158
|
+
# Conversions from types.Complex
|
|
159
|
+
if vector_length == 2:
|
|
160
|
+
|
|
161
|
+
@overload(create)
|
|
162
|
+
def make_complex(cplx):
|
|
163
|
+
if isinstance(cplx, types.Complex):
|
|
164
|
+
|
|
165
|
+
def impl(cplx):
|
|
166
|
+
return vector(cplx.real, cplx.imag)
|
|
167
|
+
|
|
168
|
+
return impl
|
|
169
|
+
|
|
170
|
+
@lower_cast(types.Complex, vector_type)
|
|
171
|
+
def np_complex_to_complex(context, builder, fromty, toty, val):
|
|
172
|
+
src = context.make_complex(builder, fromty, value=val)
|
|
173
|
+
src_float_ty = fromty.underlying_float
|
|
174
|
+
ctor_sig = toty(src_float_ty, src_float_ty)
|
|
175
|
+
ctor_args = (src.real, src.imag)
|
|
176
|
+
return vector_ctor(context, builder, ctor_sig, ctor_args)
|
|
177
|
+
|
|
178
|
+
@lower_cast(vector_type, types.Complex)
|
|
179
|
+
def complex_to_np_complex(context, builder, fromty, toty, val):
|
|
180
|
+
dst_float_ty = toty.underlying_float
|
|
181
|
+
x = complex_get(context, builder, fromty, val, 0)
|
|
182
|
+
y = complex_get(context, builder, fromty, val, 1)
|
|
183
|
+
x = context.cast(builder, x, numba_float_type, dst_float_ty)
|
|
184
|
+
y = context.cast(builder, y, numba_float_type, dst_float_ty)
|
|
185
|
+
vt = context.get_value_type(toty)
|
|
186
|
+
val = ir.Constant(vt, ir.Undefined)
|
|
187
|
+
val = builder.insert_value(val, x, [0])
|
|
188
|
+
val = builder.insert_value(val, y, [1])
|
|
189
|
+
return val
|
|
190
|
+
|
|
191
|
+
vector.__name__ = f"float{float_bitwidth}x{vector_length}"
|
|
192
|
+
vector.__doc__ = f"""
|
|
193
|
+
float{float_bitwidth}x{vector_length}({"x, y" if vector_length == 2 else "x, y, z, w"})
|
|
194
|
+
|
|
195
|
+
Create a Numba compliant vector object for float{float_bitwidth} with vector length {vector_length}.
|
|
196
|
+
"""
|
|
197
|
+
return vector, vector_type
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
float16x2, float16x2_type = make_vector(16, types.float16, ir.IntType(16), 2)
|
|
201
|
+
float16x4, float16x4_type = make_vector(16, types.float16, ir.IntType(16), 4)
|
|
202
|
+
float32x2, float32x2_type = make_vector(32, types.float32, ir.FloatType(), 2)
|
|
203
|
+
float64x2, float64x2_type = make_vector(64, types.float64, ir.DoubleType(), 2)
|
|
@@ -0,0 +1,205 @@
|
|
|
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
|
+
import sys
|
|
8
|
+
|
|
9
|
+
if sys.platform != "linux":
|
|
10
|
+
raise ImportError("nvmath.distributed is only supported on Linux.")
|
|
11
|
+
|
|
12
|
+
import atexit
|
|
13
|
+
from collections.abc import Sequence
|
|
14
|
+
from dataclasses import dataclass
|
|
15
|
+
from threading import Lock
|
|
16
|
+
from typing import TYPE_CHECKING, Any, Literal
|
|
17
|
+
|
|
18
|
+
import numpy as np
|
|
19
|
+
|
|
20
|
+
try:
|
|
21
|
+
from cuda.core import Device
|
|
22
|
+
except ImportError:
|
|
23
|
+
from cuda.core.experimental import Device
|
|
24
|
+
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
import mpi4py
|
|
27
|
+
|
|
28
|
+
from nvmath.distributed import fft, linalg, reshape # noqa: E402
|
|
29
|
+
from nvmath.internal.utils import device_ctx
|
|
30
|
+
|
|
31
|
+
from . import distribution
|
|
32
|
+
from ._internal import nvshmem
|
|
33
|
+
from ._utils import allocate_symmetric_memory, free_symmetric_memory
|
|
34
|
+
from .process_group import MPIProcessGroup, ProcessGroup, TorchProcessGroup
|
|
35
|
+
|
|
36
|
+
__all__ = [
|
|
37
|
+
"initialize",
|
|
38
|
+
"finalize",
|
|
39
|
+
"get_context",
|
|
40
|
+
"ProcessGroup",
|
|
41
|
+
"MPIProcessGroup",
|
|
42
|
+
"TorchProcessGroup",
|
|
43
|
+
"allocate_symmetric_memory",
|
|
44
|
+
"free_symmetric_memory",
|
|
45
|
+
"distribution",
|
|
46
|
+
"fft",
|
|
47
|
+
"linalg",
|
|
48
|
+
"reshape",
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
_initialize_mutex = Lock()
|
|
52
|
+
_atexit_registered = False
|
|
53
|
+
_ctx = None
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@dataclass(frozen=True)
|
|
57
|
+
class DistributedContext:
|
|
58
|
+
"""
|
|
59
|
+
Context of initialized ``nvmath.distributed`` runtime.
|
|
60
|
+
|
|
61
|
+
Attributes:
|
|
62
|
+
device_id: CUDA device ID associated with the distributed runtime
|
|
63
|
+
on this process.
|
|
64
|
+
|
|
65
|
+
process_group: ``nvmath.distributed`` participating processes.
|
|
66
|
+
|
|
67
|
+
nvshmem_available: True if NVSHMEM backend was selected at initialization.
|
|
68
|
+
|
|
69
|
+
nccl_comm: nccl4py communicator if NCCL backend was selected at
|
|
70
|
+
initialization, None otherwise.
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
device_id: int
|
|
74
|
+
process_group: ProcessGroup
|
|
75
|
+
nvshmem_available: bool
|
|
76
|
+
nccl_comm: Any | None
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def initialize(
|
|
80
|
+
device_id: int,
|
|
81
|
+
process_group: ProcessGroup | mpi4py.MPI.Comm,
|
|
82
|
+
backends: Sequence[Literal["nvshmem", "nccl"]],
|
|
83
|
+
) -> None:
|
|
84
|
+
"""Initialize ``nvmath.distributed`` runtime. This is required before any distributed
|
|
85
|
+
operations can be performed. **Note that this is a collective operation and must be
|
|
86
|
+
called by all processes.**
|
|
87
|
+
|
|
88
|
+
If the runtime is already initialized this function will raise an error. If you need
|
|
89
|
+
to reinitialize the runtime (for example with different backends) you have to finalize
|
|
90
|
+
it first.
|
|
91
|
+
|
|
92
|
+
Note: NCCL doesn't allow assigning more than one process to the same GPU.
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
device_id: CUDA device ID to associate with the ``nvmath.distributed`` runtime
|
|
96
|
+
on this process.
|
|
97
|
+
|
|
98
|
+
process_group: ProcessGroup (or mpi4py communicator) specifying the participating
|
|
99
|
+
processes. This is used for setup and not for communication during compute.
|
|
100
|
+
|
|
101
|
+
backends: Communication backends to use in distributed computations. Valid values
|
|
102
|
+
are "nvshmem" and "nccl". Note that specific libraries (cuFFTMp, cuBLASMp, ...)
|
|
103
|
+
have specific required backends.
|
|
104
|
+
"""
|
|
105
|
+
if not isinstance(device_id, int):
|
|
106
|
+
raise TypeError(
|
|
107
|
+
"The device ID used to initialize the nvmath.distributed module "
|
|
108
|
+
f"must be an integer. The provided device ID is {device_id}."
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
valid_backends = ("nvshmem", "nccl")
|
|
112
|
+
for backend in backends:
|
|
113
|
+
if backend not in valid_backends:
|
|
114
|
+
raise ValueError(f"backend must be one of {valid_backends}, got {backend}")
|
|
115
|
+
|
|
116
|
+
if len(backends) == 0:
|
|
117
|
+
raise ValueError(f"Need to specify at least one of {valid_backends} communication backends")
|
|
118
|
+
|
|
119
|
+
if process_group is None:
|
|
120
|
+
raise ValueError("process_group cannot be None")
|
|
121
|
+
|
|
122
|
+
with _initialize_mutex:
|
|
123
|
+
global _atexit_registered, _ctx
|
|
124
|
+
|
|
125
|
+
if _ctx is not None:
|
|
126
|
+
raise RuntimeError("nvmath.distributed has already been initialized")
|
|
127
|
+
|
|
128
|
+
if not _atexit_registered:
|
|
129
|
+
atexit.register(finalize)
|
|
130
|
+
_atexit_registered = True
|
|
131
|
+
|
|
132
|
+
if not isinstance(process_group, ProcessGroup):
|
|
133
|
+
valid_process_group = False
|
|
134
|
+
if "mpi4py" in sys.modules:
|
|
135
|
+
import mpi4py.MPI
|
|
136
|
+
|
|
137
|
+
if isinstance(process_group, mpi4py.MPI.Comm):
|
|
138
|
+
process_group = MPIProcessGroup(process_group)
|
|
139
|
+
valid_process_group = True
|
|
140
|
+
if not valid_process_group:
|
|
141
|
+
raise TypeError(
|
|
142
|
+
f"Unrecognized process group type ({process_group}). "
|
|
143
|
+
"Need nvmath.distributed.ProcessGroup or mpi4py communicator."
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
assert isinstance(process_group, ProcessGroup) # for type-checker
|
|
147
|
+
rank = process_group.rank
|
|
148
|
+
nranks = process_group.nranks
|
|
149
|
+
|
|
150
|
+
# Set the device for NVSHMEM and NCCL initialization, but also need to make sure
|
|
151
|
+
# that a CUDA context has been created. We can't rely on `device_ctx` to do it
|
|
152
|
+
# since it's not guaranteed to make a runtime API call.
|
|
153
|
+
old_device = Device()
|
|
154
|
+
device = Device(device_id)
|
|
155
|
+
device.set_current()
|
|
156
|
+
|
|
157
|
+
try:
|
|
158
|
+
nvshmem_available = False
|
|
159
|
+
if "nvshmem" in backends:
|
|
160
|
+
nvshmem.initialize(device_id, process_group)
|
|
161
|
+
nvshmem_available = True
|
|
162
|
+
|
|
163
|
+
nccl_comm = None
|
|
164
|
+
if "nccl" in backends:
|
|
165
|
+
# Don't want to import this at the global scope yet because
|
|
166
|
+
# `import nccl.core` imports cupy and torch (with nccl4py 0.1.1)
|
|
167
|
+
import nccl.core as nccl # type: ignore
|
|
168
|
+
|
|
169
|
+
# Create NCCL communicator.
|
|
170
|
+
unique_id = nccl.get_unique_id()
|
|
171
|
+
process_group.broadcast_buffer(unique_id.as_ndarray.view(np.int8), root=0)
|
|
172
|
+
nccl_comm = nccl.Communicator.init(nranks=nranks, rank=rank, unique_id=unique_id)
|
|
173
|
+
|
|
174
|
+
_ctx = DistributedContext(
|
|
175
|
+
device_id=device_id, process_group=process_group, nvshmem_available=nvshmem_available, nccl_comm=nccl_comm
|
|
176
|
+
)
|
|
177
|
+
finally:
|
|
178
|
+
old_device.set_current()
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def finalize() -> None:
|
|
182
|
+
"""Finalize ``nvmath.distributed`` runtime (this is called automatically at exit
|
|
183
|
+
if the runtime is initialized). **Note that this is a collective operation and
|
|
184
|
+
must be called by all processes.**"""
|
|
185
|
+
global _ctx
|
|
186
|
+
with _initialize_mutex:
|
|
187
|
+
if _ctx is None:
|
|
188
|
+
return
|
|
189
|
+
|
|
190
|
+
linalg.advanced.matmulmod._grid_cache.clear()
|
|
191
|
+
|
|
192
|
+
if _ctx.nccl_comm is not None:
|
|
193
|
+
with device_ctx(_ctx.device_id):
|
|
194
|
+
_ctx.nccl_comm.finalize()
|
|
195
|
+
_ctx.nccl_comm.destroy()
|
|
196
|
+
|
|
197
|
+
if _ctx.nvshmem_available:
|
|
198
|
+
nvshmem.finalize(_ctx.device_id)
|
|
199
|
+
|
|
200
|
+
_ctx = None
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def get_context() -> DistributedContext | None:
|
|
204
|
+
"""Return the distributed runtime's context or None if not initialized."""
|
|
205
|
+
return _ctx
|
|
File without changes
|