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,476 @@
|
|
|
1
|
+
# Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
This module overrides PyTorch tensors with the UST (for easy "injection").
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
__all__ = ["TorchUST", "prune_model", "reformat_model"]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
import numbers
|
|
13
|
+
from collections.abc import Callable
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
import numpy as np
|
|
17
|
+
import torch
|
|
18
|
+
import torch.nn.utils.prune as prune
|
|
19
|
+
|
|
20
|
+
from nvmath.sparse.generic import Matmul
|
|
21
|
+
from nvmath.sparse.ust._utils import Cache
|
|
22
|
+
from nvmath.sparse.ust.tensor import Tensor
|
|
23
|
+
|
|
24
|
+
_MATMUL_CACHE = Cache()
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _matmul(A, B, C_shape, transpose_a=False):
|
|
28
|
+
a = A.ust
|
|
29
|
+
b = Tensor.from_package(B)
|
|
30
|
+
|
|
31
|
+
vtp = a.dtype
|
|
32
|
+
itp = a.index_type
|
|
33
|
+
format_a = a.tensor_format.name
|
|
34
|
+
format_b = b.tensor_format.name
|
|
35
|
+
sizes = (tuple(a.extents), tuple(b.extents), C_shape)
|
|
36
|
+
|
|
37
|
+
# Lookup matmul. Also recycles the result tensor allocation.
|
|
38
|
+
key = (vtp, itp, format_a, format_b, transpose_a, sizes, A.stream, A.device)
|
|
39
|
+
mm = _MATMUL_CACHE.get(key)
|
|
40
|
+
if mm is None:
|
|
41
|
+
t = torch.zeros(C_shape, dtype=A.dtype, device=A.device)
|
|
42
|
+
c = Tensor.from_package(t)
|
|
43
|
+
# Or: options = {"codegen": True}
|
|
44
|
+
options = None
|
|
45
|
+
if transpose_a:
|
|
46
|
+
matrix_qualifiers_dtype = np.dtype([("is_transpose", "<i4"), ("is_conjugate", "<i4")])
|
|
47
|
+
qualifiers = np.zeros((3,), dtype=matrix_qualifiers_dtype)
|
|
48
|
+
qualifiers[0]["is_transpose"] = True
|
|
49
|
+
else:
|
|
50
|
+
qualifiers = None
|
|
51
|
+
mm = Matmul(a, b, c, beta=1.0, qualifiers=qualifiers, options=options)
|
|
52
|
+
mm.plan()
|
|
53
|
+
_MATMUL_CACHE[key] = (mm, t, c)
|
|
54
|
+
else:
|
|
55
|
+
mm, t, c = mm
|
|
56
|
+
t.zero_()
|
|
57
|
+
mm.reset_operands_unchecked(a=a, b=b, c=c)
|
|
58
|
+
mm.execute()
|
|
59
|
+
mm.release_operands()
|
|
60
|
+
|
|
61
|
+
return t # fast c.to_package()
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _ust_detach(func, types, args, kwargs) -> torch.Tensor:
|
|
65
|
+
assert len(args) == 1
|
|
66
|
+
self = args[0]
|
|
67
|
+
assert isinstance(self, TorchUST)
|
|
68
|
+
return self.__class__(
|
|
69
|
+
shape=self.shape,
|
|
70
|
+
device=self.device,
|
|
71
|
+
dtype=self.dtype,
|
|
72
|
+
layout=self.layout,
|
|
73
|
+
requires_grad=False,
|
|
74
|
+
ust=self.ust,
|
|
75
|
+
transposed=self.transposed,
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _ust_zeros_like(func, types, args, kwargs) -> torch.Tensor:
|
|
80
|
+
assert len(args) == 1
|
|
81
|
+
self = args[0]
|
|
82
|
+
assert isinstance(self, TorchUST)
|
|
83
|
+
return torch.zeros(self.shape, dtype=self.dtype, device=self.device)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def _ust_ones_like(func, types, args, kwargs) -> torch.Tensor:
|
|
87
|
+
assert len(args) == 1
|
|
88
|
+
self = args[0]
|
|
89
|
+
assert isinstance(self, TorchUST)
|
|
90
|
+
return torch.ones(self.shape, dtype=self.dtype, device=self.device)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _ust_empty_like(func, types, args, kwargs) -> torch.Tensor:
|
|
94
|
+
assert len(args) == 1
|
|
95
|
+
self = args[0]
|
|
96
|
+
assert isinstance(self, TorchUST)
|
|
97
|
+
return torch.empty(self.shape, dtype=self.dtype, device=self.device)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _ust_to_copy(func, types, args, kwargs) -> torch.Tensor:
|
|
101
|
+
assert len(args) == 1
|
|
102
|
+
self = args[0]
|
|
103
|
+
assert isinstance(self, TorchUST)
|
|
104
|
+
return self
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def _ust_t(func, types, args, kwargs) -> torch.Tensor:
|
|
108
|
+
assert len(args) == 1
|
|
109
|
+
self = args[0]
|
|
110
|
+
assert isinstance(self, TorchUST)
|
|
111
|
+
lshape = len(self.shape)
|
|
112
|
+
# TODO: self.requires_grad?
|
|
113
|
+
if lshape == 1:
|
|
114
|
+
return self.__class__(
|
|
115
|
+
shape=self.shape,
|
|
116
|
+
device=self.device,
|
|
117
|
+
dtype=self.dtype,
|
|
118
|
+
layout=self.layout,
|
|
119
|
+
requires_grad=False,
|
|
120
|
+
ust=self.ust,
|
|
121
|
+
transposed=False, # no impact on vector
|
|
122
|
+
)
|
|
123
|
+
elif lshape == 2:
|
|
124
|
+
return self.__class__(
|
|
125
|
+
shape=(self.shape[1], self.shape[0]), # type: ignore
|
|
126
|
+
device=self.device,
|
|
127
|
+
dtype=self.dtype,
|
|
128
|
+
layout=self.layout,
|
|
129
|
+
requires_grad=False,
|
|
130
|
+
ust=self.ust,
|
|
131
|
+
transposed=not self.transposed, # simply flip
|
|
132
|
+
)
|
|
133
|
+
raise NotImplementedError("`TorchUST` transpose: Unexpected operand")
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def _ust_permute(func, types, args, kwargs) -> torch.Tensor:
|
|
137
|
+
assert len(args) == 2
|
|
138
|
+
self, perm = args
|
|
139
|
+
assert isinstance(self, TorchUST)
|
|
140
|
+
if len(perm) == 1 or (len(perm) == 2 and perm[0] == 1 and perm[1] == 0):
|
|
141
|
+
return _ust_t(func, types, args[:-1], kwargs)
|
|
142
|
+
raise NotImplementedError("`TorchUST` transpose: Unexpected operand")
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def _ust_view(func, types, args, kwargs) -> torch.Tensor:
|
|
146
|
+
assert len(args) == 2
|
|
147
|
+
self, perm = args
|
|
148
|
+
raise NotImplementedError("`TorchUST` view: Unexpected operand")
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def _ust_dot_impl(A, B):
|
|
152
|
+
assert A.ndim == 1 and B.ndim == 1
|
|
153
|
+
if isinstance(A, TorchUST):
|
|
154
|
+
if isinstance(B, TorchUST):
|
|
155
|
+
raise NotImplementedError("`TorchUST` dot: Only one operand can be sparse")
|
|
156
|
+
# DOT a x b direct, can ignore A.transposed.
|
|
157
|
+
return _matmul(A, B, ())
|
|
158
|
+
elif isinstance(B, TorchUST):
|
|
159
|
+
# DOT a x b as b x a, can ignore B.transposed.
|
|
160
|
+
return _matmul(B, A, ())
|
|
161
|
+
raise NotImplementedError("`TorchUST` dot: Unexpected operands")
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def _ust_mv_impl(A, B):
|
|
165
|
+
assert A.ndim == 2 and B.ndim == 1
|
|
166
|
+
if isinstance(A, TorchUST):
|
|
167
|
+
if isinstance(B, TorchUST):
|
|
168
|
+
raise NotImplementedError("`TorchUST` mv: Only one operand can be sparse")
|
|
169
|
+
# MV A* x b direct.
|
|
170
|
+
return _matmul(A, B, (A.shape[0],), transpose_a=A.transposed)
|
|
171
|
+
elif isinstance(B, TorchUST):
|
|
172
|
+
# MV A x b as b x A^T, can ignore sparse vector B.transposed.
|
|
173
|
+
return _matmul(B, A.t(), (A.shape[0],))
|
|
174
|
+
raise NotImplementedError("`TorchUST` mv: Unexpected operands")
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def _ust_mm_impl(A, B):
|
|
178
|
+
if isinstance(A, TorchUST):
|
|
179
|
+
if isinstance(B, TorchUST):
|
|
180
|
+
raise NotImplementedError("`TorchUST` mm: Only one operand can be sparse")
|
|
181
|
+
# MM A* x B direct.
|
|
182
|
+
return _matmul(A, B, (*A.shape[:-1], B.shape[-1]), transpose_a=A.transposed)
|
|
183
|
+
elif isinstance(B, TorchUST):
|
|
184
|
+
assert A.ndim == 2 and B.ndim == 2
|
|
185
|
+
# MM A x B* as (B** x A^T)^T.
|
|
186
|
+
return _matmul(B, A.t(), (B.shape[1], A.shape[0]), transpose_a=not B.transposed).t()
|
|
187
|
+
raise NotImplementedError("`TorchUST` mm: Unexpected operands")
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def _ust_dot(func, types, args=(), kwargs=None) -> torch.Tensor:
|
|
191
|
+
assert len(args) == 2
|
|
192
|
+
A, B = args
|
|
193
|
+
C = _ust_dot_impl(A, B)
|
|
194
|
+
# print("ust_dot(", A.shape, ",", B.shape, ") ->", C.shape)
|
|
195
|
+
return C
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def _ust_mv(func, types, args=(), kwargs=None) -> torch.Tensor:
|
|
199
|
+
assert len(args) in [2, 3]
|
|
200
|
+
A, B = args[-2:]
|
|
201
|
+
C = _ust_mv_impl(A, B)
|
|
202
|
+
# print("ust_mv(", A.shape, ",", B.shape, ") ->", C.shape)
|
|
203
|
+
return C if len(args) == 2 else C + args[0]
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def _ust_mm(func, types, args=(), kwargs=None) -> torch.Tensor:
|
|
207
|
+
assert len(args) in [2, 3]
|
|
208
|
+
A, B = args[-2:]
|
|
209
|
+
# if A.shape[0] == 1:
|
|
210
|
+
# C = _ust_mv_impl(B.t(), A.squeeze(dim=0)).unsqueeze(dim=0)
|
|
211
|
+
# # print("ust_mm(", A.shape, ",", B.shape, ") ->", C.shape, "as vec")
|
|
212
|
+
# else:
|
|
213
|
+
C = _ust_mm_impl(A, B)
|
|
214
|
+
# print("ust_mm(", A.shape, ",", B.shape, ") ->", C.shape)
|
|
215
|
+
return C if len(args) == 2 else C + args[0]
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def _ust_linear(func, types, args=(), kwargs=None) -> torch.Tensor:
|
|
219
|
+
assert len(args) in [2, 3]
|
|
220
|
+
A, B = args[:2] # bias at end
|
|
221
|
+
if A.ndim == 1:
|
|
222
|
+
# Recognized matvec (e.g. single token inference).
|
|
223
|
+
C = _ust_mv_impl(B, A)
|
|
224
|
+
# print("ust_linear_1(", A.shape, ",", B.shape, ") ->", C.shape)
|
|
225
|
+
else:
|
|
226
|
+
# Cast into matmul (works for matvec as well).
|
|
227
|
+
shape = A.shape
|
|
228
|
+
A_2d = A.view(-1, shape[-1])
|
|
229
|
+
C = _ust_mm_impl(A_2d, B.t()).view(*shape[:-1], -1)
|
|
230
|
+
# print("ust_linear(", shape, "->", A_2d.shape, ",", B.shape, ") ->", C.shape)
|
|
231
|
+
return C if len(args) == 2 else C + args[2]
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def _ust_mul_inplace(func, types, args=(), kwargs=None) -> torch.Tensor:
|
|
235
|
+
assert len(args) == 2
|
|
236
|
+
A, B = args
|
|
237
|
+
# This only works for broadcasting scalar B because otherwise there
|
|
238
|
+
# is no direct match between values array (nse) and shape of B (all).
|
|
239
|
+
assert isinstance(A, TorchUST)
|
|
240
|
+
if not isinstance(B, numbers.Number):
|
|
241
|
+
raise NotImplementedError("`TorchUST` mul: Unexpected operands")
|
|
242
|
+
# print("ust_mul_inplace(", A.shape, ",", B, ")")
|
|
243
|
+
v = A.ust._val.tensor
|
|
244
|
+
v *= B # good performance
|
|
245
|
+
return A
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def _ust_addcdiv_inplace(func, types, args=(), kwargs=None) -> torch.Tensor:
|
|
249
|
+
assert len(args) == 3
|
|
250
|
+
A, B, C = args
|
|
251
|
+
assert isinstance(A, TorchUST)
|
|
252
|
+
assert not isinstance(B, TorchUST)
|
|
253
|
+
assert not isinstance(C, TorchUST)
|
|
254
|
+
# print("ust_addcdiv_inplace(", A.shape, ",", B.shape, ",", C.shape, ")", kwargs)
|
|
255
|
+
val = kwargs["value"]
|
|
256
|
+
if val is not None:
|
|
257
|
+
raise NotImplementedError("`TorchUST` no inplace addcdiv")
|
|
258
|
+
return A
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
def _ust_multi_head_attention(func, types, args=(), kwargs=None) -> torch.Tensor:
|
|
262
|
+
raise NotImplementedError("`TorchUST` no multi-head attention (try running in training mode)")
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
class TorchUST(torch.Tensor):
|
|
266
|
+
"""
|
|
267
|
+
This class wraps the universal sparse tensor as a :class:`torch.Tensor`.
|
|
268
|
+
|
|
269
|
+
The purpose of this class is to inject the UST into PyTorch models with minimal
|
|
270
|
+
code changes. Objects of the ``TorchUST`` class behave like PyTorch tensors, but
|
|
271
|
+
transparently use an UST implementation for the actual operations. A set of
|
|
272
|
+
operations commonly used in models is supported (otherwise a "can't perform"
|
|
273
|
+
message is prompted; please let us know of such cases, so we can extend the
|
|
274
|
+
supported set accordingly).
|
|
275
|
+
|
|
276
|
+
Examples:
|
|
277
|
+
>>> import torch
|
|
278
|
+
>>> from nvmath.sparse.ust.interfaces.torch_interface import TorchUST
|
|
279
|
+
|
|
280
|
+
Create two torch vectors.
|
|
281
|
+
|
|
282
|
+
>>> x = (1.0 + torch.arange(32)).cuda()
|
|
283
|
+
>>> y = (2.0 + torch.arange(32)).cuda()
|
|
284
|
+
|
|
285
|
+
Now perform a dot product operation.
|
|
286
|
+
|
|
287
|
+
>>> z = torch.dot(x, y)
|
|
288
|
+
|
|
289
|
+
Convert the first operand to UST.
|
|
290
|
+
|
|
291
|
+
>>> x = TorchUST.from_torch(x)
|
|
292
|
+
|
|
293
|
+
Now perform the same dot production operation. It transparently
|
|
294
|
+
uses the UST implementation!
|
|
295
|
+
|
|
296
|
+
>>> z = torch.dot(x, y)
|
|
297
|
+
"""
|
|
298
|
+
|
|
299
|
+
SPARSE_DISPATCH: dict[Callable, Callable]
|
|
300
|
+
|
|
301
|
+
ust: Tensor
|
|
302
|
+
transposed: bool
|
|
303
|
+
stream: int
|
|
304
|
+
|
|
305
|
+
__slots__ = ["ust", "transposed"]
|
|
306
|
+
|
|
307
|
+
@staticmethod
|
|
308
|
+
def __new__(
|
|
309
|
+
cls,
|
|
310
|
+
shape: torch.Size,
|
|
311
|
+
device: torch.device,
|
|
312
|
+
dtype: torch.dtype,
|
|
313
|
+
layout: torch.layout,
|
|
314
|
+
requires_grad: bool,
|
|
315
|
+
ust: Tensor,
|
|
316
|
+
transposed: bool,
|
|
317
|
+
):
|
|
318
|
+
# print("new", cls, "(", shape, ",", dtype, layout, ", transp =", transposed, ")")
|
|
319
|
+
cls._load_dispatch_table()
|
|
320
|
+
torch._dynamo.allow_in_graph(cls)
|
|
321
|
+
tensor = torch.Tensor._make_wrapper_subclass(
|
|
322
|
+
cls,
|
|
323
|
+
shape,
|
|
324
|
+
device=device,
|
|
325
|
+
dtype=dtype,
|
|
326
|
+
layout=torch.strided, # cheat
|
|
327
|
+
requires_grad=requires_grad,
|
|
328
|
+
)
|
|
329
|
+
tensor.ust = ust
|
|
330
|
+
tensor.transposed = transposed
|
|
331
|
+
tensor.stream = torch.cuda.current_stream().cuda_stream
|
|
332
|
+
return tensor
|
|
333
|
+
|
|
334
|
+
@classmethod
|
|
335
|
+
def from_torch(cls, original_tensor: torch.Tensor) -> "TorchUST":
|
|
336
|
+
"""Constructs a ``TorchUST`` from the given ``torch.Tensor``."""
|
|
337
|
+
ust = Tensor.from_package(original_tensor)
|
|
338
|
+
return cls(
|
|
339
|
+
original_tensor.shape,
|
|
340
|
+
device=original_tensor.device,
|
|
341
|
+
dtype=original_tensor.dtype,
|
|
342
|
+
layout=original_tensor.layout,
|
|
343
|
+
requires_grad=original_tensor.requires_grad,
|
|
344
|
+
ust=ust,
|
|
345
|
+
transposed=False,
|
|
346
|
+
)
|
|
347
|
+
|
|
348
|
+
@classmethod
|
|
349
|
+
def __torch_dispatch__(cls, func, types, args, kwargs) -> Any: # type: ignore[override]
|
|
350
|
+
if func._overloadpacket not in cls.SPARSE_DISPATCH:
|
|
351
|
+
raise NotImplementedError(
|
|
352
|
+
f"{cls.__name__} only supports a specific set of operations, "
|
|
353
|
+
f"can't perform requested op ({func.__name__} aka {func._overloadpacket})"
|
|
354
|
+
)
|
|
355
|
+
return cls.SPARSE_DISPATCH[func._overloadpacket](func, types, args, kwargs)
|
|
356
|
+
|
|
357
|
+
@classmethod
|
|
358
|
+
def _load_dispatch_table(cls, custom_dispatch_table=None) -> None:
|
|
359
|
+
"""
|
|
360
|
+
Loads the op overload sparse dispatch table for the current class.
|
|
361
|
+
"""
|
|
362
|
+
if getattr(cls, "SPARSE_DISPATCH", None) is None:
|
|
363
|
+
cls.SPARSE_DISPATCH = {
|
|
364
|
+
torch.ops.aten.detach: _ust_detach,
|
|
365
|
+
torch.ops.aten.zeros_like: _ust_zeros_like,
|
|
366
|
+
torch.ops.aten.ones_like: _ust_ones_like,
|
|
367
|
+
torch.ops.aten.empty_like: _ust_empty_like,
|
|
368
|
+
torch.ops.aten._to_copy: _ust_to_copy,
|
|
369
|
+
torch.ops.aten.t: _ust_t, # .t()
|
|
370
|
+
torch.ops.aten.permute: _ust_permute, # .T
|
|
371
|
+
torch.ops.aten.view: _ust_view,
|
|
372
|
+
torch.ops.aten.dot: _ust_dot,
|
|
373
|
+
torch.ops.aten.mv: _ust_mv,
|
|
374
|
+
torch.ops.aten.addmv: _ust_mv,
|
|
375
|
+
torch.ops.aten.mm: _ust_mm,
|
|
376
|
+
torch.ops.aten.addmm: _ust_mm,
|
|
377
|
+
torch.ops.aten.matmul: _ust_mm,
|
|
378
|
+
torch.ops.aten.linear: _ust_linear,
|
|
379
|
+
torch.ops.aten.bmm: _ust_mm,
|
|
380
|
+
torch.ops.aten.baddbmm: _ust_mm,
|
|
381
|
+
torch.ops.aten.mul_: _ust_mul_inplace,
|
|
382
|
+
torch.ops.aten.addcdiv_: _ust_addcdiv_inplace,
|
|
383
|
+
torch.ops.aten._native_multi_head_attention: _ust_multi_head_attention,
|
|
384
|
+
}
|
|
385
|
+
if custom_dispatch_table is not None:
|
|
386
|
+
cls.SPARSE_DISPATCH.update(custom_dispatch_table)
|
|
387
|
+
|
|
388
|
+
def __str__(self):
|
|
389
|
+
return self.ust.__str__()
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
def prune_model(model, *, local=True, amount=0.5):
|
|
393
|
+
"""
|
|
394
|
+
This is a convenience wrapper that uses the framework :mod:`torch.nn.utils.prune`
|
|
395
|
+
to prune all the weights of linear layers in a model either locally (per layer)
|
|
396
|
+
or globally (over all layers) with the given amount.
|
|
397
|
+
|
|
398
|
+
Args:
|
|
399
|
+
model: the model to be pruned
|
|
400
|
+
local: local per layer pruning if True, otherwise global over all layers
|
|
401
|
+
amount: amount of weights to be dropped (e.g. 0.50 drops 50%)
|
|
402
|
+
"""
|
|
403
|
+
# Local pruning.
|
|
404
|
+
if local:
|
|
405
|
+
for module in model.modules():
|
|
406
|
+
if isinstance(module, torch.nn.Linear):
|
|
407
|
+
prune.l1_unstructured(module, name="weight", amount=amount)
|
|
408
|
+
return
|
|
409
|
+
# Global pruning.
|
|
410
|
+
parameters_to_prune = tuple([(module, "weight") for module in model.modules() if isinstance(module, torch.nn.Linear)])
|
|
411
|
+
prune.global_unstructured(
|
|
412
|
+
parameters_to_prune,
|
|
413
|
+
pruning_method=prune.L1Unstructured,
|
|
414
|
+
amount=amount,
|
|
415
|
+
)
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
def reformat_model(model, *, func=None):
|
|
419
|
+
"""
|
|
420
|
+
This function potentially converts the linear weights in a model into UST format.
|
|
421
|
+
If ``func`` is None, all weights are unconditionally converted into the UST COO format
|
|
422
|
+
(stress testing the system with exactly the same weights but using sparse operations).
|
|
423
|
+
If a user-defined function ``func=reformat`` is given, this method is applied to every
|
|
424
|
+
weight and replaces the parameter only if the function returns not None.
|
|
425
|
+
|
|
426
|
+
Args:
|
|
427
|
+
model: the model to be reformatted
|
|
428
|
+
func: if set, user-defined reformatting function
|
|
429
|
+
|
|
430
|
+
Examples:
|
|
431
|
+
>>> import torch
|
|
432
|
+
>>> from nvmath.sparse.ust.interfaces.torch_interface import TorchUST
|
|
433
|
+
|
|
434
|
+
Inside the ``reformat`` method, inspect the weight sparsity (note that we
|
|
435
|
+
could even prune here, but it is more common to rely on other pruning
|
|
436
|
+
frameworks like ``torch.nn.utils.prune`` in combination with fine-tuning
|
|
437
|
+
for accuracy).
|
|
438
|
+
|
|
439
|
+
If the condition is met, pick a suitable format for ``weight`` and then
|
|
440
|
+
return ``TorchUST.from_torch(weight)``. Otherwise, just return ``None``.
|
|
441
|
+
|
|
442
|
+
>>> def reformat(weight):
|
|
443
|
+
... nel = weight.numel()
|
|
444
|
+
... nnz = torch.count_nonzero(weight)
|
|
445
|
+
... sparsity = (1.0 - float(nnz) / float(nel)) * 100.0
|
|
446
|
+
... if sparsity >= sparse_threshold:
|
|
447
|
+
... # TODO: Pick suitable format for weight
|
|
448
|
+
... return TorchUST.from_torch(weight)
|
|
449
|
+
... return None
|
|
450
|
+
|
|
451
|
+
This approach enables experimenting with novel formats to speedup
|
|
452
|
+
sparsified models during inference by simply calling the method
|
|
453
|
+
``ust.reformat_model(model, func=reformat)``.
|
|
454
|
+
No source code changes inside the model are required! If used during
|
|
455
|
+
training, always make sure to construct the optimizer (by calling e.g.
|
|
456
|
+
``torch.optim.Adam(model.parameters(), lr=0.001)``)
|
|
457
|
+
after the reformatting method call, so that the new parameters will
|
|
458
|
+
be involved in the optimizer steps.
|
|
459
|
+
"""
|
|
460
|
+
for name, module in model.named_modules():
|
|
461
|
+
if isinstance(module, torch.nn.Linear):
|
|
462
|
+
# Make any pruning permanent prior to reformatting
|
|
463
|
+
# (this is required to get a proper weight matrix).
|
|
464
|
+
if prune.is_pruned(module):
|
|
465
|
+
print(f"Making pruning in {name} permanent prior to reformatting")
|
|
466
|
+
prune.remove(module, name="weight")
|
|
467
|
+
|
|
468
|
+
# Apply unconditional reformatting into COO if func is None.
|
|
469
|
+
# Otherwise, apply the user-defined function.
|
|
470
|
+
if func is None:
|
|
471
|
+
U = TorchUST.from_torch(module.weight.data.to_sparse())
|
|
472
|
+
module.weight = torch.nn.Parameter(U)
|
|
473
|
+
else:
|
|
474
|
+
U = func(module.weight.data)
|
|
475
|
+
if U is not None:
|
|
476
|
+
module.weight = torch.nn.Parameter(U)
|