Uni20
Asynchronous tensor and runtime library.
Loading...
Searching...
No Matches
blas/gemv.hpp
Go to the documentation of this file.
1#pragma once
2
15
16#include <concepts>
17#include <cstddef>
18#include <type_traits>
19
20namespace uni20::linalg::blas
21{
22
23namespace detail
24{
25template <class Mdspan, class Scalar, std::size_t Rank>
26concept readable_gemv_mdspan_for =
27 blas_readable_mdspan<Mdspan, Rank> && std::same_as<std::remove_cv_t<typename Mdspan::element_type>, Scalar> &&
28 std::convertible_to<typename Mdspan::data_handle_type, Scalar const*>;
29
30template <class Mdspan, class Scalar>
31concept writable_gemv_vector_for =
32 blas_writable_mdspan<Mdspan, 1> && std::same_as<std::remove_cv_t<typename Mdspan::element_type>, Scalar> &&
33 std::convertible_to<typename Mdspan::data_handle_type, Scalar*>;
34
35template <uni20::BlasScalar Scalar, class Handle>
36 requires std::convertible_to<Handle, Scalar*>
37void scale_vector(BlasWritableVector<Scalar, Handle> output, Scalar beta)
38{
39 if (beta == Scalar{1})
40 {
41 return;
42 }
43
44 Scalar* value = output.data;
45 for (blas_int index = 0; index < output.size; ++index, value += output.increment)
46 {
47 if (beta == Scalar{})
48 {
49 *value = Scalar{};
50 }
51 else
52 {
53 *value *= beta;
54 }
55 }
56}
57
58template <uni20::BlasScalar Scalar, class OutputHandle, class MatrixHandle, class InputHandle>
59 requires std::convertible_to<OutputHandle, Scalar*> && std::convertible_to<MatrixHandle, Scalar const*> &&
60 std::convertible_to<InputHandle, Scalar const*>
61void gemv(BlasWritableVector<Scalar, OutputHandle> output, BlasReadableMatrix<Scalar, MatrixHandle> matrix,
62 BlasReadableVector<Scalar, InputHandle> input, Scalar alpha, Scalar beta)
63{
64 blas_int const matrix_rows = transformed_rows(matrix.rows, matrix.cols, matrix.transform);
65 blas_int const matrix_cols = transformed_cols(matrix.rows, matrix.cols, matrix.transform);
66 CHECK_EQUAL(output.size, matrix_rows);
67 CHECK_EQUAL(input.size, matrix_cols);
68
69 if (output.size == 0)
70 {
71 return;
72 }
73
74 // BLAS GEMV permits a quick return for an empty provider dimension. Preserve
75 // the linalg operation's y = beta*y semantics explicitly when no product is read.
76 if (alpha == Scalar{} || input.size == 0)
77 {
78 scale_vector(output, beta);
79 return;
80 }
81
82 CHECK(blas_trans_char_is_supported<Scalar>(matrix.transform));
83 char const trans = blas_trans_char<Scalar>(matrix.transform);
84 ::uni20::blas::gemv(trans, matrix.rows, matrix.cols, alpha, matrix.data, matrix.leading_dimension, input.data,
85 input.increment, beta, output.data, output.increment);
86}
87
88} // namespace detail
89
92template <uni20::BlasScalar Scalar, class OutputMdspan, class MatrixMdspan, class InputMdspan>
93 requires detail::writable_gemv_vector_for<std::remove_cvref_t<OutputMdspan>, Scalar> &&
94 detail::readable_gemv_mdspan_for<std::remove_cvref_t<MatrixMdspan>, Scalar, 2> &&
95 detail::readable_gemv_mdspan_for<std::remove_cvref_t<InputMdspan>, Scalar, 1>
96KernelAttempt try_gemv(OutputMdspan&& output, Scalar alpha, MatrixMdspan&& matrix, InputMdspan&& input, Scalar beta)
97{
98 auto output_stage = try_mdspan_vector_stage(output);
99 auto matrix_stage = try_mdspan_matrix_stage(matrix);
100 auto input_stage = try_mdspan_vector_stage(input);
101 if (!output_stage || !matrix_stage || !input_stage)
102 {
104 }
105
106 if (output_stage->needs_conjugation || input_stage->needs_conjugation)
107 {
109 }
110
111 auto const matrix_operand = blas_readable_matrix(*matrix_stage);
112 if (!blas_trans_char_is_supported<Scalar>(matrix_operand.transform))
113 {
115 }
116
117 detail::gemv(blas_writable_vector(*output_stage), matrix_operand, blas_readable_vector(*input_stage), alpha, beta);
119}
120
122template <uni20::BlasScalar Scalar, class OutputMdspan, class MatrixMdspan, class InputMdspan>
123 requires detail::writable_gemv_vector_for<std::remove_cvref_t<OutputMdspan>, Scalar> &&
124 detail::readable_gemv_mdspan_for<std::remove_cvref_t<MatrixMdspan>, Scalar, 2> &&
125 detail::readable_gemv_mdspan_for<std::remove_cvref_t<InputMdspan>, Scalar, 1>
126void gemv(OutputMdspan&& output, Scalar alpha, MatrixMdspan&& matrix, InputMdspan&& input, Scalar beta)
127{
128 CHECK(kernel_attempt_succeeded(try_gemv(output, alpha, matrix, input, beta)));
129}
130
131} // namespace uni20::linalg::blas
Central include that selects the configured BLAS backend wrappers.
Concept for numeric scalar types (integer, real, or complex).
Definition scalar_concepts.hpp:81
locale_t value
Definition data_table.cpp:49
Allocation-free runtime results for kernel backend attempts.
Lower mdspan matrix views to provider-ready BLAS operands.
Lower rank-one mdspan views to provider-ready BLAS operands.
void gemv(char trans, blas_int m, blas_int n, BLASTYPE alpha, BLASTYPE const *A, blas_int lda, BLASTYPE const *x, blas_int incx, BLASTYPE beta, BLASTYPE *y, blas_int incy)
Definition blasproto.hpp:129
Definition blas.hpp:18
constexpr auto blas_writable_vector(MdspanVectorStage< Scalar, Handle > const &stage) -> BlasWritableVector< Scalar, Handle >
Return the provider-ready writable operand for a staged mdspan vector.
Definition mdspan_vector.hpp:81
constexpr blas_int transformed_cols(blas_int rows, blas_int cols, MatrixTransform transform)
Columns produced by applying transform to an untransformed matrix.
Definition blas_matrix.hpp:145
constexpr blas_int transformed_rows(blas_int rows, blas_int cols, MatrixTransform transform)
Rows produced by applying transform to an untransformed matrix.
Definition blas_matrix.hpp:139
auto try_mdspan_matrix_stage(Mdspan const &span) -> std::optional< MdspanMatrixStage< std::remove_cv_t< typename Mdspan::element_type >, detail::span_data_t< Mdspan > > >
Build a matrix staging descriptor when direct provider lowering is possible.
Definition mdspan_matrix.hpp:202
auto try_mdspan_vector_stage(Mdspan const &span) -> std::optional< MdspanVectorStage< std::remove_cv_t< typename Mdspan::element_type >, typename Mdspan::data_handle_type > >
Build an mdspan vector staging descriptor when direct BLAS lowering is possible.
Definition mdspan_vector.hpp:40
constexpr auto blas_readable_vector(MdspanVectorStage< Scalar, Handle > const &stage) -> BlasReadableVector< Scalar, Handle >
Return the provider-ready readable storage operand for a staged mdspan vector.
Definition mdspan_vector.hpp:92
constexpr auto blas_readable_matrix(MdspanMatrixStage< Scalar, Handle > const &stage) -> BlasReadableMatrix< Scalar, Handle >
Return the provider-ready readable operand for a staged mdspan matrix.
Definition mdspan_matrix.hpp:238
void gemv(OutputMdspan &&output, Scalar alpha, MatrixMdspan &&matrix, InputMdspan &&input, Scalar beta)
Direct no-copy BLAS GEMV from mdspan-like operands.
Definition blas/gemv.hpp:126
KernelAttempt try_gemv(OutputMdspan &&output, Scalar alpha, MatrixMdspan &&matrix, InputMdspan &&input, Scalar beta)
Try a direct no-copy BLAS GEMV from mdspan-like operands.
Definition blas/gemv.hpp:96
constexpr bool kernel_attempt_succeeded(KernelAttempt attempt) noexcept
Return whether a backend performed the operation.
Definition kernel_attempt.hpp:40
KernelAttempt
Result of one runtime kernel backend attempt.
Definition kernel_attempt.hpp:27
mpreal beta(mpreal const &a, mpreal const &x)
Real Beta function; positive rational/integer pairs retain exact values.
Definition mpreal_special.hpp:164
#define CHECK(cond,...)
Definition trace.hpp:299
#define CHECK_EQUAL(a, b,...)
Definition trace.hpp:309