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,53 @@
|
|
|
1
|
+
// Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
|
|
2
|
+
//
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
#ifndef NVMATH_COPY_KERNEL_ELEMENTWISE_H
|
|
6
|
+
#define NVMATH_COPY_KERNEL_ELEMENTWISE_H
|
|
7
|
+
|
|
8
|
+
#include "args.h"
|
|
9
|
+
#include "copy_kernel_impl/array_view.h"
|
|
10
|
+
#include "copy_kernel_impl/elementwise.h"
|
|
11
|
+
#include "copy_kernel_impl/grid_indexer.h"
|
|
12
|
+
#include "copy_kernel_impl/type_utils.h"
|
|
13
|
+
#include "copy_kernel_impl/utils.h"
|
|
14
|
+
#include "copy_kernel_impl/vec.h"
|
|
15
|
+
|
|
16
|
+
#define ELEMENTWISE_KERNEL(stride_t, dst_ndim, src_ndim, itemsize, needs_grid_stride_loop) \
|
|
17
|
+
extern "C" { \
|
|
18
|
+
constexpr int N = dst_ndim > src_ndim ? dst_ndim : src_ndim; \
|
|
19
|
+
void __global__ elementwise_copy(const nvmath::KernelArgs<N> args) { \
|
|
20
|
+
nvmath::elementwise_copy<nvmath::##stride_t, dst_ndim, src_ndim, itemsize, needs_grid_stride_loop> kernel; \
|
|
21
|
+
kernel(args); \
|
|
22
|
+
} \
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
namespace nvmath {
|
|
26
|
+
|
|
27
|
+
template <typename stride_t, int dst_ndim, int src_ndim, int itemsize, int needs_grid_stride_loop>
|
|
28
|
+
struct elementwise_copy {
|
|
29
|
+
using dtype_t = opaque_t<itemsize>;
|
|
30
|
+
using dst_coords_t = vec<dst_ndim, stride_t>;
|
|
31
|
+
using src_coords_t = vec<src_ndim, stride_t>;
|
|
32
|
+
using dst_array_view_t = array_view<dtype_t, dst_coords_t>;
|
|
33
|
+
using src_array_view_t = array_view<const dtype_t, src_coords_t>;
|
|
34
|
+
using grid_indexer_t = element_indexer<stride_t, needs_grid_stride_loop>;
|
|
35
|
+
constexpr static bool has_equal_shapes = dst_ndim == src_ndim;
|
|
36
|
+
constexpr static int ndim = dst_ndim > src_ndim ? dst_ndim : src_ndim;
|
|
37
|
+
|
|
38
|
+
void __forceinline__ __device__ operator()(const KernelArgs<ndim> args) {
|
|
39
|
+
dst_coords_t dst_shape{args.dst_shape};
|
|
40
|
+
src_coords_t src_shape{args.src_shape};
|
|
41
|
+
dst_coords_t dst_strides{args.dst_strides};
|
|
42
|
+
src_coords_t src_strides{args.src_strides};
|
|
43
|
+
dst_array_view_t dst_array_view{static_cast<dtype_t *>(args.dst_ptr), std::move(dst_shape), std::move(dst_strides)};
|
|
44
|
+
src_array_view_t src_array_view{static_cast<const dtype_t *>(args.src_ptr), std::move(src_shape),
|
|
45
|
+
std::move(src_strides)};
|
|
46
|
+
auto kernel = elementwise_copy_impl<has_equal_shapes, dst_array_view_t, src_array_view_t, grid_indexer_t>{};
|
|
47
|
+
kernel(std::move(dst_array_view), std::move(src_array_view), grid_indexer_t{static_cast<stride_t>(args.grid_arg)});
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
} // namespace nvmath
|
|
52
|
+
|
|
53
|
+
#endif // NVMATH_COPY_KERNEL_ELEMENTWISE_H
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
|
|
2
|
+
//
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
#ifndef NVMATH_COPY_KERNEL_TRANSPOSED_H
|
|
6
|
+
#define NVMATH_COPY_KERNEL_TRANSPOSED_H
|
|
7
|
+
|
|
8
|
+
#include "args.h"
|
|
9
|
+
#include "copy_kernel_impl/array_view.h"
|
|
10
|
+
#include "copy_kernel_impl/grid_indexer.h"
|
|
11
|
+
#include "copy_kernel_impl/transposed.h"
|
|
12
|
+
#include "copy_kernel_impl/type_utils.h"
|
|
13
|
+
#include "copy_kernel_impl/utils.h"
|
|
14
|
+
#include "copy_kernel_impl/vec.h"
|
|
15
|
+
|
|
16
|
+
#define TRANSPOSE_KERNEL(stride_t, ndim, itemsize, needs_grid_stride_loop, transposed_dim, tile_y, tile_x, \
|
|
17
|
+
reading_order) \
|
|
18
|
+
extern "C" { \
|
|
19
|
+
void __global__ transpose_copy(const nvmath::KernelArgs<ndim> args) { \
|
|
20
|
+
nvmath::transpose_copy<nvmath::##stride_t, ndim, itemsize, needs_grid_stride_loop, transposed_dim, tile_y, tile_x, \
|
|
21
|
+
reading_order> \
|
|
22
|
+
kernel; \
|
|
23
|
+
kernel(args); \
|
|
24
|
+
} \
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
namespace nvmath {
|
|
28
|
+
|
|
29
|
+
template <typename stride_t, int ndim, int itemsize, int needs_grid_stride_loop, int transposed_dim, int tile_y,
|
|
30
|
+
int tile_x, char reading_order>
|
|
31
|
+
struct transpose_copy {
|
|
32
|
+
using dtype_t = opaque_t<itemsize>;
|
|
33
|
+
using coords_t = vec<ndim, stride_t>;
|
|
34
|
+
using dst_array_view_t = array_view<dtype_t, coords_t>;
|
|
35
|
+
using src_array_view_t = array_view<const dtype_t, coords_t>;
|
|
36
|
+
using grid_indexer_t = block_indexer<stride_t, needs_grid_stride_loop>;
|
|
37
|
+
static_assert(tile_y > 0 && tile_x > 0, "tile_y and tile_x must be positive");
|
|
38
|
+
using copy_helper_t = detail::transpose2d<dtype_t, stride_t, transposed_dim, tile_y, tile_x, reading_order>;
|
|
39
|
+
|
|
40
|
+
void __forceinline__ __device__ operator()(const KernelArgs<ndim> args) {
|
|
41
|
+
__shared__ stride_t dst_offsets[copy_helper_t::tile_num_elements];
|
|
42
|
+
__shared__ dtype_t shared_data[copy_helper_t::tile_num_elements];
|
|
43
|
+
coords_t dst_shape{args.dst_shape};
|
|
44
|
+
coords_t src_shape{args.src_shape};
|
|
45
|
+
coords_t dst_strides{args.dst_strides};
|
|
46
|
+
coords_t src_strides{args.src_strides};
|
|
47
|
+
dst_array_view_t dst_array_view{static_cast<dtype_t *>(args.dst_ptr), std::move(dst_shape), std::move(dst_strides)};
|
|
48
|
+
src_array_view_t src_array_view{static_cast<const dtype_t *>(args.src_ptr), std::move(src_shape),
|
|
49
|
+
std::move(src_strides)};
|
|
50
|
+
auto kernel = transpose_copy_impl<dst_array_view_t, src_array_view_t, grid_indexer_t, copy_helper_t>{};
|
|
51
|
+
kernel(std::move(dst_array_view), std::move(src_array_view), grid_indexer_t{static_cast<stride_t>(args.grid_arg)},
|
|
52
|
+
copy_helper_t{shared_data, dst_offsets});
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
} // namespace nvmath
|
|
57
|
+
|
|
58
|
+
#endif // NVMATH_COPY_KERNEL_TRANSPOSED_H
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
An abstract interface to certain package-provided operations.
|
|
7
|
+
|
|
8
|
+
Even though cuda.core does not have the concept of a "current stream" or a "stream context",
|
|
9
|
+
we promise to honor third-party CUDA stream contexts if they match the input operand's
|
|
10
|
+
package. The interface class defined in this module wraps around those stream concepts to
|
|
11
|
+
make them uniform.
|
|
12
|
+
|
|
13
|
+
The strategy is to use cuda.core everywhere internally except for context managers which
|
|
14
|
+
will need to wrap back around to the external implementation.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
__all__ = ["Package", "StreamHolder"]
|
|
18
|
+
|
|
19
|
+
from abc import ABC, abstractmethod
|
|
20
|
+
from collections.abc import Hashable
|
|
21
|
+
from contextlib import AbstractContextManager
|
|
22
|
+
from dataclasses import dataclass
|
|
23
|
+
from typing import Generic, Protocol, TypeVar
|
|
24
|
+
|
|
25
|
+
from cuda.core import Stream
|
|
26
|
+
|
|
27
|
+
from ._device_utils import get_device
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class AnyStream(Hashable, Protocol):
|
|
31
|
+
"""Any supported Stream object such as a Stream from cuda.core, CuPy, or PyTorch."""
|
|
32
|
+
|
|
33
|
+
# This empty protocol class is just a placeholder to make type checking more helpful.
|
|
34
|
+
# Since the class is empty, it doesn't assume anything is true about the implementation
|
|
35
|
+
# classes.
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
"""
|
|
40
|
+
A generic type for the third-party Stream which a given Package implementation wraps
|
|
41
|
+
around.
|
|
42
|
+
"""
|
|
43
|
+
S = TypeVar("S")
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
# CUDA stream protocol version, see
|
|
47
|
+
# https://nvidia.github.io/cuda-python/cuda-core/latest/interoperability.html#cuda-stream-protocol
|
|
48
|
+
_CUDA_STREAM_PROTOCOL_VERSION = 0
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class _cuda_core_stream_holder(Generic[S]):
|
|
52
|
+
"""
|
|
53
|
+
Expose a raw ``cudaStream_t`` handle through the CUDA stream protocol.
|
|
54
|
+
|
|
55
|
+
This adapter can be passed to consumers that accept the protocol, such as
|
|
56
|
+
``cuda.core.Device.create_stream`` or ``cp.cuda.Stream.from_external``.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
handle: The raw ``cudaStream_t`` value to expose.
|
|
60
|
+
external: Optional object that owns or keeps ``handle`` alive. The
|
|
61
|
+
holder stores a strong reference to this object but does not
|
|
62
|
+
otherwise use it. Pass ``None`` when the consumer only reads the
|
|
63
|
+
protocol immediately, or when the stream lifetime is guaranteed
|
|
64
|
+
elsewhere.
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
__slots__ = ("external", "handle")
|
|
68
|
+
|
|
69
|
+
def __init__(self, handle: int, external: S | None = None):
|
|
70
|
+
self.handle = handle
|
|
71
|
+
self.external = external
|
|
72
|
+
|
|
73
|
+
def __cuda_stream__(self):
|
|
74
|
+
return (_CUDA_STREAM_PROTOCOL_VERSION, self.handle)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class Package(ABC, Generic[S]):
|
|
78
|
+
@staticmethod
|
|
79
|
+
@abstractmethod
|
|
80
|
+
def get_current_stream(device_id: int) -> S:
|
|
81
|
+
"""
|
|
82
|
+
Obtain the current stream on the device.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
device_id: The id (ordinal) of the device.
|
|
86
|
+
"""
|
|
87
|
+
raise NotImplementedError
|
|
88
|
+
|
|
89
|
+
@staticmethod
|
|
90
|
+
@abstractmethod
|
|
91
|
+
def to_stream_pointer(stream: S) -> int:
|
|
92
|
+
"""
|
|
93
|
+
Obtain the stream pointer.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
stream: The stream object.
|
|
97
|
+
"""
|
|
98
|
+
raise NotImplementedError
|
|
99
|
+
|
|
100
|
+
@staticmethod
|
|
101
|
+
@abstractmethod
|
|
102
|
+
def get_current_stream_ptr(device_id: int) -> int:
|
|
103
|
+
"""
|
|
104
|
+
Return the raw ``cudaStream_t`` int for the current stream on ``device_id``.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
device_id: The id (ordinal) of the device.
|
|
108
|
+
"""
|
|
109
|
+
raise NotImplementedError
|
|
110
|
+
|
|
111
|
+
@staticmethod
|
|
112
|
+
@abstractmethod
|
|
113
|
+
def to_stream_context(stream: S) -> AbstractContextManager[S]:
|
|
114
|
+
"""
|
|
115
|
+
Create a context manager from the stream.
|
|
116
|
+
|
|
117
|
+
Args:
|
|
118
|
+
stream: The stream object.
|
|
119
|
+
"""
|
|
120
|
+
raise NotImplementedError
|
|
121
|
+
|
|
122
|
+
@staticmethod
|
|
123
|
+
@abstractmethod
|
|
124
|
+
def create_external_stream(device_id: int, stream_ptr: int) -> S:
|
|
125
|
+
"""
|
|
126
|
+
Wrap a stream pointer into an external stream object.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
device_id: The id (ordinal) of the device.
|
|
130
|
+
stream: The stream pointer (int) to be wrapped.
|
|
131
|
+
"""
|
|
132
|
+
raise NotImplementedError
|
|
133
|
+
|
|
134
|
+
@classmethod
|
|
135
|
+
def create_stream(cls, external: S, device_id: int) -> Stream:
|
|
136
|
+
"""
|
|
137
|
+
Wrap an external Stream object into a cuda.core.Stream.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
external: The external Stream object.
|
|
141
|
+
"""
|
|
142
|
+
# use get_device to ensure the initial set_current is called
|
|
143
|
+
device = get_device(device_id)
|
|
144
|
+
# the stream holder ensures we tie the external reference to the
|
|
145
|
+
# cuda.core stream object, extending its lifetime.
|
|
146
|
+
holder = _cuda_core_stream_holder(cls.to_stream_pointer(external), external)
|
|
147
|
+
return device.create_stream(holder)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
@dataclass
|
|
151
|
+
class StreamHolder(Generic[S]):
|
|
152
|
+
"""A data class for easing CUDA stream manipulation.
|
|
153
|
+
|
|
154
|
+
Attributes:
|
|
155
|
+
ctx: A context manager for using the specified stream.
|
|
156
|
+
device_id (int): The device ID where the encapsulated stream locates.
|
|
157
|
+
external: A foreign object that holds the stream alive.
|
|
158
|
+
obj: The cuda.core Stream object wrapping external.
|
|
159
|
+
package (str): The name of the package to which the external stream belongs.
|
|
160
|
+
ptr (int): The address of the underlying ``cudaStream_t`` object.
|
|
161
|
+
"""
|
|
162
|
+
|
|
163
|
+
ctx: AbstractContextManager[S]
|
|
164
|
+
device_id: int
|
|
165
|
+
external: S
|
|
166
|
+
obj: Stream
|
|
167
|
+
package: str
|
|
168
|
+
ptr: int
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
Interface to cuda.core operations.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
__all__ = ["CUDAPackage"]
|
|
10
|
+
|
|
11
|
+
import contextlib
|
|
12
|
+
import functools
|
|
13
|
+
|
|
14
|
+
from cuda.core import Stream
|
|
15
|
+
|
|
16
|
+
from ._device_utils import get_device
|
|
17
|
+
from .package_ifc import Package
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# cuda.core's ``Device.default_stream`` wraps a CUDA driver *sentinel* pointer
|
|
21
|
+
# (``CU_STREAM_LEGACY = 0x1`` or ``CU_STREAM_PER_THREAD = 0x2``) that is constant
|
|
22
|
+
# for the life of the process, so the (device_id -> ptr) map can be cached.
|
|
23
|
+
@functools.cache
|
|
24
|
+
def _get_current_stream_ptr(device_id: int) -> int:
|
|
25
|
+
return int(get_device(device_id).default_stream.handle)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class CUDAPackage(Package[Stream]):
|
|
29
|
+
@staticmethod
|
|
30
|
+
def get_current_stream(device_id: int):
|
|
31
|
+
# Use get_device to ensure the cuda.core
|
|
32
|
+
# device has been initialized.
|
|
33
|
+
# In cuda.core 0.5.0, Stream.__hash__ requires context
|
|
34
|
+
# to be set.
|
|
35
|
+
# See https://github.com/NVIDIA/cuda-python/issues/1480
|
|
36
|
+
# TODO(ktokarski): Once we drop support for cuda.core 0.5.0,
|
|
37
|
+
# we can remove this precaution.
|
|
38
|
+
device = get_device(device_id)
|
|
39
|
+
return device.default_stream
|
|
40
|
+
|
|
41
|
+
@staticmethod
|
|
42
|
+
def to_stream_pointer(stream: Stream) -> int: # type: ignore[override]
|
|
43
|
+
return int(stream.handle)
|
|
44
|
+
|
|
45
|
+
get_current_stream_ptr = staticmethod(_get_current_stream_ptr)
|
|
46
|
+
|
|
47
|
+
@staticmethod
|
|
48
|
+
def to_stream_context(stream: Stream): # type: ignore[override]
|
|
49
|
+
return contextlib.nullcontext(stream)
|
|
50
|
+
|
|
51
|
+
@staticmethod
|
|
52
|
+
def create_external_stream(device_id: int, stream_ptr: int) -> Stream:
|
|
53
|
+
return Stream.from_handle(stream_ptr)
|
|
54
|
+
|
|
55
|
+
@classmethod
|
|
56
|
+
def create_stream(cls, external: Stream, device_id: int) -> Stream: # type: ignore[override]
|
|
57
|
+
return external
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
Interface to CuPy operations.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
__all__ = ["CupyPackage"]
|
|
10
|
+
|
|
11
|
+
import cupy as cp
|
|
12
|
+
|
|
13
|
+
from . import utils
|
|
14
|
+
from .package_ifc import Package, _cuda_core_stream_holder
|
|
15
|
+
|
|
16
|
+
_CUPY_MAJOR = int(cp.__version__.split(".")[0])
|
|
17
|
+
|
|
18
|
+
# Using the functional API is faster than setting a device context
|
|
19
|
+
if _CUPY_MAJOR >= 13:
|
|
20
|
+
_get_current_stream = cp.cuda.get_current_stream
|
|
21
|
+
else:
|
|
22
|
+
|
|
23
|
+
def _get_current_stream(device_id: int):
|
|
24
|
+
with utils.device_ctx(device_id):
|
|
25
|
+
stream = cp.cuda.get_current_stream()
|
|
26
|
+
return stream
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# CuPy v14 deprecated ``cp.cuda.ExternalStream(int)`` in favor of
|
|
30
|
+
# ``cp.cuda.Stream.from_external(obj)``, where ``obj`` must implement the
|
|
31
|
+
# CUDA stream protocol.
|
|
32
|
+
if _CUPY_MAJOR >= 14:
|
|
33
|
+
|
|
34
|
+
def _create_external_stream(stream_ptr: int):
|
|
35
|
+
return cp.cuda.Stream.from_external(_cuda_core_stream_holder(stream_ptr))
|
|
36
|
+
|
|
37
|
+
else:
|
|
38
|
+
_create_external_stream = cp.cuda.ExternalStream
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class CupyPackage(Package[cp.cuda.Stream]):
|
|
42
|
+
@staticmethod
|
|
43
|
+
def get_current_stream(device_id: int):
|
|
44
|
+
return _get_current_stream(device_id)
|
|
45
|
+
|
|
46
|
+
@staticmethod
|
|
47
|
+
def to_stream_pointer(stream: cp.cuda.Stream) -> int:
|
|
48
|
+
return stream.ptr
|
|
49
|
+
|
|
50
|
+
# Goal: return the raw ``cudaStream_t`` int for the current stream on a
|
|
51
|
+
# given device. CuPy has a binding-level ptr getter at the runtime
|
|
52
|
+
# layer, but at the time this method was added it was only exposed as
|
|
53
|
+
# a Cython ``cdef`` function not callable from Python, so we can't
|
|
54
|
+
# reach it directly. ``cp.cuda.get_current_stream().ptr`` is nearly
|
|
55
|
+
# as fast empirically because CuPy caches the per-thread Stream object on
|
|
56
|
+
# ``_ThreadLocal.current_stream``.
|
|
57
|
+
@staticmethod
|
|
58
|
+
def get_current_stream_ptr(device_id: int) -> int:
|
|
59
|
+
return _get_current_stream(device_id).ptr
|
|
60
|
+
|
|
61
|
+
@staticmethod
|
|
62
|
+
def to_stream_context(stream: cp.cuda.Stream):
|
|
63
|
+
return stream
|
|
64
|
+
|
|
65
|
+
@staticmethod
|
|
66
|
+
def create_external_stream(device_id: int, stream_ptr: int):
|
|
67
|
+
return _create_external_stream(stream_ptr)
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
Interface to Torch operations.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
__all__ = ["TorchPackage"]
|
|
10
|
+
|
|
11
|
+
import torch
|
|
12
|
+
|
|
13
|
+
from .package_ifc import Package
|
|
14
|
+
|
|
15
|
+
_TORCH_VERSION = tuple(int(p) for p in torch.__version__.split(".")[:2])
|
|
16
|
+
|
|
17
|
+
# Goal: return the raw ``cudaStream_t`` int for the current stream on a
|
|
18
|
+
# given device. ``torch.cuda.current_stream(device=...).cuda_stream``
|
|
19
|
+
# does this but allocates a fresh ``torch.cuda.Stream`` Python wrapper
|
|
20
|
+
# just to read one ``int`` off it. As an alternative, torch's C
|
|
21
|
+
# bindings expose ``torch._C._cuda_getCurrentRawStream``, which returns
|
|
22
|
+
# the raw int directly. Being a private symbol it is not guaranteed
|
|
23
|
+
# on every torch build, so we guard with ``hasattr`` and fall back
|
|
24
|
+
# to the other path when absent.
|
|
25
|
+
# This is resolved once at import time, not per call.
|
|
26
|
+
if hasattr(torch._C, "_cuda_getCurrentRawStream"):
|
|
27
|
+
_get_current_stream_ptr = torch._C._cuda_getCurrentRawStream
|
|
28
|
+
else:
|
|
29
|
+
# Parameter is named ``device_id`` to match ``Package.get_current_stream_ptr``;
|
|
30
|
+
# the ``# type: ignore[misc]`` silences mypy's redefinition warning, since
|
|
31
|
+
# torch's typed signature for ``_cuda_getCurrentRawStream`` calls the
|
|
32
|
+
# argument ``device`` rather than ``device_id``. The runtime call is
|
|
33
|
+
# positional, so the name disagreement is purely a typing artifact.
|
|
34
|
+
def _get_current_stream_ptr(device_id: int) -> int: # type: ignore[misc]
|
|
35
|
+
return torch.cuda.current_stream(device=device_id).cuda_stream
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class TorchPackage(Package[torch.cuda.Stream]):
|
|
39
|
+
@staticmethod
|
|
40
|
+
def get_current_stream(device_id: int) -> torch.cuda.Stream:
|
|
41
|
+
return torch.cuda.current_stream(device=device_id)
|
|
42
|
+
|
|
43
|
+
@staticmethod
|
|
44
|
+
def to_stream_pointer(stream: torch.cuda.Stream) -> int:
|
|
45
|
+
return stream.cuda_stream
|
|
46
|
+
|
|
47
|
+
# Same ``device`` vs ``device_id`` parameter-name disagreement as above:
|
|
48
|
+
# torch's typed signature uses ``device``, but ``Package`` declares
|
|
49
|
+
# ``device_id``. Runtime calls are positional, so this is type-only noise.
|
|
50
|
+
get_current_stream_ptr = staticmethod(_get_current_stream_ptr) # type: ignore[assignment]
|
|
51
|
+
|
|
52
|
+
@staticmethod
|
|
53
|
+
def to_stream_context(stream: torch.cuda.Stream) -> torch.cuda.StreamContext:
|
|
54
|
+
return torch.cuda.stream(stream)
|
|
55
|
+
|
|
56
|
+
@staticmethod
|
|
57
|
+
def create_external_stream(device_id: int, stream_ptr: int) -> torch.cuda.Stream:
|
|
58
|
+
# Issue: ``torch.cuda.ExternalStream(0, ...)`` does not wrap handle
|
|
59
|
+
# ``0x0`` (= the device default stream). Its C++ ctor treats
|
|
60
|
+
# ``stream_ptr == 0`` as "no ptr supplied" and silently returns a
|
|
61
|
+
# fresh pooled stream instead.
|
|
62
|
+
#
|
|
63
|
+
# Use ``torch.cuda.get_stream_from_external`` (first shipped in
|
|
64
|
+
# torch 2.7), which routes through a different C++ path and faithfully
|
|
65
|
+
# wraps any handle, including ``0x0``. On older torch we leave the
|
|
66
|
+
# pre-existing buggy behavior in place.
|
|
67
|
+
if _TORCH_VERSION >= (2, 7):
|
|
68
|
+
return torch.cuda.get_stream_from_external(stream_ptr, device=device_id)
|
|
69
|
+
return torch.cuda.ExternalStream(stream_ptr, device=device_id)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
Create map from package names to package interface objects.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
__all__ = ["PACKAGE", "AnyStream", "StreamHolder"]
|
|
10
|
+
|
|
11
|
+
from .package_ifc import AnyStream, Package, StreamHolder
|
|
12
|
+
from .package_ifc_cuda import CUDAPackage
|
|
13
|
+
|
|
14
|
+
PACKAGE: dict[str, type[Package]] = {"cuda": CUDAPackage}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. ALL RIGHTS RESERVED.
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
Interface to seamlessly use tensors (or ndarray-like objects) from different libraries.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations # allows typehint of class methods to return the self class
|
|
10
|
+
|
|
11
|
+
from abc import ABC, abstractmethod
|
|
12
|
+
from collections.abc import Callable, Sequence
|
|
13
|
+
from types import ModuleType
|
|
14
|
+
from typing import Any, Generic, Literal, Protocol, TypeVar
|
|
15
|
+
|
|
16
|
+
from . import typemaps
|
|
17
|
+
from .ndbuffer import NDBuffer
|
|
18
|
+
from .package_ifc import StreamHolder
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class AnyTensor(Protocol):
|
|
22
|
+
"""Any supported external tensor object such as NumPy, CuPy, and PyTorch arrays."""
|
|
23
|
+
|
|
24
|
+
# This empty protocol class is just a placeholder to make type checking more helpful.
|
|
25
|
+
# Since the class is empty, it doesn't assume anything is true about the implementation
|
|
26
|
+
# classes. Used to type hint any object that TensorHolder knows how to wrap.
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
"""
|
|
31
|
+
A generic type for the third-party Tensor which a given TensorHolder implementation wraps
|
|
32
|
+
around.
|
|
33
|
+
"""
|
|
34
|
+
Tensor = TypeVar("Tensor")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class TensorHolder(ABC, Generic[Tensor]):
|
|
38
|
+
"""
|
|
39
|
+
A simple wrapper type for tensors to make the API package-agnostic.
|
|
40
|
+
|
|
41
|
+
Methods of a TensorHolder should always return a TensorHolder instead of a Tensor (one
|
|
42
|
+
of the wrapped classes) in order to prevent implementation details from the various
|
|
43
|
+
Tensor implementations from leaking into nvmath-python.
|
|
44
|
+
|
|
45
|
+
Tensors from the user should be immediately wrapped with a TensorHolder and should
|
|
46
|
+
remain wrapped until just before returning to the user.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
name: str
|
|
50
|
+
module: ModuleType
|
|
51
|
+
name_to_dtype: dict[str, Any]
|
|
52
|
+
|
|
53
|
+
def __init__(self, tensor: Tensor):
|
|
54
|
+
self.tensor: Tensor = tensor
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
@abstractmethod
|
|
58
|
+
def data_ptr(self) -> int:
|
|
59
|
+
raise NotImplementedError
|
|
60
|
+
|
|
61
|
+
@property
|
|
62
|
+
@abstractmethod
|
|
63
|
+
def device(self) -> Literal["cuda"] | Literal["cpu"]:
|
|
64
|
+
"""The type of the device which stores the tensor."""
|
|
65
|
+
raise NotImplementedError
|
|
66
|
+
|
|
67
|
+
@property
|
|
68
|
+
@abstractmethod
|
|
69
|
+
def device_id(self) -> int | Literal["cpu"]:
|
|
70
|
+
"""The device ordinal of the device storing the tensor."""
|
|
71
|
+
raise NotImplementedError
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
@abstractmethod
|
|
75
|
+
def dtype(self) -> str:
|
|
76
|
+
"""Name of the data type"""
|
|
77
|
+
raise NotImplementedError
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
@abstractmethod
|
|
81
|
+
def itemsize(self) -> int:
|
|
82
|
+
"""The size of the data type in bytes."""
|
|
83
|
+
raise NotImplementedError
|
|
84
|
+
|
|
85
|
+
@classmethod
|
|
86
|
+
@abstractmethod
|
|
87
|
+
def empty(cls, shape: Sequence[int], device_id: int | Literal["cpu"], **context: Any) -> TensorHolder[Tensor]:
|
|
88
|
+
"""Create an empty TensorHolder of the specified shape and data type."""
|
|
89
|
+
raise NotImplementedError
|
|
90
|
+
|
|
91
|
+
@property
|
|
92
|
+
@abstractmethod
|
|
93
|
+
def shape(self) -> Sequence[int]:
|
|
94
|
+
"""The extent of each dimension in number of elements."""
|
|
95
|
+
raise NotImplementedError
|
|
96
|
+
|
|
97
|
+
@property
|
|
98
|
+
@abstractmethod
|
|
99
|
+
def size(self) -> int:
|
|
100
|
+
"""The total number of elements in the tensor."""
|
|
101
|
+
raise NotImplementedError
|
|
102
|
+
|
|
103
|
+
@property
|
|
104
|
+
@abstractmethod
|
|
105
|
+
def strides(self) -> Sequence[int]:
|
|
106
|
+
"""The stride of each dimension in number of elements."""
|
|
107
|
+
raise NotImplementedError
|
|
108
|
+
|
|
109
|
+
@abstractmethod
|
|
110
|
+
def to(self, device_id: int | Literal["cpu"], stream_holder: StreamHolder | None) -> TensorHolder:
|
|
111
|
+
"""Copy the TensorHolder to a different device.
|
|
112
|
+
|
|
113
|
+
No copy is performed if the TensorHolder is already on the requested device.
|
|
114
|
+
"""
|
|
115
|
+
raise NotImplementedError
|
|
116
|
+
|
|
117
|
+
@abstractmethod
|
|
118
|
+
def asndbuffer(self) -> NDBuffer:
|
|
119
|
+
"""Wraps the package tensor as a NDBuffer object."""
|
|
120
|
+
raise NotImplementedError
|
|
121
|
+
|
|
122
|
+
@abstractmethod
|
|
123
|
+
def copy_(self, src: TensorHolder, stream_holder: StreamHolder | None) -> None:
|
|
124
|
+
"""Overwrite self.tensor (in-place) with a copy of src."""
|
|
125
|
+
raise NotImplementedError
|
|
126
|
+
|
|
127
|
+
@staticmethod
|
|
128
|
+
def create_name_dtype_map(conversion_function: Callable[[str], Any], exception_type: type[Exception]) -> dict[str, Any]:
|
|
129
|
+
"""
|
|
130
|
+
Create a map between CUDA data type names and the corresponding package dtypes for
|
|
131
|
+
supported data types.
|
|
132
|
+
"""
|
|
133
|
+
names = typemaps.NAME_TO_DATA_TYPE.keys()
|
|
134
|
+
name_to_dtype = {}
|
|
135
|
+
for name in names:
|
|
136
|
+
try:
|
|
137
|
+
name_to_dtype[name] = conversion_function(name)
|
|
138
|
+
except exception_type:
|
|
139
|
+
pass
|
|
140
|
+
return name_to_dtype
|
|
141
|
+
|
|
142
|
+
@abstractmethod
|
|
143
|
+
def istensor(self) -> bool:
|
|
144
|
+
"""Return whether self.tensor is the expected type."""
|
|
145
|
+
raise NotImplementedError
|
|
146
|
+
|
|
147
|
+
@abstractmethod
|
|
148
|
+
def reshape(self, shape: Sequence[int], *, copy: bool | None = None) -> TensorHolder[Tensor]:
|
|
149
|
+
"""Reshapes tensor without changing its data.
|
|
150
|
+
|
|
151
|
+
Args:
|
|
152
|
+
shape: a new shape compatible with the original shape.
|
|
153
|
+
|
|
154
|
+
copy (Optional[bool]): whether or not to copy the input tensor. If True, the
|
|
155
|
+
function must always copy. If False, the function must never copy. If None,
|
|
156
|
+
the function must avoid copying, if possible, and may copy otherwise.
|
|
157
|
+
"""
|
|
158
|
+
raise NotImplementedError
|
|
159
|
+
|
|
160
|
+
@abstractmethod
|
|
161
|
+
def memory_buffer(self) -> TensorHolder[Tensor]:
|
|
162
|
+
"""Creates a view of the memory buffer as a 1D tensor."""
|
|
163
|
+
raise NotImplementedError
|
|
164
|
+
|
|
165
|
+
@abstractmethod
|
|
166
|
+
def memory_buffer_to_tensor(self, shape, strides) -> TensorHolder[Tensor]:
|
|
167
|
+
"""
|
|
168
|
+
Creates a N-D tensor view of the memory buffer according to the specified
|
|
169
|
+
shape and strides.
|
|
170
|
+
"""
|
|
171
|
+
raise NotImplementedError
|
|
172
|
+
|
|
173
|
+
@property
|
|
174
|
+
def is_conjugate(self) -> bool:
|
|
175
|
+
"""Return True when self.tensor has a no-op conjugation flag enabled.
|
|
176
|
+
|
|
177
|
+
The default implementation always returns False.
|
|
178
|
+
"""
|
|
179
|
+
return False
|