nvmath-python 0.5.0__cp313-cp313-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 +37 -0
- nvmath/_internal/__init__.py +0 -0
- nvmath/_internal/layout.py +58 -0
- nvmath/_utils.py +363 -0
- nvmath/bindings/__init__.pxd +0 -0
- nvmath/bindings/__init__.py +44 -0
- nvmath/bindings/_internal/__init__.pxd +0 -0
- nvmath/bindings/_internal/__init__.py +0 -0
- nvmath/bindings/_internal/cublas.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cublas.pxd +518 -0
- nvmath/bindings/_internal/cublasLt.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cublasLt.pxd +54 -0
- nvmath/bindings/_internal/cudss.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cudss.pxd +44 -0
- nvmath/bindings/_internal/cufft.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cufft.pxd +69 -0
- nvmath/bindings/_internal/cufftMp.pxd +77 -0
- nvmath/bindings/_internal/curand.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/curand.pxd +42 -0
- nvmath/bindings/_internal/cusolver.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cusolver.pxd +15 -0
- nvmath/bindings/_internal/cusolverDn.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cusolverDn.pxd +386 -0
- nvmath/bindings/_internal/cusparse.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/cusparse.pxd +270 -0
- nvmath/bindings/_internal/mathdx.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/mathdx.pxd +79 -0
- nvmath/bindings/_internal/nvshmem.pxd +29 -0
- nvmath/bindings/_internal/utils.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/_internal/utils.pxd +186 -0
- nvmath/bindings/cublas.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cublas.pxd +545 -0
- nvmath/bindings/cublas.pyi +18 -0
- nvmath/bindings/cublasLt.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cublasLt.pxd +99 -0
- nvmath/bindings/cudss.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cudss.pxd +83 -0
- nvmath/bindings/cudss.pyi +249 -0
- nvmath/bindings/cufft.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cufft.pxd +114 -0
- nvmath/bindings/cufftMp.pxd +124 -0
- nvmath/bindings/curand.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/curand.pxd +71 -0
- nvmath/bindings/cusolver.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cusolver.pxd +60 -0
- nvmath/bindings/cusolverDn.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cusolverDn.pxd +410 -0
- nvmath/bindings/cusparse.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cusparse.pxd +329 -0
- nvmath/bindings/cycublas.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cycublas.pxd +657 -0
- nvmath/bindings/cycublasLt.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cycublasLt.pxd +1010 -0
- nvmath/bindings/cycudss.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cycudss.pxd +191 -0
- nvmath/bindings/cycufft.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cycufft.pxd +320 -0
- nvmath/bindings/cycufftMp.pxd +333 -0
- nvmath/bindings/cycurand.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cycurand.pxd +146 -0
- nvmath/bindings/cycusolver.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cycusolver.pxd +143 -0
- nvmath/bindings/cycusolverDn.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cycusolverDn.pxd +414 -0
- nvmath/bindings/cycusparse.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cycusparse.pxd +476 -0
- nvmath/bindings/cymathdx.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/cymathdx.pxd +363 -0
- nvmath/bindings/cynvshmem.pxd +126 -0
- nvmath/bindings/mathdx.cp313-win_amd64.pyd +0 -0
- nvmath/bindings/mathdx.pxd +131 -0
- nvmath/bindings/mathdx.pyi +686 -0
- nvmath/bindings/nvpl/__init__.pxd +0 -0
- nvmath/bindings/nvpl/__init__.py +11 -0
- nvmath/bindings/nvpl/_internal/__init__.pxd +0 -0
- nvmath/bindings/nvpl/_internal/__init__.py +0 -0
- nvmath/bindings/nvpl/_internal/fft.pxd +36 -0
- nvmath/bindings/nvpl/cyfft.pxd +87 -0
- nvmath/bindings/nvpl/fft.pxd +100 -0
- nvmath/bindings/nvshmem.pxd +54 -0
- nvmath/device/__init__.py +23 -0
- nvmath/device/_deprecated.py +33 -0
- nvmath/device/caching.py +51 -0
- nvmath/device/common.py +131 -0
- nvmath/device/common_backend.py +125 -0
- nvmath/device/common_cuda.py +156 -0
- nvmath/device/common_mathdx.py +97 -0
- nvmath/device/common_numba.py +159 -0
- nvmath/device/common_opaque_tensor.py +128 -0
- nvmath/device/cublasdx.py +1085 -0
- nvmath/device/cublasdx_backend.py +552 -0
- nvmath/device/cublasdx_numba.py +528 -0
- nvmath/device/cufftdx.py +551 -0
- nvmath/device/cufftdx_backend.py +194 -0
- nvmath/device/cufftdx_numba.py +123 -0
- nvmath/device/curand_kernel.py +9147 -0
- nvmath/device/nvrtc.py +95 -0
- nvmath/device/patch.py +35 -0
- nvmath/device/random.py +417 -0
- nvmath/device/random_helpers.py +23 -0
- nvmath/device/random_states.py +189 -0
- nvmath/device/types.py +11 -0
- nvmath/device/vector_types_numba.py +203 -0
- nvmath/distributed/__init__.py +117 -0
- nvmath/distributed/_internal/__init__.py +0 -0
- nvmath/distributed/_internal/nvshmem.py +243 -0
- nvmath/distributed/_internal/tensor_ifc_cupy.py +111 -0
- nvmath/distributed/_internal/tensor_ifc_numpy.py +53 -0
- nvmath/distributed/_internal/tensor_ifc_torch.py +108 -0
- nvmath/distributed/_internal/tensor_wrapper.py +59 -0
- nvmath/distributed/_utils.py +152 -0
- nvmath/distributed/fft/__init__.py +6 -0
- nvmath/distributed/fft/_configuration.py +86 -0
- nvmath/distributed/fft/fft.py +1737 -0
- nvmath/distributed/reshape/__init__.py +6 -0
- nvmath/distributed/reshape/_configuration.py +39 -0
- nvmath/distributed/reshape/reshape.py +1249 -0
- nvmath/fft/__init__.py +7 -0
- nvmath/fft/_configuration.py +208 -0
- nvmath/fft/_exec_utils.py +116 -0
- nvmath/fft/_helpers.py +260 -0
- nvmath/fft/fft.py +2346 -0
- nvmath/internal/__init__.py +5 -0
- nvmath/internal/enum_utils.py +142 -0
- nvmath/internal/formatters.py +87 -0
- nvmath/internal/mem_limit.py +51 -0
- nvmath/internal/package_ifc.py +119 -0
- nvmath/internal/package_ifc_cuda.py +43 -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 +143 -0
- nvmath/internal/tensor_ifc_cupy.py +185 -0
- nvmath/internal/tensor_ifc_numpy.py +157 -0
- nvmath/internal/tensor_ifc_torch.py +115 -0
- nvmath/internal/tensor_wrapper.py +160 -0
- nvmath/internal/typemaps.py +154 -0
- nvmath/internal/utils.py +634 -0
- nvmath/linalg/__init__.py +11 -0
- nvmath/linalg/_internal/__init__.py +3 -0
- nvmath/linalg/_internal/algo_cap_ifc.py +86 -0
- nvmath/linalg/_internal/algo_config_ifc.py +87 -0
- nvmath/linalg/_internal/enum_to_tuples.py +64 -0
- nvmath/linalg/_internal/epilog_protocol.py +738 -0
- nvmath/linalg/_internal/matmul_desc_ifc.py +72 -0
- nvmath/linalg/_internal/matmul_pref_ifc.py +65 -0
- nvmath/linalg/_internal/matrix_layout_ifc.py +59 -0
- nvmath/linalg/_internal/typemaps.py +135 -0
- nvmath/linalg/_internal/utils.py +96 -0
- nvmath/linalg/advanced/__init__.py +8 -0
- nvmath/linalg/advanced/_algorithmmod.py +142 -0
- nvmath/linalg/advanced/_configuration.py +320 -0
- nvmath/linalg/advanced/helpers/__init__.py +5 -0
- nvmath/linalg/advanced/helpers/matmul.py +173 -0
- nvmath/linalg/advanced/matmulmod.py +2855 -0
- nvmath/memory.py +266 -0
- nvmath/sparse/__init__.py +18 -0
- nvmath/sparse/_internal/__init__.py +21 -0
- nvmath/sparse/_internal/common_utils.py +81 -0
- nvmath/sparse/_internal/cudss_config_ifc.py +584 -0
- nvmath/sparse/_internal/cudss_data_ifc.py +291 -0
- nvmath/sparse/_internal/cudss_utils.py +398 -0
- nvmath/sparse/_internal/sparse_csr_ifc.py +154 -0
- nvmath/sparse/_internal/sparse_format_helpers.py +88 -0
- nvmath/sparse/_internal/sparse_tensor_ifc.py +80 -0
- nvmath/sparse/advanced/__init__.py +7 -0
- nvmath/sparse/advanced/_configuration.py +150 -0
- nvmath/sparse/advanced/direct_solver.py +1705 -0
- nvmath_python-0.5.0.dist-info/METADATA +122 -0
- nvmath_python-0.5.0.dist-info/RECORD +174 -0
- nvmath_python-0.5.0.dist-info/WHEEL +5 -0
- nvmath_python-0.5.0.dist-info/licenses/LICENSE +177 -0
- nvmath_python-0.5.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
Interface to seamlessly use CSR tensors from different libraries.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations # allows typehint of class methods to return the self class
|
|
10
|
+
|
|
11
|
+
__all__ = ["CSRTensorHolder"]
|
|
12
|
+
|
|
13
|
+
from typing import Literal, TypeVar
|
|
14
|
+
|
|
15
|
+
from .sparse_tensor_ifc import SparseTensorHolder
|
|
16
|
+
from nvmath.internal import tensor_wrapper
|
|
17
|
+
from nvmath.internal.package_ifc import StreamHolder
|
|
18
|
+
from nvmath.internal.tensor_ifc import TensorHolder
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
"""
|
|
22
|
+
A generic type for the third-party CSRTensor which a CSRTensorHolder implementation wraps
|
|
23
|
+
around.
|
|
24
|
+
"""
|
|
25
|
+
CSRTensor = TypeVar("CSRTensor")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class CSRTensorHolder(SparseTensorHolder):
|
|
29
|
+
"""
|
|
30
|
+
A simple wrapper type for CSR sparse tensors to make the API package-agnostic. The
|
|
31
|
+
naming convention is sparse format name with the suffix "TensorHolder", which convention
|
|
32
|
+
is used in the sparse format helper.
|
|
33
|
+
|
|
34
|
+
Since the implementation is in terms of our dense tensor abstraction, package-specific
|
|
35
|
+
implementation is not needed.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
_format_name: str = "CSR"
|
|
39
|
+
|
|
40
|
+
def __init__(self, crow_indices, col_indices, values, *, attr_name_map=None, shape=None, tensor=None):
|
|
41
|
+
# tensor is the native tensor.
|
|
42
|
+
self.tensor = tensor
|
|
43
|
+
|
|
44
|
+
# attr_name_map is the canonical attribute name to package attribute name map.
|
|
45
|
+
# It is set when constructing from a tensor, otherwise it is None.
|
|
46
|
+
self._attr_name_map = attr_name_map
|
|
47
|
+
|
|
48
|
+
assert (shape is not None) ^ (tensor is not None), "Internal error."
|
|
49
|
+
|
|
50
|
+
if shape is not None:
|
|
51
|
+
self._shape = shape
|
|
52
|
+
else:
|
|
53
|
+
self._shape = tuple(tensor.shape)
|
|
54
|
+
|
|
55
|
+
# Wrap constituent dense tensors, if required.
|
|
56
|
+
if not isinstance(crow_indices, TensorHolder):
|
|
57
|
+
crow_indices = tensor_wrapper.wrap_operand(crow_indices)
|
|
58
|
+
|
|
59
|
+
if not isinstance(col_indices, TensorHolder):
|
|
60
|
+
col_indices = tensor_wrapper.wrap_operand(col_indices)
|
|
61
|
+
|
|
62
|
+
if not isinstance(values, TensorHolder):
|
|
63
|
+
values = tensor_wrapper.wrap_operand(values)
|
|
64
|
+
|
|
65
|
+
# The wrapped constituent dense tensors.
|
|
66
|
+
self._crow_indices = crow_indices
|
|
67
|
+
self._col_indices = col_indices
|
|
68
|
+
self._values = values
|
|
69
|
+
|
|
70
|
+
# Ensure constituent dense tensors are all on the same device.
|
|
71
|
+
device_ids = {d.device_id for d in (self._crow_indices, self._col_indices, self._values)}
|
|
72
|
+
message = f"Internal error: the arrays defining the sparse format aren't on the same device {device_ids}."
|
|
73
|
+
assert len(device_ids) == 1, message
|
|
74
|
+
self._device_id = device_ids.pop()
|
|
75
|
+
|
|
76
|
+
self._device = self._values.device
|
|
77
|
+
|
|
78
|
+
@classmethod
|
|
79
|
+
def create_from_tensor(cls, tensor, *, attr_name_map=None):
|
|
80
|
+
assert attr_name_map is not None, "Internal error."
|
|
81
|
+
|
|
82
|
+
# tensor is the native tensor.
|
|
83
|
+
crow_indices = attr_name_map["crow_indices"](tensor)
|
|
84
|
+
col_indices = attr_name_map["col_indices"](tensor)
|
|
85
|
+
values = attr_name_map["values"](tensor)
|
|
86
|
+
return CSRTensorHolder(crow_indices, col_indices, values, attr_name_map=attr_name_map, tensor=tensor)
|
|
87
|
+
|
|
88
|
+
@property
|
|
89
|
+
def attr_name_map(self):
|
|
90
|
+
return self._attr_name_map
|
|
91
|
+
|
|
92
|
+
@property
|
|
93
|
+
def device(self):
|
|
94
|
+
return self._device
|
|
95
|
+
|
|
96
|
+
@property
|
|
97
|
+
def device_id(self):
|
|
98
|
+
return self._device_id
|
|
99
|
+
|
|
100
|
+
@property
|
|
101
|
+
def dtype(self):
|
|
102
|
+
return self._values.dtype
|
|
103
|
+
|
|
104
|
+
@property
|
|
105
|
+
def index_type(self):
|
|
106
|
+
return self._crow_indices.dtype
|
|
107
|
+
|
|
108
|
+
@property
|
|
109
|
+
def format_name(self) -> str:
|
|
110
|
+
return CSRTensorHolder._format_name
|
|
111
|
+
|
|
112
|
+
@property
|
|
113
|
+
def num_dimensions(self):
|
|
114
|
+
return len(self._shape)
|
|
115
|
+
|
|
116
|
+
@property
|
|
117
|
+
def shape(self):
|
|
118
|
+
return self._shape
|
|
119
|
+
|
|
120
|
+
@property
|
|
121
|
+
def crow_indices(self) -> TensorHolder:
|
|
122
|
+
"""The TensorHolder object wrapping the crow_indices array."""
|
|
123
|
+
return self._crow_indices
|
|
124
|
+
|
|
125
|
+
@property
|
|
126
|
+
def col_indices(self) -> TensorHolder:
|
|
127
|
+
"""The TensorHolder object wrapping the col_indices array."""
|
|
128
|
+
return self._col_indices
|
|
129
|
+
|
|
130
|
+
@property
|
|
131
|
+
def values(self) -> TensorHolder:
|
|
132
|
+
"""The TensorHolder object wrapping the values array."""
|
|
133
|
+
return self._values
|
|
134
|
+
|
|
135
|
+
def to(self, device_id: int | Literal["cpu"], stream_holder: StreamHolder | None):
|
|
136
|
+
"""Copy the CSRTensor representation to a different device.
|
|
137
|
+
|
|
138
|
+
No copy is performed if the CSRTensor is already on the requested device.
|
|
139
|
+
"""
|
|
140
|
+
|
|
141
|
+
target_crow_indices = self.crow_indices.to(device_id=device_id, stream_holder=stream_holder)
|
|
142
|
+
target_col_indices = self.col_indices.to(device_id=device_id, stream_holder=stream_holder)
|
|
143
|
+
target_values = self.values.to(device_id=device_id, stream_holder=stream_holder)
|
|
144
|
+
|
|
145
|
+
return CSRTensorHolder(
|
|
146
|
+
target_crow_indices, target_col_indices, target_values, attr_name_map=self.attr_name_map, shape=self.shape
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
def copy_(self, src, stream_holder: StreamHolder | None) -> None:
|
|
150
|
+
"""Overwrite self.tensor (in-place) with a copy of src (CSRTensor)."""
|
|
151
|
+
|
|
152
|
+
self.crow_indices.copy_(src=src.crow_indices, stream_holder=stream_holder)
|
|
153
|
+
self.col_indices.copy_(src=src.col_indices, stream_holder=stream_holder)
|
|
154
|
+
self.values.copy_(src=src.values, stream_holder=stream_holder)
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
Package-agnostic interface for key sparse tensor attributes.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
__all__ = ["PACKAGE_HELPER_MAP", "CupySparseFormatHelper", "ScipySparseFormatHelper", "TorchSparseFormatHelper"]
|
|
10
|
+
|
|
11
|
+
from abc import ABC, abstractmethod
|
|
12
|
+
|
|
13
|
+
import re
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class SparseFormatHelper(ABC):
|
|
17
|
+
@staticmethod
|
|
18
|
+
@abstractmethod
|
|
19
|
+
def sparse_format_name(tensor):
|
|
20
|
+
raise NotImplementedError
|
|
21
|
+
|
|
22
|
+
# Attribute name map: canonical name <> package name.
|
|
23
|
+
# One for each named sparse format type.
|
|
24
|
+
@staticmethod
|
|
25
|
+
@abstractmethod
|
|
26
|
+
def csr_attribute_names():
|
|
27
|
+
raise NotImplementedError
|
|
28
|
+
|
|
29
|
+
# A ctor for each named sparse format type.
|
|
30
|
+
@staticmethod
|
|
31
|
+
@abstractmethod
|
|
32
|
+
def create_csr(shape, crow_indices, col_indices, values):
|
|
33
|
+
raise NotImplementedError
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class TorchSparseFormatHelper(SparseFormatHelper):
|
|
37
|
+
@staticmethod
|
|
38
|
+
def sparse_format_name(tensor):
|
|
39
|
+
name = re.sub(r"^torch\.sparse_", "", str(tensor.layout)).upper()
|
|
40
|
+
return name
|
|
41
|
+
|
|
42
|
+
@staticmethod
|
|
43
|
+
def csr_attribute_names():
|
|
44
|
+
return {
|
|
45
|
+
"crow_indices": lambda a: a.crow_indices(),
|
|
46
|
+
"col_indices": lambda a: a.col_indices(),
|
|
47
|
+
"values": lambda a: a.values(),
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@staticmethod
|
|
51
|
+
def create_csr(shape, crow_indices, col_indices, values):
|
|
52
|
+
# import torch
|
|
53
|
+
# return torch.sparse_csr_tensor(crow_indices.tensor, col_indices.tensor,
|
|
54
|
+
# values.tensor, shape, device=values.device_id)
|
|
55
|
+
raise NotImplementedError
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class CupySparseFormatHelper(SparseFormatHelper):
|
|
59
|
+
@staticmethod
|
|
60
|
+
def sparse_format_name(tensor):
|
|
61
|
+
name = re.sub(r"_(array|matrix)$", "", type(tensor).__name__).upper()
|
|
62
|
+
return name
|
|
63
|
+
|
|
64
|
+
@staticmethod
|
|
65
|
+
def csr_attribute_names():
|
|
66
|
+
return {"crow_indices": lambda a: a.indptr, "col_indices": lambda a: a.indices, "values": lambda a: a.data}
|
|
67
|
+
|
|
68
|
+
@staticmethod
|
|
69
|
+
def create_csr(shape, crow_indices, col_indices, values):
|
|
70
|
+
raise NotImplementedError
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class ScipySparseFormatHelper(SparseFormatHelper):
|
|
74
|
+
@staticmethod
|
|
75
|
+
def sparse_format_name(tensor):
|
|
76
|
+
name = re.sub(r"_(array|matrix)$", "", type(tensor).__name__).upper()
|
|
77
|
+
return name
|
|
78
|
+
|
|
79
|
+
@staticmethod
|
|
80
|
+
def csr_attribute_names():
|
|
81
|
+
return {"crow_indices": lambda a: a.indptr, "col_indices": lambda a: a.indices, "values": lambda a: a.data}
|
|
82
|
+
|
|
83
|
+
@staticmethod
|
|
84
|
+
def create_csr(shape, crow_indices, col_indices, values):
|
|
85
|
+
raise NotImplementedError
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
PACKAGE_HELPER_MAP = {"cupyx": CupySparseFormatHelper, "scipy": ScipySparseFormatHelper, "torch": TorchSparseFormatHelper}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
Interface to seamlessly use sparse tensors from different libraries.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations # allows typehint of class methods to return the self class
|
|
10
|
+
|
|
11
|
+
__all__ = ["SparseTensorHolder"]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
from abc import ABC, abstractmethod
|
|
15
|
+
from typing import Literal
|
|
16
|
+
|
|
17
|
+
from nvmath.internal.package_ifc import StreamHolder
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class SparseTensorHolder(ABC):
|
|
21
|
+
"""
|
|
22
|
+
A simple base type for attributes common to *all* sparse formats.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
@classmethod
|
|
26
|
+
@abstractmethod
|
|
27
|
+
def create_from_tensor(cls, attr_name_map, tensor):
|
|
28
|
+
raise NotImplementedError
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
@abstractmethod
|
|
32
|
+
def attr_name_map(self):
|
|
33
|
+
raise NotImplementedError
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
@abstractmethod
|
|
37
|
+
def device(self):
|
|
38
|
+
raise NotImplementedError
|
|
39
|
+
|
|
40
|
+
@property
|
|
41
|
+
@abstractmethod
|
|
42
|
+
def device_id(self):
|
|
43
|
+
raise NotImplementedError
|
|
44
|
+
|
|
45
|
+
@property
|
|
46
|
+
@abstractmethod
|
|
47
|
+
def dtype(self):
|
|
48
|
+
raise NotImplementedError
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
@abstractmethod
|
|
52
|
+
def index_type(self):
|
|
53
|
+
raise NotImplementedError
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
@abstractmethod
|
|
57
|
+
def format_name(self) -> str:
|
|
58
|
+
raise NotImplementedError
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
@abstractmethod
|
|
62
|
+
def num_dimensions(self):
|
|
63
|
+
raise NotImplementedError
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
@abstractmethod
|
|
67
|
+
def shape(self):
|
|
68
|
+
raise NotImplementedError
|
|
69
|
+
|
|
70
|
+
@abstractmethod
|
|
71
|
+
def to(self, device_id: int | Literal["cpu"], stream_holder: StreamHolder | None):
|
|
72
|
+
"""Copy the SparseTensor representation to a different device.
|
|
73
|
+
|
|
74
|
+
No copy is performed if the SparseTensor is already on the requested device.
|
|
75
|
+
"""
|
|
76
|
+
raise NotImplementedError
|
|
77
|
+
|
|
78
|
+
def copy_(self, src: SparseTensorHolder, stream_holder: StreamHolder | None) -> None:
|
|
79
|
+
"""Overwrite the sparse tensor (in-place) with a copy of src."""
|
|
80
|
+
raise NotImplementedError
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
from ._configuration import * # noqa: F403
|
|
6
|
+
from .direct_solver import * # noqa: F403
|
|
7
|
+
from .._internal.cudss_data_ifc import memory_estimates_dtype # noqa: F401
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"DirectSolverOptions",
|
|
7
|
+
"DirectSolverMatrixType",
|
|
8
|
+
"DirectSolverMatrixViewType",
|
|
9
|
+
"ExecutionCUDA",
|
|
10
|
+
"ExecutionHybrid",
|
|
11
|
+
"HybridMemoryModeOptions",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
from dataclasses import dataclass, field
|
|
16
|
+
from logging import Logger
|
|
17
|
+
from typing import ClassVar, Literal, TypeAlias
|
|
18
|
+
|
|
19
|
+
from nvmath.bindings import cudss
|
|
20
|
+
from nvmath.internal import mem_limit
|
|
21
|
+
|
|
22
|
+
DirectSolverMatrixType: TypeAlias = cudss.MatrixType
|
|
23
|
+
DirectSolverMatrixViewType: TypeAlias = cudss.MatrixViewType
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass
|
|
27
|
+
class HybridMemoryModeOptions:
|
|
28
|
+
"""
|
|
29
|
+
A data class for providing options related to the use of hybrid (CPU-GPU) memory to
|
|
30
|
+
those execution spaces that support it.
|
|
31
|
+
|
|
32
|
+
Attributes:
|
|
33
|
+
hybrid_memory_mode: If set to True, use CPU memory to store factors (default:
|
|
34
|
+
``False``). See :attr:`nvmath.bindings.cudss.ConfigParam.HYBRID_MODE`.
|
|
35
|
+
device_memory_limit: The maximum device memory available for execution. It can
|
|
36
|
+
be specified as a value (with optional suffix like K[iB], M[iB], G[iB]) or as a
|
|
37
|
+
percentage. The default is based on internal heuristics. See
|
|
38
|
+
:attr:`nvmath.bindings.cudss.ConfigParam.HYBRID_DEVICE_MEMORY_LIMIT`.
|
|
39
|
+
register_cuda_memory: Specify whether to register memory using
|
|
40
|
+
``cudaHostRegister()`` if hybrid memory mode is used. The default is
|
|
41
|
+
``True``. See
|
|
42
|
+
:attr:`nvmath.bindings.cudss.ConfigParam.USE_CUDA_REGISTER_MEMORY`.
|
|
43
|
+
|
|
44
|
+
See Also:
|
|
45
|
+
:class:`ExecutionHybrid`, :class:`DirectSolver`, :func:`direct_solver`.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
hybrid_memory_mode: bool = False
|
|
49
|
+
hybrid_device_memory_limit: int | str | None = None # Internal heuristic.
|
|
50
|
+
register_cuda_memory: bool = True
|
|
51
|
+
|
|
52
|
+
def __post_init__(self):
|
|
53
|
+
if self.hybrid_device_memory_limit is not None:
|
|
54
|
+
mem_limit.check_memory_str(self.hybrid_device_memory_limit, "hybrid device memory limit")
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@dataclass
|
|
58
|
+
class ExecutionCUDA:
|
|
59
|
+
"""
|
|
60
|
+
A data class for providing GPU execution options to the :class:`DirectSolver`
|
|
61
|
+
object and the wrapper function :func:`direct_solver`.
|
|
62
|
+
|
|
63
|
+
Attributes:
|
|
64
|
+
device_id: CUDA device ordinal (only used if the operand resides on the CPU). The
|
|
65
|
+
default value is 0.
|
|
66
|
+
hybrid_memory_mode_options: Options controlling the use of hybrid (CPU-GPU) memory
|
|
67
|
+
as an object of type :class:`HybridMemoryModeOptions` or a `dict`.
|
|
68
|
+
|
|
69
|
+
See Also:
|
|
70
|
+
:class:`ExecutionHybrid`, :class:`HybridMemoryModeOptions`, :class:`DirectSolver`,
|
|
71
|
+
:func:`direct_solver`.
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
name: ClassVar[Literal["cuda"]] = "cuda"
|
|
75
|
+
device_id: int = 0
|
|
76
|
+
hybrid_memory_mode_options: object = field(default_factory=HybridMemoryModeOptions)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@dataclass
|
|
80
|
+
class ExecutionHybrid:
|
|
81
|
+
"""
|
|
82
|
+
A data class for providing hybrid (CPU-GPU) execution options to the
|
|
83
|
+
:class:`DirectSolver` object and the wrapper function :func:`direct_solver`.
|
|
84
|
+
|
|
85
|
+
Attributes:
|
|
86
|
+
device_id: CUDA device ordinal (only used if the operand resides on the CPU). The
|
|
87
|
+
default value is 0.
|
|
88
|
+
num_threads: The number of CPU threads used to execute the plan.
|
|
89
|
+
If not specified, defaults to the number of CPU cores available to the process.
|
|
90
|
+
|
|
91
|
+
See Also:
|
|
92
|
+
:class:`ExecutionCUDA`, :class:`DirectSolver`, :func:`direct_solver`.
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
name: ClassVar[Literal["hybrid"]] = "hybrid"
|
|
96
|
+
device_id: int = 0
|
|
97
|
+
num_threads: int | None = None
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
# TODO: docstring
|
|
101
|
+
@dataclass
|
|
102
|
+
class DirectSolverOptions:
|
|
103
|
+
"""
|
|
104
|
+
A data class for providing options to the :class:`DirectSolver` object and the wrapper
|
|
105
|
+
function :func:`direct_solver`.
|
|
106
|
+
|
|
107
|
+
Attributes:
|
|
108
|
+
sparse_system_type (:class:`DirectSolverMatrixType`): The type of the sparse
|
|
109
|
+
system of equations (general, symmetric, symmetric positive definite, etc).
|
|
110
|
+
The default is ``DirectSolverMatrixType.GENERAL``.
|
|
111
|
+
|
|
112
|
+
sparse_system_view (:class:`DirectSolverMatrixViewType`): The desired view of the
|
|
113
|
+
sparse system of equations (full, upper, lower). The default is
|
|
114
|
+
``DirectSolverMatrixViewType.FULL``.
|
|
115
|
+
|
|
116
|
+
multithreading_lib: The location (full path) to the library implementing the
|
|
117
|
+
threading layer interface. **TODO**: link to docs and default pip path.
|
|
118
|
+
|
|
119
|
+
logger (logging.Logger): Python Logger object. The root logger will be used if a
|
|
120
|
+
logger object is not provided.
|
|
121
|
+
|
|
122
|
+
blocking: A flag specifying the behavior of the execution functions and methods,
|
|
123
|
+
such as :func:`direct_solver` and :meth:`DirectSolver.solve`.
|
|
124
|
+
When ``blocking`` is `True`, the execution methods do not return until the
|
|
125
|
+
operation is complete. When
|
|
126
|
+
``blocking`` is ``"auto"``, the methods return immediately when the input tensor
|
|
127
|
+
is on the GPU and ``execution`` is set to 'CUDA'. The execution methods always
|
|
128
|
+
block when the input tensor is on the CPU or ``execution`` is specified to 'CPU'
|
|
129
|
+
to ensure that the user doesn't inadvertently use the result before it becomes
|
|
130
|
+
available. The default is ``"auto"``.
|
|
131
|
+
|
|
132
|
+
handle: cuDSS library handle. A handle will be created if one is not provided.
|
|
133
|
+
|
|
134
|
+
See Also:
|
|
135
|
+
:class:`ExecutionCUDA`, :class:`ExecutionHybrid`, :class:`DirectSolver`, and
|
|
136
|
+
:func:`direct_solver`.
|
|
137
|
+
"""
|
|
138
|
+
|
|
139
|
+
sparse_system_type: int = DirectSolverMatrixType.GENERAL
|
|
140
|
+
sparse_system_view: int = DirectSolverMatrixViewType.FULL
|
|
141
|
+
multithreading_lib: str | None = None
|
|
142
|
+
logger: Logger | None = None
|
|
143
|
+
blocking: Literal[True, "auto"] = "auto"
|
|
144
|
+
handle: int | None = None
|
|
145
|
+
|
|
146
|
+
def __post_init__(self):
|
|
147
|
+
if self.blocking not in (True, "auto"):
|
|
148
|
+
raise ValueError("The value specified for 'blocking' must be either True or 'auto'.")
|
|
149
|
+
self.sparse_system_type = DirectSolverMatrixType(self.sparse_system_type)
|
|
150
|
+
self.sparse_system_view = DirectSolverMatrixViewType(self.sparse_system_view)
|