| // This file is part of Eigen, a lightweight C++ template library |
| // for linear algebra. |
| // |
| // Copyright (C) 2026 Rasmus Munk Larsen <rmlarsen@gmail.com> |
| // |
| // This Source Code Form is subject to the terms of the Mozilla |
| // Public License v. 2.0. If a copy of the MPL was not distributed |
| // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| // SPDX-License-Identifier: MPL-2.0 |
| |
| // cuSPARSE-specific support types. |
| |
| #ifndef EIGEN_GPU_CUSPARSE_SUPPORT_H |
| #define EIGEN_GPU_CUSPARSE_SUPPORT_H |
| |
| // IWYU pragma: private |
| #include "./InternalHeaderCheck.h" |
| |
| #include "./GpuSupport.h" |
| #include "./Meta.h" |
| #include <cusparse.h> |
| |
| /** \brief 1 when cuSPARSE runs SpMV and SpMM on BSR (block sparse row) |
| * descriptors, 0 otherwise. |
| * |
| * The generic API gained BSR in SpMM with cuSPARSE 12.5 (CUDA 12.8) and in SpMV |
| * with 12.6.3 (CUDA 13.0 Update 1); older toolkits declare cusparseCreateBsr but |
| * return CUSPARSE_STATUS_NOT_SUPPORTED from the products. gpu::SparseContext |
| * uploads a BlockSparseMatrix as BSR only when this is 1, and as CSC otherwise. */ |
| #if defined(CUSPARSE_VERSION) && CUSPARSE_VERSION >= 12603 |
| #define EIGEN_HAS_CUSPARSE_BSR 1 |
| #else |
| #define EIGEN_HAS_CUSPARSE_BSR 0 |
| #endif |
| |
| namespace Eigen { |
| namespace gpu { |
| namespace internal { |
| |
| #define EIGEN_CUSPARSE_CHECK(x) \ |
| do { \ |
| const cusparseStatus_t _s = (x); \ |
| if (_s != CUSPARSE_STATUS_SUCCESS) EIGEN_GPU_CHECK_FAILED(cusparseGetErrorName(_s), #x, __FILE__, __LINE__); \ |
| } while (0) |
| |
| // cuSPARSE rejects CUSPARSE_OPERATION_CONJUGATE_TRANSPOSE for real scalar |
| // types; for real Scalar, ConjTrans is mathematically equivalent to Trans and |
| // is silently demoted. Complex Scalar passes through unchanged. |
| template <typename Scalar> |
| constexpr cusparseOperation_t to_cusparse_op(GpuOp op) { |
| const auto op_ = (op == GpuOp::ConjTrans && !NumTraits<Scalar>::IsComplex) ? GpuOp::Trans : op; |
| switch (op_) { |
| case GpuOp::Trans: |
| return CUSPARSE_OPERATION_TRANSPOSE; |
| case GpuOp::ConjTrans: |
| return CUSPARSE_OPERATION_CONJUGATE_TRANSPOSE; |
| default: |
| return CUSPARSE_OPERATION_NON_TRANSPOSE; |
| } |
| } |
| |
| // Bind without copying when the input already has the target sparse format |
| // and is compressed; otherwise convert/compress into `storage` and return |
| // that. Avoids a full host copy + format conversion on the common |
| // already-matching path. The SFINAE split (rather than plain overloading on |
| // `const SpMatType&`) is load-bearing: an exact-match overload would bind a |
| // converted temporary for other input types and return a dangling reference. |
| template <typename SpMatType, typename InputType, require_same_t<SpMatType, InputType> = 0> |
| const SpMatType& bind_sparse(const InputType& A, SpMatType& storage) { |
| if (A.isCompressed()) return A; |
| storage = A; |
| storage.makeCompressed(); |
| return storage; |
| } |
| |
| template <typename SpMatType, typename InputType, require_not_same_t<SpMatType, InputType> = 0> |
| const SpMatType& bind_sparse(const InputType& A, SpMatType& storage) { |
| storage = A; |
| storage.makeCompressed(); |
| return storage; |
| } |
| |
| // Shared guard for the 32-bit index limits of the CUDA sparse libraries |
| // (cuSPARSE, cuDSS): matrix dimensions and nonzero count must fit StorageIndex. |
| template <typename StorageIndex> |
| inline void check_storage_index_bounds(Index rows, Index cols, Index nnz) { |
| const Index max_storage_index = static_cast<Index>((std::numeric_limits<StorageIndex>::max)()); |
| eigen_assert(rows <= max_storage_index && cols <= max_storage_index && nnz <= max_storage_index && |
| "matrix dimensions or nonzeros exceed the index range supported by the CUDA sparse libraries"); |
| EIGEN_UNUSED_VARIABLE(rows); |
| EIGEN_UNUSED_VARIABLE(cols); |
| EIGEN_UNUSED_VARIABLE(nnz); |
| EIGEN_UNUSED_VARIABLE(max_storage_index); |
| } |
| |
| } // namespace internal |
| } // namespace gpu |
| } // namespace Eigen |
| |
| #endif // EIGEN_GPU_CUSPARSE_SUPPORT_H |