Uni20
Asynchronous tensor and runtime library.
Loading...
Searching...
No Matches
linalg/backends/cublas/gemm.hpp
Go to the documentation of this file.
1#pragma once
2
15
16#include <type_traits>
17#include <utility>
18
19namespace uni20::linalg
20{
21namespace detail::cublas_backend
22{
23
24template <uni20::MdspecLike Mdspan> [[nodiscard]] uni20::cuda::Device span_device(Mdspan const& span)
25{
26 return blas::detail::span_data(span).buffer().device();
27}
28
29[[nodiscard]] inline bool product_output_is_empty(detail::matrix_product_extents const& shape) noexcept
30{
31 return shape.extent(0) == 0 || shape.extent(1) == 0;
32}
33
34} // namespace detail::cublas_backend
35
37template <uni20::MutableRankedMdspecLike<2> OutputMdspan, class Scalar, uni20::RankedMdspecLike<2> LhsMdspan,
38 uni20::RankedMdspecLike<2> RhsMdspan>
39consteval auto kernel_accepts_types(CublasBackend const&, gemm_op const&, OutputMdspan&, Scalar const&, LhsMdspan&,
40 RhsMdspan&, Scalar const&)
41{
42 if constexpr (detail::cublas_backend::accepts_gemm_types<Scalar, OutputMdspan, LhsMdspan, RhsMdspan>())
43 return kernel_types_maybe;
44 else
45 return kernel_types_no;
46}
47
49template <uni20::MutableRankedMdspecLike<2> OutputMdspan, class Scalar, uni20::RankedMdspecLike<2> LhsMdspan,
50 uni20::RankedMdspecLike<2> RhsMdspan>
51KernelAttempt try_kernel(CublasBackend, gemm_op const&, OutputMdspan& output, Scalar alpha, LhsMdspan& lhs,
52 RhsMdspan& rhs, Scalar beta)
53{
54 return detail::cublas_backend::try_gemm(output, alpha, lhs, rhs, beta);
55}
56
58template <uni20::MutableRankedTensorView<2> OutputTensor, class Scalar, uni20::RankedMdspecLike<2> LhsMdspan,
59 uni20::RankedMdspecLike<2> RhsMdspan>
60consteval auto kernel_accepts_types(CublasBackend const&, assign_product_op const&, OutputTensor&, Scalar const&,
61 LhsMdspan&, RhsMdspan&)
62{
63 using output_span = std::remove_cvref_t<decltype(uni20::mdspec_of(std::declval<OutputTensor&>()))>;
64 if constexpr (detail::cublas_backend::accepts_gemm_types<Scalar, output_span, LhsMdspan, RhsMdspan>())
65 return kernel_types_maybe;
66 else
67 return kernel_types_no;
68}
69
71template <uni20::MutableRankedTensorView<2> OutputTensor, class Scalar, uni20::RankedMdspecLike<2> LhsMdspan,
72 uni20::RankedMdspecLike<2> RhsMdspan>
73KernelAttempt try_kernel(CublasBackend, assign_product_op const&, OutputTensor& output, Scalar alpha, LhsMdspan& lhs,
74 RhsMdspan& rhs)
75{
76 auto const shape = detail::matrix_product_shape(lhs, rhs);
77 bool const output_is_empty = detail::cublas_backend::product_output_is_empty(shape);
78 auto const lhs_device = detail::cublas_backend::span_device(lhs);
79 if (!output_is_empty && detail::cublas_backend::span_device(rhs) != lhs_device)
81
82 if constexpr (requires { uni20::prepare_output(output, shape, lhs_device); })
83 {
84 uni20::prepare_output(output, shape, lhs_device);
85 }
86 else if (!uni20::tensor_extents_equal(output.extents(), shape))
87 {
89 }
90
91 auto output_span = uni20::mdspec_of(output);
92 if (!output_is_empty && detail::cublas_backend::span_device(output_span) != lhs_device)
94 return detail::cublas_backend::try_gemm(output_span, alpha, lhs, rhs, Scalar{});
95}
96
98template <uni20::MutableRankedTensorView<2> OutputTensor, class Scalar, uni20::RankedMdspecLike<2> LhsMdspan,
99 uni20::RankedMdspecLike<2> RhsMdspan>
100 requires requires(async::shared_storage<OutputTensor>& storage, detail::matrix_product_extents const& shape,
101 uni20::cuda::Device device) { uni20::prepare_output(storage, shape, device); }
103 async::shared_storage<OutputTensor>&, Scalar const&, LhsMdspan&, RhsMdspan&)
104{
105 using output_span = std::remove_cvref_t<decltype(uni20::mdspec_of(std::declval<OutputTensor&>()))>;
106 if constexpr (detail::cublas_backend::accepts_gemm_types<Scalar, output_span, LhsMdspan, RhsMdspan>())
107 return kernel_types_maybe;
108 else
109 return kernel_types_no;
110}
111
113template <uni20::MutableRankedTensorView<2> OutputTensor, class Scalar, uni20::RankedMdspecLike<2> LhsMdspan,
114 uni20::RankedMdspecLike<2> RhsMdspan>
115 requires requires(async::shared_storage<OutputTensor>& storage, detail::matrix_product_extents const& shape,
116 uni20::cuda::Device device) { uni20::prepare_output(storage, shape, device); }
118 Scalar alpha, LhsMdspan& lhs, RhsMdspan& rhs)
119{
120 auto const shape = detail::matrix_product_shape(lhs, rhs);
121 bool const output_is_empty = detail::cublas_backend::product_output_is_empty(shape);
122 auto const lhs_device = detail::cublas_backend::span_device(lhs);
123 if (!output_is_empty && detail::cublas_backend::span_device(rhs) != lhs_device)
125
126 auto& output = uni20::prepare_output(output_storage, shape, lhs_device);
127 auto output_span = uni20::mdspec_of(output);
128 return detail::cublas_backend::try_gemm(output_span, alpha, lhs, rhs, Scalar{});
129}
130
131} // namespace uni20::linalg
A lightweight, thread-safe, reference-counted storage for a single object.
Definition shared_storage.hpp:94
Validated CUDA device identity with cached immutable capabilities.
Definition device.hpp:105
Concept for numeric scalar types (integer, real, or complex).
Definition scalar_concepts.hpp:81
Operation-tag backend dispatch over tensor-view operands.
CUDA-mdspan preparation and buffer-ledger execution for CublasBackend GEMM.
Backend-independent dense matrix-product shape validation.
Definition linalg/async.hpp:28
KernelAttempt try_kernel(BlasBackend, gemm_op const &, C &c, S const &alpha, A &a, B &b, S const &beta)
Pack logical host values and execute GEMM through value-preserving provider conversion.
Definition linalg/backends/blas/binary80.hpp:30
KernelAttempt
Result of one runtime kernel backend attempt.
Definition kernel_attempt.hpp:27
constexpr KernelAcceptance< KernelTypeAcceptance::no > kernel_types_no
Report that a backend rejects the argument types.
Definition dispatch_error.hpp:34
consteval auto kernel_accepts_types(BlasBackend, gemm_op const &, C &, S const &, A &, B &, S const &)
Accept host-readable native binary80 operands, including transforming accessors.
Definition linalg/backends/blas/binary80.hpp:19
constexpr KernelAcceptance< KernelTypeAcceptance::maybe > kernel_types_maybe
Report that runtime operand values determine backend acceptance.
Definition dispatch_error.hpp:37
Output & prepare_output(Output &output, RequiredExtents const &required)
Prepare a mutable tensor output with the specified shape.
Definition tensor/output.hpp:104
constexpr decltype(auto) mdspec_of(Tensor &tensor) noexcept(noexcept(tensor.mdspec()))
Return a tensor's immediate or descriptor-backed multidimensional metadata.
Definition tensor/concepts.hpp:50
mpreal beta(mpreal const &a, mpreal const &x)
Real Beta function; positive rational/integer pairs retain exact values.
Definition mpreal_special.hpp:164
constexpr bool tensor_extents_equal(LhsExtents const &lhs, RhsExtents const &rhs) noexcept
Compare two tensor extent objects by rank and per-axis extent.
Definition tensor/output.hpp:31
Backend-independent operation values used with normalized kernel operands.
std::size_t span
Definition presentation.cpp:2017
Backend value for cuBLAS dense linalg kernels.
Definition backend_selector.hpp:34
Replaceable-output dense matrix product operation tag.
Definition operation_tags.hpp:75
Fixed-output dense matrix multiplication operation tag.
Definition operation_tags.hpp:84
Concepts for tensor-level objects that resolve mdspan kernel operands.
Shape preparation contracts for tensor operation outputs.