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,305 @@
|
|
|
1
|
+
# Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
Interface to seamlessly use BSR tensors from different libraries.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations # allows typehint of class methods to return the self class
|
|
10
|
+
|
|
11
|
+
__all__ = ["BSRTensorHolder"]
|
|
12
|
+
|
|
13
|
+
from typing import Literal, TypeVar
|
|
14
|
+
|
|
15
|
+
from nvmath._internal.layout import check_monotonic_strides, is_contiguous_and_dense
|
|
16
|
+
from nvmath.internal import tensor_wrapper
|
|
17
|
+
from nvmath.internal.package_ifc import StreamHolder
|
|
18
|
+
from nvmath.internal.tensor_ifc import TensorHolder
|
|
19
|
+
from nvmath.internal.utils import infer_object_package
|
|
20
|
+
|
|
21
|
+
from .sparse_tensor_ifc import SparseTensorHolder
|
|
22
|
+
|
|
23
|
+
"""
|
|
24
|
+
A generic type for the third-party BSRTensor which a BSRTensorHolder implementation wraps
|
|
25
|
+
around.
|
|
26
|
+
"""
|
|
27
|
+
BSRTensor = TypeVar("BSRTensor")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class BSRTensorHolder(SparseTensorHolder):
|
|
31
|
+
"""
|
|
32
|
+
A simple wrapper type for BSR sparse tensors to make the API package-agnostic. The
|
|
33
|
+
naming convention is sparse format name with the suffix "TensorHolder", which convention
|
|
34
|
+
is used in the sparse format helper.
|
|
35
|
+
|
|
36
|
+
Since the implementation is in terms of our dense tensor abstraction, package-specific
|
|
37
|
+
implementation is not needed.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
_format_name: str = "BSR"
|
|
41
|
+
|
|
42
|
+
def __init__(
|
|
43
|
+
self, block_size, block_order, crow_indices, col_indices, values, *, attr_name_map=None, shape=None, tensor=None
|
|
44
|
+
):
|
|
45
|
+
# tensor is the native tensor.
|
|
46
|
+
self.tensor = tensor
|
|
47
|
+
|
|
48
|
+
# The block size is a sequence of integers.
|
|
49
|
+
self._block_size = block_size
|
|
50
|
+
|
|
51
|
+
# The block order is "left" or "right".
|
|
52
|
+
self._block_order = block_order
|
|
53
|
+
|
|
54
|
+
# attr_name_map is the canonical attribute name to package attribute name map.
|
|
55
|
+
# It is set when constructing from a tensor, otherwise it is None.
|
|
56
|
+
self._attr_name_map = attr_name_map
|
|
57
|
+
|
|
58
|
+
assert (shape is not None) ^ (tensor is not None), "Internal error."
|
|
59
|
+
|
|
60
|
+
if shape is not None:
|
|
61
|
+
self._shape = shape
|
|
62
|
+
else:
|
|
63
|
+
self._shape = tuple(tensor.shape)
|
|
64
|
+
|
|
65
|
+
# Wrap constituent dense tensors, if required.
|
|
66
|
+
if not isinstance(crow_indices, TensorHolder):
|
|
67
|
+
crow_indices = tensor_wrapper.wrap_operand(crow_indices)
|
|
68
|
+
|
|
69
|
+
if not isinstance(col_indices, TensorHolder):
|
|
70
|
+
col_indices = tensor_wrapper.wrap_operand(col_indices)
|
|
71
|
+
|
|
72
|
+
if not isinstance(values, TensorHolder):
|
|
73
|
+
values = tensor_wrapper.wrap_operand(values)
|
|
74
|
+
|
|
75
|
+
# The wrapped constituent dense tensors.
|
|
76
|
+
self._crow_indices = crow_indices
|
|
77
|
+
self._col_indices = col_indices
|
|
78
|
+
self._values = values
|
|
79
|
+
|
|
80
|
+
# Ensure constituent dense tensors are all on the same device.
|
|
81
|
+
device_ids = {d.device_id for d in (self._crow_indices, self._col_indices, self._values)}
|
|
82
|
+
message = f"Internal error: the arrays defining the sparse format aren't on the same device {device_ids}."
|
|
83
|
+
assert len(device_ids) == 1, message
|
|
84
|
+
self._device_id = device_ids.pop()
|
|
85
|
+
|
|
86
|
+
self._device = self._values.device
|
|
87
|
+
|
|
88
|
+
# Capture the native tensor package for use in reset_unchecked().
|
|
89
|
+
self.tensor_package = infer_object_package(self.tensor)
|
|
90
|
+
|
|
91
|
+
# The tensor holder type for the dense constituent tensors (take from values, since
|
|
92
|
+
# all constituent tensors have the same type).
|
|
93
|
+
self._dense_tensorholder_type = values.__class__
|
|
94
|
+
|
|
95
|
+
@classmethod
|
|
96
|
+
def create_from_tensor(cls, tensor, *, attr_name_map=None):
|
|
97
|
+
assert attr_name_map is not None, "Internal error."
|
|
98
|
+
|
|
99
|
+
# tensor is the native tensor.
|
|
100
|
+
# For UST, the buffers will be CuPy ndarrays.
|
|
101
|
+
block_size = attr_name_map["block_size"](tensor)
|
|
102
|
+
block_order = attr_name_map["block_order"](tensor)
|
|
103
|
+
crow_indices = attr_name_map["crow_indices"](tensor)
|
|
104
|
+
col_indices = attr_name_map["col_indices"](tensor)
|
|
105
|
+
values = attr_name_map["values"](tensor)
|
|
106
|
+
return BSRTensorHolder(
|
|
107
|
+
block_size, block_order, crow_indices, col_indices, values, attr_name_map=attr_name_map, tensor=tensor
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
@property
|
|
111
|
+
def attr_name_map(self):
|
|
112
|
+
return self._attr_name_map
|
|
113
|
+
|
|
114
|
+
@property
|
|
115
|
+
def device(self):
|
|
116
|
+
return self._device
|
|
117
|
+
|
|
118
|
+
@property
|
|
119
|
+
def device_id(self):
|
|
120
|
+
return self._device_id
|
|
121
|
+
|
|
122
|
+
@property
|
|
123
|
+
def dtype(self):
|
|
124
|
+
return self._values.dtype
|
|
125
|
+
|
|
126
|
+
@property
|
|
127
|
+
def index_type(self):
|
|
128
|
+
return self._crow_indices.dtype
|
|
129
|
+
|
|
130
|
+
@property
|
|
131
|
+
def format_name(self) -> str:
|
|
132
|
+
return BSRTensorHolder._format_name
|
|
133
|
+
|
|
134
|
+
@property
|
|
135
|
+
def num_dimensions(self):
|
|
136
|
+
return len(self._shape)
|
|
137
|
+
|
|
138
|
+
@property
|
|
139
|
+
def shape(self):
|
|
140
|
+
return self._shape
|
|
141
|
+
|
|
142
|
+
@property
|
|
143
|
+
def block_size(self):
|
|
144
|
+
return self._block_size
|
|
145
|
+
|
|
146
|
+
@property
|
|
147
|
+
def block_order(self):
|
|
148
|
+
return self._block_order
|
|
149
|
+
|
|
150
|
+
@property
|
|
151
|
+
def crow_indices(self) -> TensorHolder:
|
|
152
|
+
"""The TensorHolder object wrapping the crow_indices array."""
|
|
153
|
+
return self._crow_indices
|
|
154
|
+
|
|
155
|
+
@property
|
|
156
|
+
def col_indices(self) -> TensorHolder:
|
|
157
|
+
"""The TensorHolder object wrapping the col_indices array."""
|
|
158
|
+
return self._col_indices
|
|
159
|
+
|
|
160
|
+
@property
|
|
161
|
+
def values(self) -> TensorHolder:
|
|
162
|
+
"""The TensorHolder object wrapping the values array."""
|
|
163
|
+
return self._values
|
|
164
|
+
|
|
165
|
+
def to(self, device_id: int | Literal["cpu"], stream_holder: StreamHolder | None):
|
|
166
|
+
"""Copy the BSRTensor representation to a different device.
|
|
167
|
+
|
|
168
|
+
No copy is performed if the BSRTensor is already on the requested device.
|
|
169
|
+
"""
|
|
170
|
+
if self.tensor_package == "nvmath":
|
|
171
|
+
return super().to(device_id=device_id, stream_holder=stream_holder)
|
|
172
|
+
|
|
173
|
+
target_crow_indices = self.crow_indices.to(device_id=device_id, stream_holder=stream_holder)
|
|
174
|
+
target_col_indices = self.col_indices.to(device_id=device_id, stream_holder=stream_holder)
|
|
175
|
+
target_values = self.values.to(device_id=device_id, stream_holder=stream_holder)
|
|
176
|
+
|
|
177
|
+
return BSRTensorHolder(
|
|
178
|
+
self.block_size,
|
|
179
|
+
self.block_order,
|
|
180
|
+
target_crow_indices,
|
|
181
|
+
target_col_indices,
|
|
182
|
+
target_values,
|
|
183
|
+
attr_name_map=self.attr_name_map,
|
|
184
|
+
shape=self.shape,
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
def copy_(self, src, stream_holder: StreamHolder | None) -> None:
|
|
188
|
+
"""Overwrite self.tensor (in-place) with a copy of src (BSRTensor)."""
|
|
189
|
+
|
|
190
|
+
self._block_size = src.block_size
|
|
191
|
+
self._block_order = src.block_order
|
|
192
|
+
self.crow_indices.copy_(src=src.crow_indices, stream_holder=stream_holder)
|
|
193
|
+
self.col_indices.copy_(src=src.col_indices, stream_holder=stream_holder)
|
|
194
|
+
self.values.copy_(src=src.values, stream_holder=stream_holder)
|
|
195
|
+
|
|
196
|
+
def to_ust(self, *, stream):
|
|
197
|
+
from nvmath.sparse.ust.tensor import Tensor
|
|
198
|
+
from nvmath.sparse.ust.tensor_format import NamedFormats
|
|
199
|
+
|
|
200
|
+
wrapped = self
|
|
201
|
+
tensor = wrapped.tensor
|
|
202
|
+
if not (wrapped.attr_name_map["is_coalesced"](tensor) and wrapped.attr_name_map["has_sorted_indices"](tensor)):
|
|
203
|
+
raise ValueError(
|
|
204
|
+
"The BSR tensor is not coalesced (metadata sorted with duplicates removed). \
|
|
205
|
+
To coalesce, use the operation provided by your sparse tensor library: `coalesce()`, `sum_duplicates()`, ..."
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
if not (
|
|
209
|
+
is_contiguous_and_dense(wrapped.crow_indices.shape, wrapped.crow_indices.strides)
|
|
210
|
+
and is_contiguous_and_dense(wrapped.col_indices.shape, wrapped.col_indices.strides)
|
|
211
|
+
and is_contiguous_and_dense(wrapped.values.shape, wrapped.values.strides)
|
|
212
|
+
):
|
|
213
|
+
raise ValueError(
|
|
214
|
+
"The sparse tensor representation (crow_indices(), col_indices(), and values() tensors) must be \
|
|
215
|
+
dense and contiguous."
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
values = wrapped.values.memory_buffer() # Typed memory viewed as a 1-D tensor.
|
|
219
|
+
|
|
220
|
+
num_dim = self.num_dimensions
|
|
221
|
+
num_sparse_dim = self.attr_name_map["num_sparse_dim"](tensor)
|
|
222
|
+
num_dense_dim = self.attr_name_map["num_dense_dim"](tensor)
|
|
223
|
+
num_batch_dim = num_dim - num_sparse_dim - num_dense_dim
|
|
224
|
+
|
|
225
|
+
if wrapped.block_order == "left" and num_batch_dim > 0:
|
|
226
|
+
raise ValueError("The 'left' block layout is not currently supported for batched BSR UST.")
|
|
227
|
+
|
|
228
|
+
block_size = wrapped.block_size
|
|
229
|
+
tensor_format = (
|
|
230
|
+
NamedFormats.BSRLeft(block_size)
|
|
231
|
+
if wrapped.block_order == "left"
|
|
232
|
+
else NamedFormats.BSRRightd(block_size, num_batch_dim, num_dense_dim)
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
# Check if the batch axes are in C-order for all component dense arrays.
|
|
236
|
+
if not (
|
|
237
|
+
check_monotonic_strides(wrapped.crow_indices.strides[:num_batch_dim], reverse=True)
|
|
238
|
+
and check_monotonic_strides(wrapped.col_indices.strides[:num_batch_dim], reverse=True)
|
|
239
|
+
and check_monotonic_strides(wrapped.values.strides[:num_batch_dim], reverse=True)
|
|
240
|
+
):
|
|
241
|
+
raise ValueError(
|
|
242
|
+
"The batch dimensions in the sparse tensor representation (crow_indices(), col_indices(), \
|
|
243
|
+
and values() tensors) must use the C-layout."
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
# Create the UST.
|
|
247
|
+
ust = Tensor(tensor.shape, tensor_format=tensor_format, index_type=wrapped.index_type, dtype=wrapped.dtype)
|
|
248
|
+
|
|
249
|
+
ust._pos[num_batch_dim + 1] = wrapped.crow_indices
|
|
250
|
+
ust._crd[num_batch_dim + 1] = wrapped.col_indices
|
|
251
|
+
ust._val = values
|
|
252
|
+
|
|
253
|
+
return ust
|
|
254
|
+
|
|
255
|
+
def to_package(self):
|
|
256
|
+
"""
|
|
257
|
+
This will create a sparse tensor for the original package from which this
|
|
258
|
+
interface was created.
|
|
259
|
+
"""
|
|
260
|
+
create_bsr = self.attr_name_map["sparse_format_helper"].create_bsr
|
|
261
|
+
return create_bsr(self.shape, self.block_size, self.crow_indices, self.col_indices, self.values)
|
|
262
|
+
|
|
263
|
+
def release(self):
|
|
264
|
+
"""
|
|
265
|
+
This method will release the wrapped tensor and any format-specific data
|
|
266
|
+
by setting them to None.
|
|
267
|
+
"""
|
|
268
|
+
# The tensor reference.
|
|
269
|
+
self.tensor = None
|
|
270
|
+
|
|
271
|
+
# Format-specific data.
|
|
272
|
+
self._crow_indices = None
|
|
273
|
+
self._col_indices = None
|
|
274
|
+
self._values = None
|
|
275
|
+
|
|
276
|
+
def reset_unchecked(self, tensor):
|
|
277
|
+
"""
|
|
278
|
+
This method will reset the wrapped tensor to the specified one, and update
|
|
279
|
+
any format-specific data accordingly. It assumes that all attributes
|
|
280
|
+
like the device, shape, etc are consistent between the existing and new tensor.
|
|
281
|
+
|
|
282
|
+
Args:
|
|
283
|
+
tensor: The native tensor to wrap.
|
|
284
|
+
"""
|
|
285
|
+
# Update the tensor reference.
|
|
286
|
+
self.tensor = tensor
|
|
287
|
+
|
|
288
|
+
# Format-specific data.
|
|
289
|
+
|
|
290
|
+
if self.tensor_package == "nvmath":
|
|
291
|
+
# The data arrays are already wrapped.
|
|
292
|
+
self._crow_indices = self._attr_name_map["crow_indices"](tensor)
|
|
293
|
+
self._col_indices = self._attr_name_map["col_indices"](tensor)
|
|
294
|
+
self._values = self._attr_name_map["values"](tensor)
|
|
295
|
+
else:
|
|
296
|
+
wrapper = self._dense_tensorholder_type
|
|
297
|
+
|
|
298
|
+
crow_indices = self._attr_name_map["crow_indices"](tensor)
|
|
299
|
+
self._crow_indices = wrapper(crow_indices)
|
|
300
|
+
|
|
301
|
+
col_indices = self._attr_name_map["col_indices"](tensor)
|
|
302
|
+
self._col_indices = wrapper(col_indices)
|
|
303
|
+
|
|
304
|
+
values = self._attr_name_map["values"](tensor)
|
|
305
|
+
self._values = wrapper(values)
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
# Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
Interface to seamlessly use COO tensors from different libraries.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations # allows typehint of class methods to return the self class
|
|
10
|
+
|
|
11
|
+
__all__ = ["COOTensorHolder"]
|
|
12
|
+
|
|
13
|
+
from typing import Literal, TypeVar
|
|
14
|
+
|
|
15
|
+
from nvmath._internal.layout import is_contiguous_and_dense
|
|
16
|
+
from nvmath.internal import tensor_wrapper
|
|
17
|
+
from nvmath.internal.package_ifc import StreamHolder
|
|
18
|
+
from nvmath.internal.tensor_ifc import TensorHolder
|
|
19
|
+
from nvmath.internal.utils import infer_object_package
|
|
20
|
+
|
|
21
|
+
from .sparse_tensor_ifc import SparseTensorHolder
|
|
22
|
+
|
|
23
|
+
"""
|
|
24
|
+
A generic type for the third-party COOTensor which a COOTensorHolder implementation wraps
|
|
25
|
+
around.
|
|
26
|
+
"""
|
|
27
|
+
COOTensor = TypeVar("COOTensor")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class COOTensorHolder(SparseTensorHolder):
|
|
31
|
+
"""
|
|
32
|
+
A simple wrapper type for COO sparse tensors to make the API package-agnostic. The
|
|
33
|
+
naming convention is sparse format name with the suffix "TensorHolder", which convention
|
|
34
|
+
is used in the sparse format helper.
|
|
35
|
+
|
|
36
|
+
Since the implementation is in terms of our dense tensor abstraction, package-specific
|
|
37
|
+
implementation is not needed.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
_format_name: str = "COO"
|
|
41
|
+
|
|
42
|
+
def __init__(self, indices, values, *, attr_name_map=None, shape=None, tensor=None):
|
|
43
|
+
# tensor is the native tensor.
|
|
44
|
+
self.tensor = tensor
|
|
45
|
+
|
|
46
|
+
# attr_name_map is the canonical attribute name to package attribute name map.
|
|
47
|
+
# It is set when constructing from a tensor, otherwise it is None.
|
|
48
|
+
self._attr_name_map = attr_name_map
|
|
49
|
+
|
|
50
|
+
assert (shape is not None) ^ (tensor is not None), "Internal error."
|
|
51
|
+
|
|
52
|
+
if shape is not None:
|
|
53
|
+
self._shape = shape
|
|
54
|
+
else:
|
|
55
|
+
self._shape = tuple(tensor.shape)
|
|
56
|
+
|
|
57
|
+
# Wrap constituent dense tensors, if required. If it's a sequence, it will be
|
|
58
|
+
# a sequence of TensorHolder.
|
|
59
|
+
if not isinstance(indices, TensorHolder):
|
|
60
|
+
indices = [tensor_wrapper.wrap_operand(i) for i in indices]
|
|
61
|
+
|
|
62
|
+
if not isinstance(values, TensorHolder):
|
|
63
|
+
values = tensor_wrapper.wrap_operand(values)
|
|
64
|
+
|
|
65
|
+
# The wrapped constituent dense tensors.
|
|
66
|
+
self._indices = indices
|
|
67
|
+
self._values = values
|
|
68
|
+
|
|
69
|
+
# Ensure constituent dense tensors are all on the same device.
|
|
70
|
+
device_ids = {d.device_id for d in (*self._indices, self._values)}
|
|
71
|
+
message = f"Internal error: the arrays defining the sparse format aren't on the same device {device_ids}."
|
|
72
|
+
assert len(device_ids) == 1, message
|
|
73
|
+
self._device_id = device_ids.pop()
|
|
74
|
+
|
|
75
|
+
self._device = self._values.device
|
|
76
|
+
|
|
77
|
+
# Capture the native tensor package for use in reset_unchecked().
|
|
78
|
+
self.tensor_package = infer_object_package(self.tensor)
|
|
79
|
+
|
|
80
|
+
# The tensor holder type for the dense constituent tensors (take from values, since
|
|
81
|
+
# all constituent tensors have the same type).
|
|
82
|
+
self._dense_tensorholder_type = values.__class__
|
|
83
|
+
|
|
84
|
+
@classmethod
|
|
85
|
+
def create_from_tensor(cls, tensor, *, attr_name_map=None):
|
|
86
|
+
assert attr_name_map is not None, "Internal error."
|
|
87
|
+
|
|
88
|
+
# tensor is the native tensor.
|
|
89
|
+
# For UST, the buffers will be CuPy ndarrays.
|
|
90
|
+
indices = attr_name_map["indices"](tensor)
|
|
91
|
+
values = attr_name_map["values"](tensor)
|
|
92
|
+
return COOTensorHolder(indices, values, attr_name_map=attr_name_map, tensor=tensor)
|
|
93
|
+
|
|
94
|
+
@property
|
|
95
|
+
def attr_name_map(self):
|
|
96
|
+
return self._attr_name_map
|
|
97
|
+
|
|
98
|
+
@property
|
|
99
|
+
def device(self):
|
|
100
|
+
return self._device
|
|
101
|
+
|
|
102
|
+
@property
|
|
103
|
+
def device_id(self):
|
|
104
|
+
return self._device_id
|
|
105
|
+
|
|
106
|
+
@property
|
|
107
|
+
def dtype(self):
|
|
108
|
+
return self._values.dtype
|
|
109
|
+
|
|
110
|
+
@property
|
|
111
|
+
def index_type(self):
|
|
112
|
+
# TODO: check that all index arrays in the sequence have the same dtype.
|
|
113
|
+
return self._indices[0].dtype
|
|
114
|
+
|
|
115
|
+
@property
|
|
116
|
+
def format_name(self) -> str:
|
|
117
|
+
return COOTensorHolder._format_name
|
|
118
|
+
|
|
119
|
+
@property
|
|
120
|
+
def num_dimensions(self):
|
|
121
|
+
return len(self._shape)
|
|
122
|
+
|
|
123
|
+
@property
|
|
124
|
+
def shape(self):
|
|
125
|
+
return self._shape
|
|
126
|
+
|
|
127
|
+
@property
|
|
128
|
+
def indices(self):
|
|
129
|
+
"""The TensorHolder object wrapping the indices array."""
|
|
130
|
+
return self._indices
|
|
131
|
+
|
|
132
|
+
@property
|
|
133
|
+
def values(self) -> TensorHolder:
|
|
134
|
+
"""The TensorHolder object wrapping the values array."""
|
|
135
|
+
return self._values
|
|
136
|
+
|
|
137
|
+
def to(self, device_id: int | Literal["cpu"], stream_holder: StreamHolder | None):
|
|
138
|
+
"""Copy the COOTensor representation to a different device.
|
|
139
|
+
|
|
140
|
+
No copy is performed if the COOTensor is already on the requested device.
|
|
141
|
+
"""
|
|
142
|
+
if self.tensor_package == "nvmath":
|
|
143
|
+
return super().to(device_id=device_id, stream_holder=stream_holder)
|
|
144
|
+
|
|
145
|
+
target_indices = [i.to(device_id=device_id, stream_holder=stream_holder) for i in self.indices]
|
|
146
|
+
target_values = self.values.to(device_id=device_id, stream_holder=stream_holder)
|
|
147
|
+
|
|
148
|
+
return COOTensorHolder(target_indices, target_values, attr_name_map=self.attr_name_map, shape=self.shape)
|
|
149
|
+
|
|
150
|
+
def copy_(self, src, stream_holder: StreamHolder | None) -> None:
|
|
151
|
+
"""Overwrite self.tensor (in-place) with a copy of src (COOTensor)."""
|
|
152
|
+
|
|
153
|
+
for c, component in enumerate(self.indices):
|
|
154
|
+
component.copy_(src=src.indices[c], stream_holder=stream_holder)
|
|
155
|
+
self.values.copy_(src=src.values, stream_holder=stream_holder)
|
|
156
|
+
|
|
157
|
+
def to_ust(self, *, stream):
|
|
158
|
+
from nvmath.sparse.ust.tensor import Tensor, _top_array
|
|
159
|
+
from nvmath.sparse.ust.tensor_format import NamedFormats
|
|
160
|
+
|
|
161
|
+
wrapped = self
|
|
162
|
+
tensor = wrapped.tensor
|
|
163
|
+
if not wrapped.attr_name_map["is_coalesced"](tensor):
|
|
164
|
+
raise ValueError(
|
|
165
|
+
"The COO tensor is not coalesced (metadata sorted with duplicates removed). \
|
|
166
|
+
To coalesce, use the operation provided by your sparse tensor library: `coalesce()`, `sum_duplicates()`, ..."
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
if not (
|
|
170
|
+
all(is_contiguous_and_dense(i.shape, i.strides) for i in self.indices)
|
|
171
|
+
and is_contiguous_and_dense(wrapped.values.shape, wrapped.values.strides)
|
|
172
|
+
):
|
|
173
|
+
raise ValueError(
|
|
174
|
+
"The sparse tensor representation (indices() and values() tensors) must be \
|
|
175
|
+
dense and contiguous."
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
values = wrapped.values.memory_buffer() # Typed memory viewed as a 1-D tensor.
|
|
179
|
+
|
|
180
|
+
num_sparse_dim = self.attr_name_map["num_sparse_dim"](tensor)
|
|
181
|
+
num_dense_dim = self.attr_name_map["num_dense_dim"](tensor)
|
|
182
|
+
tensor_format = NamedFormats.COOd(num_sparse_dim, num_dense_dim)
|
|
183
|
+
|
|
184
|
+
# Check if the batch axes are in C-order for all component dense arrays.
|
|
185
|
+
if not all(i.strides == (1,) for i in wrapped.indices):
|
|
186
|
+
raise ValueError("The batch dimensions in the sparse tensor representation indices() must use the C-layout.")
|
|
187
|
+
|
|
188
|
+
# Create the UST.
|
|
189
|
+
ust = Tensor(tensor.shape, tensor_format=tensor_format, index_type=wrapped.index_type, dtype=wrapped.dtype)
|
|
190
|
+
|
|
191
|
+
dense_tensorholder_type = wrapped._dense_tensorholder_type
|
|
192
|
+
if wrapped.device_id == "cpu":
|
|
193
|
+
stream_holder = None
|
|
194
|
+
else:
|
|
195
|
+
from nvmath.internal import utils
|
|
196
|
+
|
|
197
|
+
stream_holder = utils.get_or_create_stream(wrapped.device_id, stream, dense_tensorholder_type.name)
|
|
198
|
+
ust._pos[0] = _top_array(
|
|
199
|
+
wrapped.indices[0].size,
|
|
200
|
+
dtype=wrapped.index_type,
|
|
201
|
+
device_id=wrapped.device_id,
|
|
202
|
+
dense_tensorholder_type=dense_tensorholder_type,
|
|
203
|
+
stream_holder=stream_holder,
|
|
204
|
+
)
|
|
205
|
+
for d in range(num_sparse_dim):
|
|
206
|
+
ust._crd[d] = wrapped.indices[d]
|
|
207
|
+
ust._val = values
|
|
208
|
+
|
|
209
|
+
return ust
|
|
210
|
+
|
|
211
|
+
def to_package(self):
|
|
212
|
+
"""
|
|
213
|
+
This will create a sparse tensor for the original package from which this
|
|
214
|
+
interface was created.
|
|
215
|
+
"""
|
|
216
|
+
create_coo = self.attr_name_map["sparse_format_helper"].create_coo
|
|
217
|
+
return create_coo(self.shape, self.indices, self.values)
|
|
218
|
+
|
|
219
|
+
def release(self):
|
|
220
|
+
"""
|
|
221
|
+
This method will release the wrapped tensor and any format-specific data
|
|
222
|
+
by setting them to None.
|
|
223
|
+
"""
|
|
224
|
+
# The tensor reference.
|
|
225
|
+
self.tensor = None
|
|
226
|
+
|
|
227
|
+
# Format-specific data.
|
|
228
|
+
self._indices = None
|
|
229
|
+
self._values = None
|
|
230
|
+
|
|
231
|
+
def reset_unchecked(self, tensor):
|
|
232
|
+
"""
|
|
233
|
+
This method will reset the wrapped tensor to the specified one, and update
|
|
234
|
+
any format-specific data accordingly. It assumes that all attributes
|
|
235
|
+
like the device, shape, etc are consistent between the existing and new tensor.
|
|
236
|
+
|
|
237
|
+
Args:
|
|
238
|
+
tensor: The native tensor to wrap.
|
|
239
|
+
"""
|
|
240
|
+
# Update the tensor reference.
|
|
241
|
+
self.tensor = tensor
|
|
242
|
+
|
|
243
|
+
# Format-specific data.
|
|
244
|
+
|
|
245
|
+
if self.tensor_package == "nvmath":
|
|
246
|
+
# The data arrays are already wrapped.
|
|
247
|
+
self._indices = self._attr_name_map["indices"](tensor)
|
|
248
|
+
self._values = self._attr_name_map["values"](tensor)
|
|
249
|
+
else:
|
|
250
|
+
wrapper = self._dense_tensorholder_type
|
|
251
|
+
|
|
252
|
+
indices = self._attr_name_map["indices"](tensor)
|
|
253
|
+
self._indices = [wrapper(i) for i in indices]
|
|
254
|
+
|
|
255
|
+
values = self._attr_name_map["values"](tensor)
|
|
256
|
+
self._values = wrapper(values)
|