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.
- 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 +130 -0
- nvmath/_internal/threadsafe.py +106 -0
- nvmath/_internal/utils.py +43 -0
- nvmath/_internal/workspace.py +490 -0
- nvmath/_utils.py +147 -0
- nvmath/bindings/__init__.py +60 -0
- nvmath/bindings/_internal/__init__.pxd +0 -0
- nvmath/bindings/_internal/__init__.py +0 -0
- nvmath/bindings/_internal/common_types.pxd +31 -0
- nvmath/bindings/_internal/cublas.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cublas.pxd +530 -0
- nvmath/bindings/_internal/cublasLt.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cublasLt.pxd +59 -0
- nvmath/bindings/_internal/cublasMp.pxd +52 -0
- nvmath/bindings/_internal/cudss.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cudss.pxd +54 -0
- nvmath/bindings/_internal/cufft.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cufft.pxd +70 -0
- nvmath/bindings/_internal/cufftMp.pxd +77 -0
- nvmath/bindings/_internal/curand.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/curand.pxd +42 -0
- nvmath/bindings/_internal/cusolver.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cusolver.pxd +15 -0
- nvmath/bindings/_internal/cusolverDn.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cusolverDn.pxd +406 -0
- nvmath/bindings/_internal/cusolverMp.pxd +71 -0
- nvmath/bindings/_internal/cusolverSp.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cusolverSp.pxd +75 -0
- nvmath/bindings/_internal/cusparse.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cusparse.pxd +471 -0
- nvmath/bindings/_internal/cusparseLt.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cusparseLt.pxd +48 -0
- nvmath/bindings/_internal/cutensor.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cutensor.pxd +58 -0
- nvmath/bindings/_internal/mathdx.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/mathdx.pxd +116 -0
- nvmath/bindings/_internal/nvshmem.pxd +29 -0
- nvmath/bindings/_internal/utils.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/utils.pxd +174 -0
- nvmath/bindings/_internal/utils.pyi +10 -0
- nvmath/bindings/cublas.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cublas.pxd +558 -0
- nvmath/bindings/cublas.pyi +812 -0
- nvmath/bindings/cublasLt.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cublasLt.pxd +109 -0
- nvmath/bindings/cublasLt.pyi +1461 -0
- nvmath/bindings/cublasMp.pxd +85 -0
- nvmath/bindings/cublasMp.pyi +267 -0
- nvmath/bindings/cudss.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cudss.pxd +98 -0
- nvmath/bindings/cudss.pyi +443 -0
- nvmath/bindings/cufft.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cufft.pxd +118 -0
- nvmath/bindings/cufft.pyi +301 -0
- nvmath/bindings/cufftMp.pxd +124 -0
- nvmath/bindings/cufftMp.pyi +326 -0
- nvmath/bindings/curand.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/curand.pxd +71 -0
- nvmath/bindings/curand.pyi +189 -0
- nvmath/bindings/cusolver.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cusolver.pxd +62 -0
- nvmath/bindings/cusolver.pyi +320 -0
- nvmath/bindings/cusolverDn.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cusolverDn.pxd +430 -0
- nvmath/bindings/cusolverDn.pyi +422 -0
- nvmath/bindings/cusolverMp.pxd +98 -0
- nvmath/bindings/cusolverMp.pyi +114 -0
- nvmath/bindings/cusolverSp.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cusolverSp.pxd +95 -0
- nvmath/bindings/cusolverSp.pyi +70 -0
- nvmath/bindings/cusparse.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cusparse.pxd +546 -0
- nvmath/bindings/cusparse.pyi +1017 -0
- nvmath/bindings/cusparseLt.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cusparseLt.pxd +99 -0
- nvmath/bindings/cusparseLt.pyi +252 -0
- nvmath/bindings/cutensor.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cutensor.pxd +98 -0
- nvmath/bindings/cutensor.pyi +324 -0
- nvmath/bindings/cycublas.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cycublas.pxd +664 -0
- nvmath/bindings/cycublasLt.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cycublasLt.pxd +1045 -0
- nvmath/bindings/cycublasMp.pxd +171 -0
- nvmath/bindings/cycudss.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cycudss.pxd +277 -0
- nvmath/bindings/cycufft.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cycufft.pxd +333 -0
- nvmath/bindings/cycufftMp.pxd +342 -0
- nvmath/bindings/cycurand.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cycurand.pxd +141 -0
- nvmath/bindings/cycusolver.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cycusolver.pxd +137 -0
- nvmath/bindings/cycusolverDn.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cycusolverDn.pxd +443 -0
- nvmath/bindings/cycusolverMp.pxd +107 -0
- nvmath/bindings/cycusolverSp.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cycusolverSp.pxd +93 -0
- nvmath/bindings/cycusparse.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cycusparse.pxd +679 -0
- nvmath/bindings/cycusparseLt.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cycusparseLt.pxd +135 -0
- nvmath/bindings/cycutensor.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cycutensor.pxd +189 -0
- nvmath/bindings/cymathdx.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/cymathdx.pxd +552 -0
- nvmath/bindings/cynvshmem.pxd +118 -0
- nvmath/bindings/mathdx.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/mathdx.pxd +182 -0
- nvmath/bindings/mathdx.pyi +1562 -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.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/nvpl/_internal/blas.pxd +237 -0
- nvmath/bindings/nvpl/_internal/fft.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/nvpl/_internal/fft.pxd +36 -0
- nvmath/bindings/nvpl/blas.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/nvpl/blas.pxd +131 -0
- nvmath/bindings/nvpl/blas.pyi +168 -0
- nvmath/bindings/nvpl/cyblas.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/nvpl/cyblas.pxd +280 -0
- nvmath/bindings/nvpl/cyfft.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/nvpl/cyfft.pxd +93 -0
- nvmath/bindings/nvpl/fft.cp314t-win_amd64.pyd +0 -0
- nvmath/bindings/nvpl/fft.pxd +100 -0
- nvmath/bindings/nvpl/fft.pyi +168 -0
- nvmath/bindings/nvshmem.pxd +54 -0
- nvmath/bindings/nvshmem.pyi +191 -0
- nvmath/device/__init__.py +38 -0
- nvmath/device/_deprecated.py +33 -0
- nvmath/device/common.py +315 -0
- nvmath/device/common_backend.py +131 -0
- nvmath/device/common_cuda.py +201 -0
- nvmath/device/common_numba.py +300 -0
- nvmath/device/common_numba_cuda_mlir.py +202 -0
- nvmath/device/common_opaque_tensor.py +201 -0
- nvmath/device/cublasdx.py +1606 -0
- nvmath/device/cublasdx_backend.py +860 -0
- nvmath/device/cublasdx_numba.py +1534 -0
- nvmath/device/cublasdx_numba_cuda_mlir.py +208 -0
- nvmath/device/cufftdx.py +373 -0
- nvmath/device/cufftdx_backend.py +220 -0
- nvmath/device/cufftdx_numba.py +140 -0
- nvmath/device/cufftdx_numba_cuda_mlir.py +79 -0
- nvmath/device/curand_kernel.py +9147 -0
- nvmath/device/cusolverdx.py +2708 -0
- nvmath/device/cusolverdx_backend.py +440 -0
- nvmath/device/cusolverdx_numba.py +567 -0
- nvmath/device/cusolverdx_numba_cuda_mlir.py +604 -0
- nvmath/device/cusolverdx_overload_backend.py +1029 -0
- nvmath/device/llvm_array.py +29 -0
- nvmath/device/random.py +441 -0
- nvmath/device/random_helpers.py +23 -0
- nvmath/device/random_states.py +187 -0
- nvmath/device/types.py +138 -0
- nvmath/device/vector_types_numba.py +259 -0
- nvmath/distributed/__init__.py +200 -0
- nvmath/distributed/_internal/__init__.py +0 -0
- nvmath/distributed/_internal/nccl.py +86 -0
- nvmath/distributed/_internal/nvshmem.py +307 -0
- nvmath/distributed/_internal/symmetric_memory.py +35 -0
- nvmath/distributed/_internal/tensor_ifc.py +70 -0
- nvmath/distributed/_internal/tensor_ifc_cupy.py +68 -0
- nvmath/distributed/_internal/tensor_ifc_host_device.py +172 -0
- nvmath/distributed/_internal/tensor_ifc_numpy.py +46 -0
- nvmath/distributed/_internal/tensor_ifc_torch.py +162 -0
- nvmath/distributed/_internal/tensor_wrapper.py +81 -0
- nvmath/distributed/_utils.py +167 -0
- nvmath/distributed/distribution/__init__.py +30 -0
- nvmath/distributed/distribution/_configuration.py +39 -0
- nvmath/distributed/distribution/distributions.py +1024 -0
- nvmath/distributed/distribution/redistribute.py +1284 -0
- nvmath/distributed/fft/__init__.py +7 -0
- nvmath/distributed/fft/_configuration.py +82 -0
- nvmath/distributed/fft/fft.py +2742 -0
- nvmath/distributed/linalg/__init__.py +22 -0
- nvmath/distributed/linalg/_internal/__init__.py +3 -0
- nvmath/distributed/linalg/_internal/epilog_protocol.py +586 -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 +171 -0
- nvmath/distributed/linalg/advanced/matmulmod.py +3573 -0
- nvmath/distributed/linalg/generic/__init__.py +8 -0
- nvmath/distributed/linalg/generic/_caching.py +66 -0
- nvmath/distributed/linalg/generic/_configuration.py +61 -0
- nvmath/distributed/linalg/generic/_factorization.py +172 -0
- nvmath/distributed/linalg/generic/_initialization.py +966 -0
- nvmath/distributed/linalg/generic/_problem_spec.py +511 -0
- nvmath/distributed/linalg/generic/solvermod.py +1368 -0
- nvmath/distributed/process_group.py +408 -0
- nvmath/fft/__init__.py +7 -0
- nvmath/fft/_configuration.py +189 -0
- nvmath/fft/_exec_utils.py +82 -0
- nvmath/fft/_helpers.py +237 -0
- nvmath/fft/fft.py +3122 -0
- nvmath/internal/__init__.pxd +3 -0
- nvmath/internal/__init__.py +10 -0
- nvmath/internal/_bindings.cp314t-win_amd64.pyd +0 -0
- nvmath/internal/_bindings.pxd +18 -0
- nvmath/internal/_device_utils.py +45 -0
- nvmath/internal/_layout/__init__.pxd +3 -0
- nvmath/internal/_layout/__init__.py +7 -0
- nvmath/internal/_layout/_layout.cp314t-win_amd64.pyd +0 -0
- nvmath/internal/_layout/_layout.pxd +1303 -0
- nvmath/internal/_layout/_layout.pyi +1145 -0
- nvmath/internal/enum_utils.py +142 -0
- nvmath/internal/formatters.py +87 -0
- nvmath/internal/mem_limit.py +51 -0
- nvmath/internal/memory.cp314t-win_amd64.pyd +0 -0
- nvmath/internal/memory.pxd +13 -0
- nvmath/internal/memory.pyi +50 -0
- nvmath/internal/ndbuffer/__init__.pxd +3 -0
- nvmath/internal/ndbuffer/__init__.py +9 -0
- nvmath/internal/ndbuffer/_copy_kernel.cp314t-win_amd64.pyd +0 -0
- nvmath/internal/ndbuffer/_copy_kernel.pxd +10 -0
- nvmath/internal/ndbuffer/_jit.cp314t-win_amd64.pyd +0 -0
- nvmath/internal/ndbuffer/_jit.pxd +7 -0
- nvmath/internal/ndbuffer/_ndbuffer.cp314t-win_amd64.pyd +0 -0
- nvmath/internal/ndbuffer/_ndbuffer.pxd +40 -0
- nvmath/internal/ndbuffer/_ndbuffer.pyi +463 -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 +242 -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/package_ifc.py +168 -0
- nvmath/internal/package_ifc_cuda.py +57 -0
- nvmath/internal/package_ifc_cupy.py +67 -0
- nvmath/internal/package_ifc_torch.py +69 -0
- nvmath/internal/package_wrapper.py +14 -0
- nvmath/internal/tensor_ifc.py +179 -0
- nvmath/internal/tensor_ifc_cupy.py +234 -0
- nvmath/internal/tensor_ifc_ndbuffer.py +147 -0
- nvmath/internal/tensor_ifc_numpy.py +184 -0
- nvmath/internal/tensor_ifc_torch.py +178 -0
- nvmath/internal/tensor_wrapper.py +160 -0
- nvmath/internal/typemaps.py +113 -0
- nvmath/internal/utils.py +805 -0
- nvmath/linalg/__init__.py +56 -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 +234 -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/solver_utils.py +432 -0
- nvmath/linalg/_internal/typemaps.py +144 -0
- nvmath/linalg/_internal/utils.py +157 -0
- nvmath/linalg/advanced/__init__.py +8 -0
- nvmath/linalg/advanced/_algorithmmod.py +170 -0
- nvmath/linalg/advanced/_configuration.py +351 -0
- nvmath/linalg/advanced/helpers/__init__.py +5 -0
- nvmath/linalg/advanced/helpers/matmul.py +1316 -0
- nvmath/linalg/advanced/matmulmod.py +3734 -0
- nvmath/linalg/generic/__init__.py +53 -0
- nvmath/linalg/generic/_configuration/__init__.py +39 -0
- nvmath/linalg/generic/_configuration/layout.py +263 -0
- nvmath/linalg/generic/_configuration/match.py +734 -0
- nvmath/linalg/generic/_configuration/qualifiers.py +493 -0
- nvmath/linalg/generic/_configuration/solver_configuration.py +59 -0
- nvmath/linalg/generic/_configuration/wrap.py +217 -0
- nvmath/linalg/generic/_dtype.py +15 -0
- nvmath/linalg/generic/matmulmod.py +2094 -0
- nvmath/linalg/generic/solvermod.py +1301 -0
- nvmath/memory.py +279 -0
- nvmath/sparse/__init__.py +38 -0
- nvmath/sparse/_internal/__init__.py +21 -0
- nvmath/sparse/_internal/common_utils.py +147 -0
- nvmath/sparse/_internal/cudss_config_ifc.py +702 -0
- nvmath/sparse/_internal/cudss_data_ifc.py +399 -0
- nvmath/sparse/_internal/cudss_utils.py +506 -0
- nvmath/sparse/_internal/cusparse_utils.py +382 -0
- nvmath/sparse/_internal/sparse_bsc_ifc.py +303 -0
- nvmath/sparse/_internal/sparse_bsr_ifc.py +305 -0
- nvmath/sparse/_internal/sparse_coo_ifc.py +256 -0
- nvmath/sparse/_internal/sparse_csc_ifc.py +268 -0
- nvmath/sparse/_internal/sparse_csr_ifc.py +288 -0
- nvmath/sparse/_internal/sparse_dia_ifc.py +242 -0
- nvmath/sparse/_internal/sparse_format_helpers.py +601 -0
- nvmath/sparse/_internal/sparse_tensor_ifc.py +133 -0
- nvmath/sparse/_internal/sparse_ust_ifc.py +141 -0
- nvmath/sparse/_internal/utils.py +56 -0
- nvmath/sparse/advanced/__init__.py +7 -0
- nvmath/sparse/advanced/_configuration.py +227 -0
- nvmath/sparse/advanced/direct_solver.py +2069 -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 +2353 -0
- nvmath/sparse/ust/__init__.py +7 -0
- nvmath/sparse/ust/_converters.py +422 -0
- nvmath/sparse/ust/_cpp.py +28 -0
- nvmath/sparse/ust/_drawer.py +565 -0
- nvmath/sparse/ust/_emitter.py +1033 -0
- nvmath/sparse/ust/_jit.py +188 -0
- nvmath/sparse/ust/_kernel.py +282 -0
- nvmath/sparse/ust/_utils.py +149 -0
- nvmath/sparse/ust/interfaces/__init__.py +0 -0
- nvmath/sparse/ust/interfaces/torch_interface.py +476 -0
- nvmath/sparse/ust/tensor.py +1016 -0
- nvmath/sparse/ust/tensor_format.py +957 -0
- nvmath/tensor/__init__.py +6 -0
- nvmath/tensor/_configuration.py +120 -0
- nvmath/tensor/_internal/__init__.py +3 -0
- nvmath/tensor/_internal/cutensor_config_ifc.py +279 -0
- nvmath/tensor/_internal/cutensor_utils.py +230 -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 +1900 -0
- nvmath_python-1.0.0.dist-info/METADATA +134 -0
- nvmath_python-1.0.0.dist-info/RECORD +332 -0
- nvmath_python-1.0.0.dist-info/WHEEL +5 -0
- nvmath_python-1.0.0.dist-info/licenses/LICENSE +177 -0
- nvmath_python-1.0.0.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
This module defines a JIT runtime for the universal sparse tensor (UST).
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
__all__ = []
|
|
10
|
+
|
|
11
|
+
import re
|
|
12
|
+
from collections.abc import Sequence
|
|
13
|
+
|
|
14
|
+
from cuda.core import (
|
|
15
|
+
LaunchConfig,
|
|
16
|
+
Linker,
|
|
17
|
+
LinkerOptions,
|
|
18
|
+
ObjectCode,
|
|
19
|
+
Program,
|
|
20
|
+
ProgramOptions,
|
|
21
|
+
launch,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
from nvmath.internal import utils
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _check_numba_available():
|
|
28
|
+
try:
|
|
29
|
+
import numba # noqa: F401
|
|
30
|
+
except ModuleNotFoundError as e:
|
|
31
|
+
raise RuntimeError("Numba is required to compile user-defined Python functions provided to the UST APIs.") from e
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def compile_python_function(
|
|
35
|
+
function,
|
|
36
|
+
function_name,
|
|
37
|
+
signature,
|
|
38
|
+
*,
|
|
39
|
+
representation="ltoir",
|
|
40
|
+
compute_capability=None,
|
|
41
|
+
):
|
|
42
|
+
"""
|
|
43
|
+
Compile the Python function to an intermediate representation using Numba.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
function: The Python function to compile.
|
|
47
|
+
function_name: The symbol to use for the function name.
|
|
48
|
+
signature: the function signature as a sequence (return_type, *parameter_types). The
|
|
49
|
+
type names should correspond to the C type names recognized by Numba.
|
|
50
|
+
representation: the intermediate representation ("ltoir", "ptx").
|
|
51
|
+
compute_capability: the device compute capability. If not specified, the
|
|
52
|
+
current devices CC will be used.
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
The compiled IR.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
_check_numba_available()
|
|
59
|
+
|
|
60
|
+
import numba
|
|
61
|
+
import numba.cuda
|
|
62
|
+
|
|
63
|
+
user_return_type, *user_arg_types = signature
|
|
64
|
+
|
|
65
|
+
return_type = getattr(numba.cuda.types.types, user_return_type)
|
|
66
|
+
|
|
67
|
+
arg_types = []
|
|
68
|
+
for arg_type in user_arg_types:
|
|
69
|
+
m = re.match(r"(\w+)((\[:\])|( *(\*)))?", arg_type)
|
|
70
|
+
assert m is not None, "Internal error."
|
|
71
|
+
t = getattr(numba.cuda.types.types, m.group(1))
|
|
72
|
+
if m.group(2) is not None:
|
|
73
|
+
if m.group(3) == "[:]":
|
|
74
|
+
t = t[:]
|
|
75
|
+
elif m.group(5) == "*":
|
|
76
|
+
t = numba.cuda.types.types.voidptr
|
|
77
|
+
else:
|
|
78
|
+
raise AssertionError("Internal error.")
|
|
79
|
+
arg_types.append(t)
|
|
80
|
+
|
|
81
|
+
signature = numba.core.typing.signature(return_type, *arg_types)
|
|
82
|
+
|
|
83
|
+
return numba.cuda.compile(
|
|
84
|
+
function,
|
|
85
|
+
signature,
|
|
86
|
+
debug=None,
|
|
87
|
+
lineinfo=False,
|
|
88
|
+
device=True,
|
|
89
|
+
fastmath=False,
|
|
90
|
+
cc=compute_capability,
|
|
91
|
+
opt=True,
|
|
92
|
+
abi="c",
|
|
93
|
+
abi_info={"abi_name": function_name},
|
|
94
|
+
output=representation,
|
|
95
|
+
forceinline=False,
|
|
96
|
+
launch_bounds=None,
|
|
97
|
+
)[0]
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def compile_cpp_and_link(
|
|
101
|
+
*,
|
|
102
|
+
src_code=None,
|
|
103
|
+
object_code=None,
|
|
104
|
+
function_name,
|
|
105
|
+
compiler_options=None,
|
|
106
|
+
linker_options=None,
|
|
107
|
+
intermediate_type="ltoir",
|
|
108
|
+
target_type="cubin",
|
|
109
|
+
):
|
|
110
|
+
"""
|
|
111
|
+
Compile the source code (if provided) and link with the intermediate code (if provided).
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
src_code: A string or sequence of strings containing the C++ source code.
|
|
115
|
+
object_code: A byte-string or sequence of byte-string objects to be linked
|
|
116
|
+
along with the source code.
|
|
117
|
+
function_name: symbol name to use for the compiled and linked function.
|
|
118
|
+
compiler_options: the compiler options to use as a
|
|
119
|
+
:class:`cuda.core.ProgramOptions` object. Alternatively, a dictionary containing
|
|
120
|
+
the options can be provided.
|
|
121
|
+
linker_options: the linker options to use as a
|
|
122
|
+
:class:`cuda.core.LinkerOptions` object. Alternatively, a dictionary containing
|
|
123
|
+
the options can be provided.
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
The linked kernel.
|
|
127
|
+
"""
|
|
128
|
+
|
|
129
|
+
assert not (src_code is None and object_code is None), "Internal error."
|
|
130
|
+
|
|
131
|
+
compiler_options = utils.check_or_create_options(ProgramOptions, compiler_options, "Compiler Options")
|
|
132
|
+
linker_options = utils.check_or_create_options(LinkerOptions, linker_options, "Linker Options")
|
|
133
|
+
|
|
134
|
+
if isinstance(src_code, str):
|
|
135
|
+
src_code = [src_code]
|
|
136
|
+
else:
|
|
137
|
+
if src_code is not None and not isinstance(src_code, Sequence):
|
|
138
|
+
raise TypeError("The source code type 'type(src_code)' must be a string or a sequence of strings.")
|
|
139
|
+
|
|
140
|
+
# Handle the case where no source code is provided.
|
|
141
|
+
if src_code is None:
|
|
142
|
+
src_code = []
|
|
143
|
+
|
|
144
|
+
# Compile source code to LTO-IR.
|
|
145
|
+
compiled_code = [Program(s, "c++", options=compiler_options).compile(intermediate_type) for s in src_code]
|
|
146
|
+
|
|
147
|
+
if isinstance(object_code, bytes):
|
|
148
|
+
object_code = [object_code]
|
|
149
|
+
else:
|
|
150
|
+
if object_code is not None and not isinstance(object_code, Sequence):
|
|
151
|
+
raise TypeError(
|
|
152
|
+
"The intermediate code type 'type(object_code)' must be a byte-string or a sequence of byte-strings."
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
assert intermediate_type == "ltoir", "Internal error."
|
|
156
|
+
|
|
157
|
+
# Handle the case where no object code is provided.
|
|
158
|
+
if object_code is None:
|
|
159
|
+
object_code = []
|
|
160
|
+
|
|
161
|
+
object_code = [ObjectCode.from_ltoir(o) for o in object_code]
|
|
162
|
+
|
|
163
|
+
# Link all objects together.
|
|
164
|
+
linker = Linker(*(compiled_code + object_code), options=linker_options)
|
|
165
|
+
linked_code = linker.link(target_type=target_type)
|
|
166
|
+
|
|
167
|
+
# Extract kernel entry by function name.
|
|
168
|
+
return linked_code.get_kernel(function_name)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def launch_kernel(kernel, grid, block, params, *, device_id, stream_holder, blocking=True):
|
|
172
|
+
"""
|
|
173
|
+
Launch the kernel on the specified device and stream.
|
|
174
|
+
|
|
175
|
+
Args:
|
|
176
|
+
kernel: the CUDA kernel to launch.
|
|
177
|
+
grid, block: the CUDA grid and block dimensions for launch.
|
|
178
|
+
params: the kernel arguments as a sequence or None.
|
|
179
|
+
device_id: the device ID on which to launch the kernel.
|
|
180
|
+
stream_holder: a `nvmath.internal.utils.StreamHolder` object for the stream to use.
|
|
181
|
+
blocking: if True, the call blocks.
|
|
182
|
+
"""
|
|
183
|
+
config = LaunchConfig(grid=grid, block=block)
|
|
184
|
+
with utils.device_ctx(device_id):
|
|
185
|
+
launch(stream_holder.obj, config, kernel, *params)
|
|
186
|
+
# TODO: make this non-blocking by default.
|
|
187
|
+
if blocking:
|
|
188
|
+
stream_holder.obj.sync()
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
# Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
This module defines a kernel generator for various sparse tensor operations.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
__all__ = []
|
|
10
|
+
|
|
11
|
+
import time
|
|
12
|
+
|
|
13
|
+
from cuda import pathfinder
|
|
14
|
+
|
|
15
|
+
from ._cpp import prolog_a_impl, prolog_b_impl, prolog_decl
|
|
16
|
+
from ._emitter import Index, emit_matmul_kernel
|
|
17
|
+
from ._jit import compile_cpp_and_link
|
|
18
|
+
from ._utils import Cache, type_str
|
|
19
|
+
|
|
20
|
+
# Maps matmul(a,b,c) to pre-defined kernel source code.
|
|
21
|
+
_tensor_matmul_kernels = {
|
|
22
|
+
# (format_a, format_b, format_c, transpose_a, transpose_b)
|
|
23
|
+
("DIAI", "DenseVector", "DenseVector", False, False): """
|
|
24
|
+
extern "C" __global__ void matmul_kernel(
|
|
25
|
+
const POS* __restrict__ pos0,
|
|
26
|
+
const CRD* __restrict__ diags,
|
|
27
|
+
const VAL* __restrict__ A,
|
|
28
|
+
const VAL *__restrict__ B,
|
|
29
|
+
VAL *__restrict__ C,
|
|
30
|
+
unsigned long m,
|
|
31
|
+
unsigned long n,
|
|
32
|
+
unsigned long l0,
|
|
33
|
+
unsigned long l1) {
|
|
34
|
+
const unsigned long tidx = threadIdx.x;
|
|
35
|
+
const unsigned long bidx = blockIdx.x;
|
|
36
|
+
const unsigned long i = bidx * blockDim.x + tidx;
|
|
37
|
+
if (i < m) {
|
|
38
|
+
CTP acc = 0;
|
|
39
|
+
const POS numDiags = pos0[1];
|
|
40
|
+
for (unsigned long d = 0, di = i; d < numDiags; d++, di += m) {
|
|
41
|
+
const long j = i + diags[d];
|
|
42
|
+
if (0 <= j && j < n) {
|
|
43
|
+
acc += prolog_a(static_cast<CTP>(A[di])) *
|
|
44
|
+
prolog_b(static_cast<CTP>(B[j]));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
C[i] += static_cast<VAL>(acc);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
""",
|
|
51
|
+
("DIAJ", "DenseVector", "DenseVector", False, False): """
|
|
52
|
+
extern "C" __global__ void matmul_kernel(
|
|
53
|
+
const POS* __restrict__ pos0,
|
|
54
|
+
const CRD* __restrict__ diags,
|
|
55
|
+
const VAL* __restrict__ A,
|
|
56
|
+
const VAL *__restrict__ B,
|
|
57
|
+
VAL *__restrict__ C,
|
|
58
|
+
unsigned long m,
|
|
59
|
+
unsigned long n,
|
|
60
|
+
unsigned long l0,
|
|
61
|
+
unsigned long l1) {
|
|
62
|
+
const unsigned long tidx = threadIdx.x;
|
|
63
|
+
const unsigned long bidx = blockIdx.x;
|
|
64
|
+
const unsigned long i = bidx * blockDim.x + tidx;
|
|
65
|
+
if (i < m) {
|
|
66
|
+
CTP acc = 0;
|
|
67
|
+
const POS numDiags = pos0[1];
|
|
68
|
+
for (unsigned long d = 0, di = 0; d < numDiags; d++, di += n) {
|
|
69
|
+
const long j = i + diags[d];
|
|
70
|
+
if (0 <= j && j < n) {
|
|
71
|
+
acc += static_cast<CTP>(prolog_a(A[di + j])) *
|
|
72
|
+
static_cast<CTP>(prolog_b(B[j]));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
C[i] += static_cast<VAL>(acc);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
""",
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _set_user_or_default_code(*, user_code, default_code, default_prolog, src_code_list, obj_code_list):
|
|
83
|
+
"""
|
|
84
|
+
Args:
|
|
85
|
+
user_code: The user-provided LTO-IR as a bytes object or CUDA C++ source code
|
|
86
|
+
string.
|
|
87
|
+
default_code: The CUDA C++ source code that will be used if the user-provided
|
|
88
|
+
code is None.
|
|
89
|
+
default_prolog: The prolog to the CUDA C++ source code that will be used if the
|
|
90
|
+
user-provided code is None.
|
|
91
|
+
src_code_list: The list to which the source code will be appended to.
|
|
92
|
+
obj_code_list: The list to which the LTO-IR code will be appended to.
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
The pair (src_code_list, obj_code_list)
|
|
96
|
+
"""
|
|
97
|
+
|
|
98
|
+
if user_code is not None:
|
|
99
|
+
if isinstance(user_code, str):
|
|
100
|
+
target = src_code_list
|
|
101
|
+
elif isinstance(user_code, bytes):
|
|
102
|
+
target = obj_code_list
|
|
103
|
+
else:
|
|
104
|
+
raise AssertionError("Internal error.")
|
|
105
|
+
target.append(user_code)
|
|
106
|
+
return src_code_list, obj_code_list
|
|
107
|
+
|
|
108
|
+
assert default_code is not None and isinstance(default_code, str), "Internal error."
|
|
109
|
+
|
|
110
|
+
source_code = f"{default_prolog} {default_code}"
|
|
111
|
+
src_code_list.append(source_code)
|
|
112
|
+
|
|
113
|
+
return src_code_list, obj_code_list
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class KernelGen:
|
|
117
|
+
"""
|
|
118
|
+
This class defines a kernel generator for various sparse tensor operations.
|
|
119
|
+
The generated kernels can be JITted on-demand. Caching avoids recompilation
|
|
120
|
+
on subsequent uses.
|
|
121
|
+
|
|
122
|
+
The generation uses:
|
|
123
|
+
(1) kernel lookup from a collection of pre-defined kernels
|
|
124
|
+
(2) kernel generated by a sparse emitter
|
|
125
|
+
|
|
126
|
+
Clients can easily add new pre-defined kernels in the table above (for example,
|
|
127
|
+
by hand optimizing the automatically generated cuda code from the sparse emitter).
|
|
128
|
+
"""
|
|
129
|
+
|
|
130
|
+
def __init__(self, debug=False):
|
|
131
|
+
self._matmul_kernels_cache = Cache()
|
|
132
|
+
self._debug = debug
|
|
133
|
+
|
|
134
|
+
def generate_matmul(
|
|
135
|
+
self,
|
|
136
|
+
a,
|
|
137
|
+
b,
|
|
138
|
+
c,
|
|
139
|
+
compute_type,
|
|
140
|
+
prologs=None,
|
|
141
|
+
transpose_a=False,
|
|
142
|
+
transpose_b=False,
|
|
143
|
+
arch=None,
|
|
144
|
+
kernel=0,
|
|
145
|
+
):
|
|
146
|
+
"""
|
|
147
|
+
Matmul semantics:
|
|
148
|
+
|
|
149
|
+
Dot Product: If both inputs are 1-dimensional, it computes the dot
|
|
150
|
+
product (inner product).
|
|
151
|
+
|
|
152
|
+
Matrix-Vector Product: If the first input is a 2D tensor (matrix) and
|
|
153
|
+
the second is a 1D tensor (vector), it performs a matrix-vector
|
|
154
|
+
multiplication.
|
|
155
|
+
|
|
156
|
+
Vector-Matrix Product: If the first input is a 1D tensor and the second
|
|
157
|
+
is a 2D tensor, it performs a vector-matrix multiplication.
|
|
158
|
+
|
|
159
|
+
Matrix-Matrix Product: If both inputs are 2D tensors, it performs
|
|
160
|
+
standard matrix multiplication, requiring the number of columns in
|
|
161
|
+
the first matrix to equal the number of rows in the second.
|
|
162
|
+
|
|
163
|
+
Batched Matrix Product: If either input has more than two dimensions,
|
|
164
|
+
the extra leading dimensions are treated as "batch dimensions" and it
|
|
165
|
+
performs a batched matrix multiplication over the last two dimensions.
|
|
166
|
+
"""
|
|
167
|
+
|
|
168
|
+
format_a = a.tensor_format.name
|
|
169
|
+
format_b = b.tensor_format.name
|
|
170
|
+
format_c = c.tensor_format.name
|
|
171
|
+
vtp = type_str(a.dtype)
|
|
172
|
+
itp = type_str(a.index_type)
|
|
173
|
+
|
|
174
|
+
# Get user code.
|
|
175
|
+
if prologs is None:
|
|
176
|
+
user_prolog_a, user_prolog_b = None, None
|
|
177
|
+
else:
|
|
178
|
+
user_prolog_a, user_prolog_b, user_prolog_c = prologs.get("a"), prologs.get("b"), prologs.get("c")
|
|
179
|
+
if user_prolog_c is not None:
|
|
180
|
+
raise NotImplementedError("The code generation currently does not support prolog for C.")
|
|
181
|
+
|
|
182
|
+
# Try cache lookup.
|
|
183
|
+
key = (
|
|
184
|
+
format_a,
|
|
185
|
+
format_b,
|
|
186
|
+
format_c,
|
|
187
|
+
vtp,
|
|
188
|
+
itp,
|
|
189
|
+
compute_type,
|
|
190
|
+
user_prolog_a,
|
|
191
|
+
user_prolog_b,
|
|
192
|
+
transpose_a,
|
|
193
|
+
transpose_b,
|
|
194
|
+
arch,
|
|
195
|
+
kernel,
|
|
196
|
+
)
|
|
197
|
+
entry = self._matmul_kernels_cache.get(key)
|
|
198
|
+
if entry is not None:
|
|
199
|
+
return entry
|
|
200
|
+
|
|
201
|
+
# Nothing in cache, try kernel lookup. Note that kernel==0 overrides codegen
|
|
202
|
+
# with this lookup mechanism, all subsequent choices go to actual codegen.
|
|
203
|
+
typeless_key = (format_a, format_b, format_c, transpose_a, transpose_b)
|
|
204
|
+
code = _tensor_matmul_kernels.get(typeless_key) if kernel == 0 else None
|
|
205
|
+
|
|
206
|
+
# Prepare prolog.
|
|
207
|
+
ctp = type_str(compute_type)
|
|
208
|
+
if a.dtype in ["float8_e4m3fn", "float8_e5m2"]:
|
|
209
|
+
prolog = f"#include <cuda_fp8.h>\n\nusing CTP = {ctp};\n"
|
|
210
|
+
elif a.dtype == "float16":
|
|
211
|
+
prolog = f"#include <cuda_fp16.h>\n\nusing CTP = {ctp};\n"
|
|
212
|
+
elif a.dtype == "bfloat16":
|
|
213
|
+
prolog = f"#include <cuda_bf16.h>\n\nusing CTP = {ctp};\n"
|
|
214
|
+
elif a.dtype in ["complex64", "complex128"]:
|
|
215
|
+
prolog = f"#include <cuda/std/complex>\n\nusing CTP = {ctp};\n"
|
|
216
|
+
else:
|
|
217
|
+
prolog = f"using CTP = {ctp};\n"
|
|
218
|
+
|
|
219
|
+
# Use kernel lookup or emitter.
|
|
220
|
+
if code is not None:
|
|
221
|
+
# (1) Kernel lookup successful. Inject types into the typeless kernel.
|
|
222
|
+
source = f"{prolog}using VAL = {vtp};\nusing POS = {itp};\nusing CRD = {itp};\n{prolog_decl}{code}"
|
|
223
|
+
grid_iter = [(Index.FREE, 0)], True
|
|
224
|
+
else:
|
|
225
|
+
# (2) Sparse emitter. Emits proper types.
|
|
226
|
+
source, grid_iter = emit_matmul_kernel(
|
|
227
|
+
a, b, c, ctp, transpose_a=transpose_a, transpose_b=transpose_b, kernel=kernel
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
# The source and object code lists.
|
|
231
|
+
src_code_list, obj_code_list = [source], []
|
|
232
|
+
|
|
233
|
+
# User-provided or default prolog operation on A and B.
|
|
234
|
+
src_code_list, obj_code_list = _set_user_or_default_code(
|
|
235
|
+
user_code=user_prolog_a,
|
|
236
|
+
default_code=prolog_a_impl,
|
|
237
|
+
default_prolog=prolog,
|
|
238
|
+
src_code_list=src_code_list,
|
|
239
|
+
obj_code_list=obj_code_list,
|
|
240
|
+
)
|
|
241
|
+
src_code_list, obj_code_list = _set_user_or_default_code(
|
|
242
|
+
user_code=user_prolog_b,
|
|
243
|
+
default_code=prolog_b_impl,
|
|
244
|
+
default_prolog=prolog,
|
|
245
|
+
src_code_list=src_code_list,
|
|
246
|
+
obj_code_list=obj_code_list,
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
# TODO: this should use logger.debug(...)
|
|
250
|
+
if self._debug:
|
|
251
|
+
print("\n==> Compiling matmul\n")
|
|
252
|
+
for s in src_code_list:
|
|
253
|
+
print(s)
|
|
254
|
+
print("/////////////////////\n")
|
|
255
|
+
t1 = time.perf_counter_ns()
|
|
256
|
+
|
|
257
|
+
# Compile and link matmul function. Cache the result.
|
|
258
|
+
complex_path = pathfinder.find_nvidia_header_directory("cccl")
|
|
259
|
+
narrow_prec_path = pathfinder.find_nvidia_header_directory("cudart")
|
|
260
|
+
compiler_options = {
|
|
261
|
+
"std": "c++17",
|
|
262
|
+
"link_time_optimization": True,
|
|
263
|
+
"arch": arch,
|
|
264
|
+
"include_path": [complex_path, narrow_prec_path],
|
|
265
|
+
}
|
|
266
|
+
linker_options = {"link_time_optimization": True}
|
|
267
|
+
kernel_obj = compile_cpp_and_link(
|
|
268
|
+
src_code=src_code_list,
|
|
269
|
+
object_code=obj_code_list,
|
|
270
|
+
function_name="matmul_kernel",
|
|
271
|
+
compiler_options=compiler_options,
|
|
272
|
+
linker_options=linker_options,
|
|
273
|
+
)
|
|
274
|
+
assert kernel_obj is not None, "Internal error."
|
|
275
|
+
self._matmul_kernels_cache[key] = kernel_obj, grid_iter
|
|
276
|
+
|
|
277
|
+
if self._debug:
|
|
278
|
+
t2 = time.perf_counter_ns()
|
|
279
|
+
tt = (t2 - t1) / 1000.0 # ns -> us
|
|
280
|
+
print(f"<== Compiled matmul in {tt:10.2f} us.\n")
|
|
281
|
+
|
|
282
|
+
return kernel_obj, grid_iter
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
This module has internal utilities used in implementing the UST and related APIs.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
__all__ = []
|
|
10
|
+
|
|
11
|
+
import threading
|
|
12
|
+
from contextlib import nullcontext
|
|
13
|
+
|
|
14
|
+
import numpy as np
|
|
15
|
+
|
|
16
|
+
from nvmath.internal import utils
|
|
17
|
+
from nvmath.internal.ndbuffer import NDBuffer
|
|
18
|
+
from nvmath.internal.package_ifc import StreamHolder
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class Cache(dict):
|
|
22
|
+
"""
|
|
23
|
+
Cache for sharing kernels and matmuls.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def __init__(self):
|
|
27
|
+
self.lock = threading.Lock()
|
|
28
|
+
|
|
29
|
+
def free(self):
|
|
30
|
+
with self.lock:
|
|
31
|
+
for obj in self.values():
|
|
32
|
+
obj.free()
|
|
33
|
+
|
|
34
|
+
def __enter__(self):
|
|
35
|
+
return self
|
|
36
|
+
|
|
37
|
+
def __exit__(self, *args, **kwargs):
|
|
38
|
+
self.free()
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class LevelMap(dict):
|
|
42
|
+
def __init__(self, *args, **kwargs):
|
|
43
|
+
super().__init__(*args, **kwargs)
|
|
44
|
+
|
|
45
|
+
# TODO: for "subarray" like pos() and crd(), need to allocate one chunk and offset.
|
|
46
|
+
# Also need to keep track of the offsets, or recompute? Add pos.base, crd.base?
|
|
47
|
+
def to(self, device_id, stream_holder):
|
|
48
|
+
level_map = LevelMap(self)
|
|
49
|
+
for k in level_map:
|
|
50
|
+
level_map[k] = self[k].to(device_id, stream_holder)
|
|
51
|
+
return level_map
|
|
52
|
+
|
|
53
|
+
def empty_like(self, stream_holder):
|
|
54
|
+
level_map = LevelMap(self)
|
|
55
|
+
for k in level_map:
|
|
56
|
+
level_map[k] = utils.create_empty_tensor(
|
|
57
|
+
self[k].__class__, self[k].shape, self[k].dtype, self[k].device_id, stream_holder, verify_strides=False
|
|
58
|
+
)
|
|
59
|
+
return level_map
|
|
60
|
+
|
|
61
|
+
def copy_(self, src, stream_holder):
|
|
62
|
+
for k in self:
|
|
63
|
+
self[k].copy_(src[k], stream_holder)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
_CTPS = {
|
|
67
|
+
"complex64": "cuda::std::complex<float>",
|
|
68
|
+
"complex128": "cuda::std::complex<double>",
|
|
69
|
+
"float8_e4m3fn": "__nv_fp8_e4m3",
|
|
70
|
+
"float8_e5m2": "__nv_fp8_e5m2",
|
|
71
|
+
"bfloat16": "__nv_bfloat16",
|
|
72
|
+
"float16": "__half",
|
|
73
|
+
"float32": "float",
|
|
74
|
+
"float64": "double",
|
|
75
|
+
"int64": "long long",
|
|
76
|
+
"int32": "int",
|
|
77
|
+
"int16": "int",
|
|
78
|
+
"int8": "int",
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
_NP_ENVELOPE = {
|
|
82
|
+
"complex32": np.complex64,
|
|
83
|
+
"complex64": np.complex64,
|
|
84
|
+
"complex128": np.complex128,
|
|
85
|
+
"float8_e4m3fn": np.float16,
|
|
86
|
+
"float8_e5m2": np.float16,
|
|
87
|
+
"bfloat16": np.float32,
|
|
88
|
+
"float16": np.float16,
|
|
89
|
+
"float32": np.float32,
|
|
90
|
+
"float64": np.float64,
|
|
91
|
+
"int64": np.int64,
|
|
92
|
+
"int32": np.int32,
|
|
93
|
+
"int16": np.int16,
|
|
94
|
+
"int8": np.int8,
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def type_str(tp):
|
|
99
|
+
return _CTPS[tp]
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def np_enveloping_type(tp):
|
|
103
|
+
return _NP_ENVELOPE[tp]
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def resolve_stream(stream, tensor, target_device_id=None):
|
|
107
|
+
"""
|
|
108
|
+
Get a default package stream (based on the dense tensor package)
|
|
109
|
+
or wrap user-provided stream.
|
|
110
|
+
|
|
111
|
+
Similar logic is implemented inside statefull instances for matmul,
|
|
112
|
+
ffts etc, but ust.Tensor is a standalone public API, so we need
|
|
113
|
+
to implement the logic separately.
|
|
114
|
+
For internal usages from stateful objects, we don't interfere
|
|
115
|
+
and just use the provided StreamHolder.
|
|
116
|
+
"""
|
|
117
|
+
# For internal use, we accept StreamHolder so that UST `to` has a
|
|
118
|
+
# consistent interface with `TensorHolder.to`.
|
|
119
|
+
if isinstance(stream, StreamHolder):
|
|
120
|
+
return stream
|
|
121
|
+
device_id = tensor.device_id
|
|
122
|
+
if device_id == "cpu":
|
|
123
|
+
if target_device_id is None or target_device_id == "cpu":
|
|
124
|
+
return None
|
|
125
|
+
device_id = target_device_id
|
|
126
|
+
package = tensor._dense_tensorholder_type.device_tensor_class.name
|
|
127
|
+
return utils.get_or_create_stream(device_id, stream, package)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def stream_context(stream_holder):
|
|
131
|
+
if stream_holder is None:
|
|
132
|
+
return nullcontext()
|
|
133
|
+
return stream_holder.ctx
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def as_external_tensor(tensor, stream_holder):
|
|
137
|
+
"""
|
|
138
|
+
Return unchanged external package tensor (numpy, torch, etc.)
|
|
139
|
+
or convert a NDBuffer to a host tensor if necessary.
|
|
140
|
+
Ensures the tensor can be subsequently used with
|
|
141
|
+
ufuncs, reductions, etc. (which are not available with NDBuffer).
|
|
142
|
+
"""
|
|
143
|
+
if type(tensor) is not NDBuffer:
|
|
144
|
+
return tensor
|
|
145
|
+
if tensor.device_id == "cpu":
|
|
146
|
+
return tensor.as_numpy()
|
|
147
|
+
tensor_host = NDBuffer.empty_like(tensor, device_id="cpu")
|
|
148
|
+
tensor_host.copy_(tensor, stream=stream_holder)
|
|
149
|
+
return tensor_host.as_numpy()
|
|
File without changes
|