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
nvmath/device/common.py
ADDED
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
# Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
import importlib.util
|
|
6
|
+
import os
|
|
7
|
+
import tempfile
|
|
8
|
+
from abc import abstractmethod
|
|
9
|
+
from collections.abc import Sequence
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
import numpy as np
|
|
13
|
+
|
|
14
|
+
from .common_cuda import MAX_SUPPORTED_CC, MIN_SUPPORTED_CC, CodeType, ComputeCapability, get_current_device_cc
|
|
15
|
+
|
|
16
|
+
_HAS_NUMBA = importlib.util.find_spec("numba.cuda") is not None
|
|
17
|
+
_HAS_NUMBA_CUDA_MLIR = importlib.util.find_spec("numba_cuda_mlir") is not None
|
|
18
|
+
|
|
19
|
+
__all__ = [
|
|
20
|
+
"make_tensor",
|
|
21
|
+
"make_fragment_like",
|
|
22
|
+
"OpaqueTensor",
|
|
23
|
+
"Layout",
|
|
24
|
+
"axpby",
|
|
25
|
+
"copy",
|
|
26
|
+
"copy_fragment",
|
|
27
|
+
"clear",
|
|
28
|
+
"copy_wait",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
SHARED_DEVICE_DOCSTRINGS = {
|
|
32
|
+
"precision": """\
|
|
33
|
+
The computation precision specified as a numpy float dtype, currently supports ``numpy.float16``, ``numpy.float32`` and
|
|
34
|
+
``numpy.float64``.""".replace("\n", " "),
|
|
35
|
+
#
|
|
36
|
+
"code_type": "The target GPU code and compute-capability.",
|
|
37
|
+
"sm": "Target mathdx compute-capability.",
|
|
38
|
+
#
|
|
39
|
+
"execution": "A string specifying the execution method, can be ``'Block'`` or ``'Thread'``.",
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# TODO: maybe pre-compile regular expression
|
|
44
|
+
def make_binary_tempfile(content, suffix: str) -> tempfile._TemporaryFileWrapper:
|
|
45
|
+
"""Write `content` to a temporary file with the given `suffix`.
|
|
46
|
+
|
|
47
|
+
A closed file object returned; it is the user's responsibility to delete the file when
|
|
48
|
+
finished.
|
|
49
|
+
|
|
50
|
+
.. seealso:: :py:func:`delete_binary_tempfiles`
|
|
51
|
+
|
|
52
|
+
"""
|
|
53
|
+
with tempfile.NamedTemporaryFile(mode="w+b", suffix=suffix, delete=False) as tmp:
|
|
54
|
+
tmp.write(content)
|
|
55
|
+
tmp.flush()
|
|
56
|
+
return tmp
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def delete_binary_tempfiles(filenames: list[str]):
|
|
60
|
+
for name in filenames:
|
|
61
|
+
if os.path.isfile(name):
|
|
62
|
+
os.remove(name)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def check_in(name, value, coll, format="{name} must be in {coll_str} ; got {name} = {value}"):
|
|
66
|
+
if value not in coll:
|
|
67
|
+
coll_str = ", ".join(f'"{t}"' for t in coll)
|
|
68
|
+
msg = format.format(name=name, value=value, coll_str=coll_str)
|
|
69
|
+
raise ValueError(msg)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def check_not_in(name, value, coll, format="{name} must not be any of these values: {coll_str} ; got {name} = {value}"):
|
|
73
|
+
if value in coll:
|
|
74
|
+
coll_str = ", ".join(f'"{t}"' for t in coll)
|
|
75
|
+
msg = format.format(name=name, value=value, coll_str=coll_str)
|
|
76
|
+
raise ValueError(msg)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def check_contains(coll, key):
|
|
80
|
+
check_in("", key, coll, "missing required key {value!r}; got keys {coll_str}")
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def parse_sm(sm: Any) -> ComputeCapability:
|
|
84
|
+
if sm is None:
|
|
85
|
+
sm = get_current_device_cc()
|
|
86
|
+
else:
|
|
87
|
+
if not isinstance(sm, ComputeCapability) and not isinstance(sm, int):
|
|
88
|
+
raise ValueError(f"sm should be a ComputeCapability or an int; got sm = {sm}")
|
|
89
|
+
if isinstance(sm, int):
|
|
90
|
+
sm = ComputeCapability(sm // 10, sm % 10)
|
|
91
|
+
|
|
92
|
+
return sm
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def check_sm(sm, library_name: str, var_name: str = "sm"):
|
|
96
|
+
if not isinstance(sm, ComputeCapability):
|
|
97
|
+
raise ValueError(f"{var_name} should be an instance of ComputeCapability ; got {var_name} = {sm}")
|
|
98
|
+
if sm < MIN_SUPPORTED_CC:
|
|
99
|
+
raise RuntimeError(f"Minimum compute capability {MIN_SUPPORTED_CC} is required by {library_name}, got {sm}")
|
|
100
|
+
if sm > MAX_SUPPORTED_CC:
|
|
101
|
+
raise RuntimeError(f"The maximum compute capability currently supported by device APIs is {MAX_SUPPORTED_CC}, got {sm}")
|
|
102
|
+
if sm.minor < 0:
|
|
103
|
+
raise ValueError(f"{var_name}.minor must be >= 0 ; got {var_name}.minor = {sm.minor}")
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def parse_code_type(code_type: Any) -> CodeType:
|
|
107
|
+
if not isinstance(code_type, Sequence) or len(code_type) != 2:
|
|
108
|
+
raise ValueError(f"code_type should be an instance of CodeType or a 2-tuple ; got code_type = {code_type}")
|
|
109
|
+
|
|
110
|
+
return CodeType(code_type[0], ComputeCapability(*code_type[1]))
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def check_code_type(code_type, library_name):
|
|
114
|
+
if not isinstance(code_type, CodeType):
|
|
115
|
+
raise ValueError(f"code_type should be an instance of CodeType ; got code_type = {code_type}")
|
|
116
|
+
check_sm(code_type.cc, library_name, "code_type.cc")
|
|
117
|
+
check_in("code_type.kind", code_type.kind, ["lto"])
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def pad_or_truncate(list, target_len):
|
|
121
|
+
return list[:target_len] + [0] * (target_len - len(list))
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class Layout:
|
|
125
|
+
"""
|
|
126
|
+
Layout for the :py:class:`nvmath.device.OpaqueTensor`.
|
|
127
|
+
|
|
128
|
+
.. note:: Do not create directly, use appropriate method from
|
|
129
|
+
:py:class:`nvmath.device.Matmul`. Refer to
|
|
130
|
+
:cublasdx_doc:`api/other_tensors.html#imported-tensor-utilities`
|
|
131
|
+
for guidance on which method to use.
|
|
132
|
+
"""
|
|
133
|
+
|
|
134
|
+
def __init__(self):
|
|
135
|
+
raise RuntimeError("Layout should not be called directly.")
|
|
136
|
+
|
|
137
|
+
@property
|
|
138
|
+
@abstractmethod
|
|
139
|
+
def size(self) -> int:
|
|
140
|
+
"""
|
|
141
|
+
Number of valid elements in a tensor. This is simply a product of all
|
|
142
|
+
shape dimensions.
|
|
143
|
+
|
|
144
|
+
Refer to the cuBLASDx documentation for more details on how to use this attribute:
|
|
145
|
+
:cublasdx_doc:`api/other_tensors.html#imported-tensor-utilities`
|
|
146
|
+
"""
|
|
147
|
+
pass
|
|
148
|
+
|
|
149
|
+
@property
|
|
150
|
+
@abstractmethod
|
|
151
|
+
def cosize(self) -> int:
|
|
152
|
+
"""
|
|
153
|
+
Returns a distance from last element of a tensor to its first element.
|
|
154
|
+
It describes how many elements the argument layout spans.
|
|
155
|
+
|
|
156
|
+
Refer to the cuBLASDx documentation for more details on how to use this attribute:
|
|
157
|
+
:cublasdx_doc:`api/other_tensors.html#imported-tensor-utilities`
|
|
158
|
+
"""
|
|
159
|
+
pass
|
|
160
|
+
|
|
161
|
+
@property
|
|
162
|
+
@abstractmethod
|
|
163
|
+
def alignment(self) -> int:
|
|
164
|
+
"""
|
|
165
|
+
Returns the required alignment (in bytes) for the tensor data buffer.
|
|
166
|
+
|
|
167
|
+
Refer to the cuBLASDx documentation for more details on how to use this attribute:
|
|
168
|
+
:cublasdx_doc:`api/other_tensors.html#imported-tensor-utilities`
|
|
169
|
+
"""
|
|
170
|
+
pass
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
class OpaqueTensor:
|
|
174
|
+
"""
|
|
175
|
+
Abstraction over the cuBLASDx tensor type (an alias of the CuTe tensor type).
|
|
176
|
+
The CuTe tensor layout is powerful and supports layouts not provided by NumPy,
|
|
177
|
+
so this is a bridge to add this functionality to Python.
|
|
178
|
+
|
|
179
|
+
.. note:: Do not create directly, use :py:func:`nvmath.device.make_tensor`.
|
|
180
|
+
|
|
181
|
+
Refer to the cuBLASDx documentation for more details on how to use this class:
|
|
182
|
+
:cublasdx_doc:`api/other_tensors.html#tensors`
|
|
183
|
+
"""
|
|
184
|
+
|
|
185
|
+
buffer: np.ndarray
|
|
186
|
+
layout: Layout
|
|
187
|
+
leading_dimension: int | None
|
|
188
|
+
|
|
189
|
+
def __init__(self, *args):
|
|
190
|
+
raise RuntimeError("OpaqueTensor should not be called directly outside of a jitted kernel.")
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def make_tensor(array: np.ndarray, layout: Layout) -> OpaqueTensor:
|
|
194
|
+
"""
|
|
195
|
+
make_tensor is a helper function for creating
|
|
196
|
+
:py:class:`nvmath.device.OpaqueTensor` objects.
|
|
197
|
+
|
|
198
|
+
Args:
|
|
199
|
+
array (np.ndarray): The input array to be wrapped as an OpaqueTensor.
|
|
200
|
+
layout (Layout): The layout of the tensor, which describes how the data is
|
|
201
|
+
organized in memory.
|
|
202
|
+
|
|
203
|
+
Refer to the cuBLASDx documentation for more details on how to use this function:
|
|
204
|
+
:cublasdx_doc:`api/other_tensors.html#create-tensor-other-label`
|
|
205
|
+
"""
|
|
206
|
+
raise RuntimeError("make_tensor should not be called directly outside of a jitted kernel.")
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def make_fragment_like(tensor: OpaqueTensor, dtype) -> OpaqueTensor:
|
|
210
|
+
"""
|
|
211
|
+
make_fragment_like is a helper function for creating register fragments with
|
|
212
|
+
the same layout as input tensor, but different dtype.
|
|
213
|
+
|
|
214
|
+
Args:
|
|
215
|
+
tensor (OpaqueTensor): The input tensor to be used as a template for the fragment.
|
|
216
|
+
dtype: The data type of the fragment to be created.
|
|
217
|
+
|
|
218
|
+
Refer to the cuBLASDx documentation for more details on how to use this function:
|
|
219
|
+
:cublasdx_doc:`api/other_tensors.html#imported-tensor-utilities`
|
|
220
|
+
"""
|
|
221
|
+
raise RuntimeError("make_fragment_like should not be called directly outside of a jitted kernel.")
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def axpby(alpha: float, x_tensor: OpaqueTensor, beta: float, y_tensor: OpaqueTensor) -> None:
|
|
225
|
+
"""
|
|
226
|
+
AXPBY operation: y = alpha * x + beta * y
|
|
227
|
+
|
|
228
|
+
Args:
|
|
229
|
+
alpha (float): Scalar multiplier for x_tensor.
|
|
230
|
+
x_tensor (OpaqueTensor): Input tensor x.
|
|
231
|
+
beta (float): Scalar multiplier for y_tensor.
|
|
232
|
+
y_tensor (OpaqueTensor): Input/output tensor y, which will be updated
|
|
233
|
+
with the result.
|
|
234
|
+
|
|
235
|
+
Refer to the cuBLASDx documentation for more details on how to use this function:
|
|
236
|
+
:cublasdx_doc:`api/other_tensors.html#imported-tensor-utilities`
|
|
237
|
+
"""
|
|
238
|
+
raise RuntimeError("axpby should not be called directly outside of a jitted kernel.")
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def copy(src: OpaqueTensor, dst: OpaqueTensor, alignment=None):
|
|
242
|
+
"""
|
|
243
|
+
Copies data from the source tensor to the destination tensor.
|
|
244
|
+
|
|
245
|
+
Args:
|
|
246
|
+
src (OpaqueTensor): The source tensor to copy from.
|
|
247
|
+
dst (OpaqueTensor): The destination tensor to copy to.
|
|
248
|
+
alignment (int, optional): The alignment (in bytes) for the copy operation.
|
|
249
|
+
|
|
250
|
+
Refer to the cuBLASDx documentation for more details on how to use this function:
|
|
251
|
+
:cublasdx_doc:`api/other_tensors.html#cooperative-global-shared-copying`
|
|
252
|
+
"""
|
|
253
|
+
raise RuntimeError("copy should not be called directly outside of a jitted kernel.")
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def copy_fragment(src: OpaqueTensor, dst: OpaqueTensor, alignment=None):
|
|
257
|
+
"""
|
|
258
|
+
A bidirectional copying method to copy data between register fragments and
|
|
259
|
+
global memory tensors.
|
|
260
|
+
|
|
261
|
+
Args:
|
|
262
|
+
src (OpaqueTensor): The source tensor to copy from.
|
|
263
|
+
dst (OpaqueTensor): The destination tensor to copy to.
|
|
264
|
+
alignment (int, optional): The alignment (in bytes) for the copy operation.
|
|
265
|
+
|
|
266
|
+
Refer to the cuBLASDx documentation for more details on how to use this function:
|
|
267
|
+
:cublasdx_doc:`api/other_tensors.html#copying-registers-tensors`
|
|
268
|
+
"""
|
|
269
|
+
raise RuntimeError("copy_fragment should not be called directly outside of a jitted kernel.")
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def clear(arr: OpaqueTensor):
|
|
273
|
+
"""
|
|
274
|
+
Clears the contents of the given tensor by setting all elements to zero.
|
|
275
|
+
|
|
276
|
+
Args:
|
|
277
|
+
arr (OpaqueTensor): The tensor to be cleared.
|
|
278
|
+
|
|
279
|
+
Refer to the cuBLASDx documentation for more details on how to use this function:
|
|
280
|
+
:cublasdx_doc:`api/other_tensors.html#imported-tensor-utilities`
|
|
281
|
+
"""
|
|
282
|
+
raise RuntimeError("clear should not be called directly outside of a jitted kernel.")
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def copy_wait():
|
|
286
|
+
"""
|
|
287
|
+
Creates a synchronization point. It has to be called after :py:func:`nvmath.device.copy`
|
|
288
|
+
to ensure that the copy operation has completed before any subsequent
|
|
289
|
+
operations are executed.
|
|
290
|
+
|
|
291
|
+
Refer to the cuBLASDx documentation for more details on how to use this function:
|
|
292
|
+
:cublasdx_doc:`api/other_tensors.html#cooperative-global-shared-copying`
|
|
293
|
+
"""
|
|
294
|
+
raise RuntimeError("copy_wait should not be called directly outside of a jitted kernel.")
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
def check_positive_integer_sequence(arg, arg_name, min_len, max_len):
|
|
298
|
+
if not isinstance(arg, Sequence):
|
|
299
|
+
raise ValueError(f'Parameter "{arg_name}" must be a sequence. Got: {type(arg).__name__}.')
|
|
300
|
+
|
|
301
|
+
for i, x in enumerate(arg):
|
|
302
|
+
if not isinstance(x, (int, np.integer)):
|
|
303
|
+
raise ValueError(
|
|
304
|
+
f'Parameter "{arg_name}" must be a sequence of positive integers. '
|
|
305
|
+
+ f"Element {arg_name}[{i}] is {type(x).__name__}."
|
|
306
|
+
)
|
|
307
|
+
if x <= 0:
|
|
308
|
+
raise ValueError(f'Parameter "{arg_name}" values must be positive integers. Got {arg_name}[{i}] = {x}.')
|
|
309
|
+
|
|
310
|
+
if min_len == max_len:
|
|
311
|
+
if len(arg) != min_len:
|
|
312
|
+
raise ValueError(f'Parameter "{arg_name}" must be a sequence of length {min_len}. Got length: {len(arg)}.')
|
|
313
|
+
else:
|
|
314
|
+
if len(arg) > max_len or len(arg) < min_len:
|
|
315
|
+
raise ValueError(f'Parameter "{arg_name}" must define {min_len} to {max_len} values. Got {len(arg)} value(s).')
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
import weakref
|
|
6
|
+
from collections.abc import Callable
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
|
|
10
|
+
from nvmath.bindings import mathdx
|
|
11
|
+
from nvmath.device.common_cuda import ComputeCapability, ISAVersion
|
|
12
|
+
|
|
13
|
+
from .types import complex32, complex64, complex128, half2, half4
|
|
14
|
+
|
|
15
|
+
MATHDX_TYPES_TO_NP = {
|
|
16
|
+
mathdx.CommondxValueType.R_16F: np.float16,
|
|
17
|
+
mathdx.CommondxValueType.R_16F2: half2,
|
|
18
|
+
mathdx.CommondxValueType.R_32F: np.float32,
|
|
19
|
+
mathdx.CommondxValueType.R_64F: np.float64,
|
|
20
|
+
mathdx.CommondxValueType.C_16F: complex32,
|
|
21
|
+
mathdx.CommondxValueType.C_16F2: half4,
|
|
22
|
+
mathdx.CommondxValueType.C_32F: complex64,
|
|
23
|
+
mathdx.CommondxValueType.C_64F: complex128,
|
|
24
|
+
mathdx.CommondxValueType.R_8I: np.int8,
|
|
25
|
+
mathdx.CommondxValueType.R_16I: np.int16,
|
|
26
|
+
mathdx.CommondxValueType.R_32I: np.int32,
|
|
27
|
+
mathdx.CommondxValueType.R_64I: np.int64,
|
|
28
|
+
mathdx.CommondxValueType.R_8UI: np.uint8,
|
|
29
|
+
mathdx.CommondxValueType.R_16UI: np.uint16,
|
|
30
|
+
mathdx.CommondxValueType.R_32UI: np.uint32,
|
|
31
|
+
mathdx.CommondxValueType.R_64UI: np.uint64,
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
NP_TYPES_TO_MATHDX_TYPES = {np_type: mathdx_type for mathdx_type, np_type in MATHDX_TYPES_TO_NP.items()}
|
|
36
|
+
|
|
37
|
+
NP_TYPES_TO_MATHDX_PRECISION = {
|
|
38
|
+
np.float16: mathdx.CommondxPrecision.F16,
|
|
39
|
+
np.float32: mathdx.CommondxPrecision.F32,
|
|
40
|
+
np.float64: mathdx.CommondxPrecision.F64,
|
|
41
|
+
np.int8: mathdx.CommondxPrecision.I8,
|
|
42
|
+
np.int16: mathdx.CommondxPrecision.I16,
|
|
43
|
+
np.int32: mathdx.CommondxPrecision.I32,
|
|
44
|
+
np.int64: mathdx.CommondxPrecision.I64,
|
|
45
|
+
np.uint8: mathdx.CommondxPrecision.UI8,
|
|
46
|
+
np.uint16: mathdx.CommondxPrecision.UI16,
|
|
47
|
+
np.uint32: mathdx.CommondxPrecision.UI32,
|
|
48
|
+
np.uint64: mathdx.CommondxPrecision.UI64,
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
EXECUTION_STR_TO_MATHDX = {
|
|
52
|
+
"Block": mathdx.CommondxExecution.BLOCK,
|
|
53
|
+
"Thread": mathdx.CommondxExecution.THREAD,
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
NVARG_GEN_OPT_LTO = "-gen-opt-lto"
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class DescriptorWrapper:
|
|
60
|
+
"""
|
|
61
|
+
A smart pointer to a descriptor.
|
|
62
|
+
|
|
63
|
+
Lives as long as we need the descriptor (due to lru cache usage). Once the
|
|
64
|
+
descriptor is no longer needed/cached, it will trigger proper resource
|
|
65
|
+
deallocation.
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
def __init__(self, descriptor, destructor):
|
|
69
|
+
self.descriptor = descriptor
|
|
70
|
+
self._destructor = destructor
|
|
71
|
+
if destructor is not None:
|
|
72
|
+
weakref.finalize(self, self._destructor, self.descriptor)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def get_lto(code_descriptor: int) -> bytes:
|
|
76
|
+
"""Get lto binary from the mathdx common code descriptor."""
|
|
77
|
+
lto_size = mathdx.commondx_get_code_ltoir_size(code_descriptor)
|
|
78
|
+
|
|
79
|
+
lto_fn = bytearray(lto_size)
|
|
80
|
+
mathdx.commondx_get_code_ltoir(code_descriptor, lto_size, lto_fn)
|
|
81
|
+
return bytes(lto_fn)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def get_isa_version(code_descriptor: int) -> ISAVersion:
|
|
85
|
+
"""Parse isa version from the mathdx common code descriptor."""
|
|
86
|
+
isa = mathdx.commondx_get_code_option_int64(code_descriptor, mathdx.CommondxOption.CODE_ISA)
|
|
87
|
+
return ISAVersion.from_integer(isa)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def build_get_int_traits(get_trait_int64s: Callable[[int, int, int, int], int]):
|
|
91
|
+
"""Generate function that returns mathdx tuple of int traits."""
|
|
92
|
+
|
|
93
|
+
def get_int_traits(handle: int, trait_type: int, size: int) -> tuple:
|
|
94
|
+
int_buffer = np.zeros(size, np.int64)
|
|
95
|
+
get_trait_int64s(handle, trait_type, size, int_buffer.ctypes.data)
|
|
96
|
+
return tuple(map(int, int_buffer))
|
|
97
|
+
|
|
98
|
+
return get_int_traits
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def build_get_str_trait(
|
|
102
|
+
get_trait_str_size: Callable[[int, int], int],
|
|
103
|
+
get_trait_str: Callable[[int, int, int, bytearray], bytearray],
|
|
104
|
+
):
|
|
105
|
+
"""Generate function that returns mathdx string trait."""
|
|
106
|
+
|
|
107
|
+
def get_str_trait(handle: int, trait_type: int) -> str:
|
|
108
|
+
symbol_size = get_trait_str_size(handle, trait_type)
|
|
109
|
+
|
|
110
|
+
symbol = bytearray(symbol_size)
|
|
111
|
+
|
|
112
|
+
get_trait_str(handle, trait_type, symbol_size, symbol)
|
|
113
|
+
|
|
114
|
+
# terminate trailing 0 (indicator of c-string end)
|
|
115
|
+
symbol_str = symbol[:-1].decode()
|
|
116
|
+
|
|
117
|
+
return symbol_str
|
|
118
|
+
|
|
119
|
+
return get_str_trait
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def get_mathdx_sm(version: ComputeCapability) -> list:
|
|
123
|
+
sm = [version.integer]
|
|
124
|
+
if version.arch == "a":
|
|
125
|
+
sm.append(mathdx.CommondxArchModifier.ARCH_SPECIFIC)
|
|
126
|
+
return sm
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def set_code_target_sm(code: int, version: ComputeCapability):
|
|
130
|
+
sm = get_mathdx_sm(version)
|
|
131
|
+
mathdx.commondx_set_code_option_int64s(code, mathdx.CommondxOption.TARGET_SM, len(sm), sm)
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"current_device_lto",
|
|
7
|
+
"current_device_sm",
|
|
8
|
+
"ComputeCapability",
|
|
9
|
+
"CodeType",
|
|
10
|
+
"ISAVersion",
|
|
11
|
+
"Code",
|
|
12
|
+
"Dim3",
|
|
13
|
+
"MAX_SUPPORTED_CC",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
import logging
|
|
17
|
+
from collections import namedtuple
|
|
18
|
+
from typing import NamedTuple
|
|
19
|
+
|
|
20
|
+
from cuda.bindings import driver as cudadrv
|
|
21
|
+
from cuda.bindings import runtime as cudart
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# Code = CodeType + ISAVersion + buffer
|
|
25
|
+
class Code(namedtuple("Code", ("code_type", "isa_version", "data"))):
|
|
26
|
+
"""
|
|
27
|
+
A namedtuple class that encapsulates code type, version, and buffer.
|
|
28
|
+
|
|
29
|
+
Attributes:
|
|
30
|
+
code_type (CodeType): The underlying code type.
|
|
31
|
+
isa_version (ISAVersion): The instruction set architecture version for the code.
|
|
32
|
+
data (bytes): The code buffer.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
__slots__ = ()
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
# CodeType = type + CC
|
|
39
|
+
class CodeType(namedtuple("CodeType", ("kind", "cc"))):
|
|
40
|
+
"""
|
|
41
|
+
A namedtuple class that encapsulates code kind and compute capability.
|
|
42
|
+
|
|
43
|
+
Attributes:
|
|
44
|
+
kind (str): A string denoting the nature of the code, e.g, ``'lto'``.
|
|
45
|
+
cc (ComputeCapability): The target compute capability of the code.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
__slots__ = ()
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
# CC = e.g. SM 9.0 (Hopper)
|
|
52
|
+
class ComputeCapability(NamedTuple):
|
|
53
|
+
"""
|
|
54
|
+
A namedtuple class that encapsulates the major and minor compute capability.
|
|
55
|
+
|
|
56
|
+
Attributes:
|
|
57
|
+
major (int): The major compute capability.
|
|
58
|
+
minor (int): The minor compute capability.
|
|
59
|
+
arch (str): An optional string representing the GPU accelerated
|
|
60
|
+
architecture. Must be either empty or one of 'f' (for Family),
|
|
61
|
+
'a' (for Architecture).
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
major: int
|
|
65
|
+
minor: int
|
|
66
|
+
arch: str = ""
|
|
67
|
+
|
|
68
|
+
@property
|
|
69
|
+
def integer(self) -> int:
|
|
70
|
+
"""Integer representation of the ComputeCapability"""
|
|
71
|
+
return self.major * 100 + self.minor * 10
|
|
72
|
+
|
|
73
|
+
def __str__(self):
|
|
74
|
+
"""String representation of the ComputeCapability"""
|
|
75
|
+
return f"{self.major}.{self.minor}{self.arch}"
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
MIN_SUPPORTED_CC = ComputeCapability(7, 0)
|
|
79
|
+
MAX_SUPPORTED_CC = ComputeCapability(12, 1)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class Dim3(namedtuple("Dim3", ("x", "y", "z"), defaults=(1, 1, 1))):
|
|
83
|
+
"""
|
|
84
|
+
A namedtuple class that encapsulates the dimensions for grids and blocks.
|
|
85
|
+
|
|
86
|
+
Attributes:
|
|
87
|
+
x (int): The dimension in the x direction (default 1).
|
|
88
|
+
y (int): The dimension in the y direction (default 1).
|
|
89
|
+
z (int): The dimension in the z direction (default 1).
|
|
90
|
+
"""
|
|
91
|
+
|
|
92
|
+
__slots__ = ()
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
# ISAVersion = e.g. 12.3 (from CUDA 12.3)
|
|
96
|
+
class ISAVersion(NamedTuple):
|
|
97
|
+
"""
|
|
98
|
+
A namedtuple class that encapsulates the code version.
|
|
99
|
+
|
|
100
|
+
Attributes:
|
|
101
|
+
major (int): The major code version.
|
|
102
|
+
minor (int): The minor code version.
|
|
103
|
+
"""
|
|
104
|
+
|
|
105
|
+
major: int
|
|
106
|
+
minor: int
|
|
107
|
+
|
|
108
|
+
@classmethod
|
|
109
|
+
def from_integer(cls, isa: int):
|
|
110
|
+
major = isa // 1000
|
|
111
|
+
minor = (isa % 1000) // 10
|
|
112
|
+
|
|
113
|
+
return cls(major, minor)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def CHECK_CUDART(err):
|
|
117
|
+
if err != cudart.cudaError_t.cudaSuccess:
|
|
118
|
+
err2, str = cudart.cudaGetErrorString(err)
|
|
119
|
+
raise RuntimeError(f"CUDArt Error: {str} ({err})")
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def CHECK_CUDA(err):
|
|
123
|
+
if err != cudadrv.CUresult.CUDA_SUCCESS:
|
|
124
|
+
err2, str = cudadrv.cuGetErrorName(err)
|
|
125
|
+
raise RuntimeError(f"CUDA Error: {str} ({err})")
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def get_current_device() -> int:
|
|
129
|
+
(err,) = cudadrv.cuInit(0)
|
|
130
|
+
CHECK_CUDA(err)
|
|
131
|
+
# Check if a context exist
|
|
132
|
+
err, pctx = cudadrv.cuCtxGetCurrent()
|
|
133
|
+
CHECK_CUDA(err)
|
|
134
|
+
if int(pctx) == 0:
|
|
135
|
+
# If not, return the CC of device 0
|
|
136
|
+
device = 0
|
|
137
|
+
else:
|
|
138
|
+
err, device = cudart.cudaGetDevice()
|
|
139
|
+
CHECK_CUDART(err)
|
|
140
|
+
|
|
141
|
+
return device
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def get_current_device_cc():
|
|
145
|
+
(err,) = cudadrv.cuInit(0)
|
|
146
|
+
CHECK_CUDA(err)
|
|
147
|
+
# Check if a context exist
|
|
148
|
+
err, pctx = cudadrv.cuCtxGetCurrent()
|
|
149
|
+
CHECK_CUDA(err)
|
|
150
|
+
if int(pctx) == 0:
|
|
151
|
+
# If not, return the CC of device 0
|
|
152
|
+
device = 0
|
|
153
|
+
else:
|
|
154
|
+
err, device = cudart.cudaGetDevice()
|
|
155
|
+
CHECK_CUDART(err)
|
|
156
|
+
err, prop = cudart.cudaGetDeviceProperties(device)
|
|
157
|
+
CHECK_CUDART(err)
|
|
158
|
+
major, minor = prop.major, prop.minor
|
|
159
|
+
if (major, minor) > MAX_SUPPORTED_CC:
|
|
160
|
+
logging.info(
|
|
161
|
+
"The current device supports compute capability "
|
|
162
|
+
f"{prop.major}.{prop.minor}, but the generated LTO version is "
|
|
163
|
+
f"capped at {MAX_SUPPORTED_CC}."
|
|
164
|
+
)
|
|
165
|
+
major, minor = MAX_SUPPORTED_CC
|
|
166
|
+
logging.info(f"Using device {device} for default compute capability, found cc = {prop.major}.{prop.minor}")
|
|
167
|
+
arch = ""
|
|
168
|
+
if (major, minor) >= (9, 0):
|
|
169
|
+
arch = "a"
|
|
170
|
+
return ComputeCapability(major, minor, arch)
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def get_default_code_type() -> CodeType:
|
|
174
|
+
try:
|
|
175
|
+
return CodeType("lto", get_current_device_cc())
|
|
176
|
+
except RuntimeError as e:
|
|
177
|
+
raise ValueError(f"Failed to get the current GPU compute capability (got {e}). Set code_type explicitly.") from e
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def current_device_lto():
|
|
181
|
+
"""
|
|
182
|
+
A helper function to get the default code type for link time optimization (LTO) on the
|
|
183
|
+
current device.
|
|
184
|
+
|
|
185
|
+
Returns:
|
|
186
|
+
A :class:`CodeType` object representing the default LTO code type for the current
|
|
187
|
+
device.
|
|
188
|
+
"""
|
|
189
|
+
return get_default_code_type()
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def current_device_sm() -> ComputeCapability:
|
|
193
|
+
"""
|
|
194
|
+
A helper function to get the default SM for mathdx types on the
|
|
195
|
+
current device.
|
|
196
|
+
|
|
197
|
+
Returns:
|
|
198
|
+
A :class:`ComputeCapability` object representing the default SM for
|
|
199
|
+
mathdx types on the current device.
|
|
200
|
+
"""
|
|
201
|
+
return get_current_device_cc()
|