23template <
class Mdspan,
class Scalar>
24concept readable_blas_mdspec_for =
25 blas_readable_mdspec<Mdspan, 2> && std::same_as<std::remove_cv_t<typename Mdspan::element_type>, Scalar>;
27template <
class Mdspan,
class Scalar>
28concept writable_blas_mdspec_for =
29 blas_writable_mdspec<Mdspan, 2> && std::same_as<std::remove_cv_t<typename Mdspan::element_type>, Scalar>;
31template <
class Mdspan,
class Scalar>
32concept readable_blas_mdspan_for =
33 blas_readable_mdspan<Mdspan, 2> && std::same_as<std::remove_cv_t<typename Mdspan::element_type>, Scalar> &&
34 std::convertible_to<typename Mdspan::data_handle_type, Scalar const*>;
36template <
class Mdspan,
class Scalar>
37concept writable_blas_mdspan_for =
38 blas_writable_mdspan<Mdspan, 2> && std::same_as<std::remove_cv_t<typename Mdspan::element_type>, Scalar> &&
39 std::convertible_to<typename Mdspan::data_handle_type, Scalar*>;
41constexpr blas_int logical_rows(blas_int rows, blas_int cols,
MatrixTransform transform)
46constexpr blas_int logical_cols(blas_int rows, blas_int cols,
MatrixTransform transform)
51template <
class Scalar,
class Handle>
52constexpr auto with_transform(BlasReadableMatrix<Scalar, Handle> matrix,
MatrixTransform transform)
53 -> BlasReadableMatrix<Scalar, Handle>
55 matrix.transform =
compose(transform, matrix.transform);
59template <uni20::BlasScalar Scalar,
class OutputHandle,
class LhsHandle,
class RhsHandle>
60 requires std::convertible_to<OutputHandle, Scalar*> && std::convertible_to<LhsHandle, Scalar const*> &&
61 std::convertible_to<RhsHandle, Scalar const*>
62void gemm(BlasWritableMatrix<Scalar, OutputHandle> output, BlasReadableMatrix<Scalar, LhsHandle> lhs,
63 BlasReadableMatrix<Scalar, RhsHandle> rhs, Scalar alpha, Scalar
beta)
65 auto const transa = blas_trans_char<Scalar>(lhs.transform);
66 auto const transb = blas_trans_char<Scalar>(rhs.transform);
68 blas_int
const lhs_rows = logical_rows(lhs.rows, lhs.cols, lhs.transform);
69 blas_int
const lhs_cols = logical_cols(lhs.rows, lhs.cols, lhs.transform);
70 blas_int
const rhs_rows = logical_rows(rhs.rows, rhs.cols, rhs.transform);
71 blas_int
const rhs_cols = logical_cols(rhs.rows, rhs.cols, rhs.transform);
76 if (output.rows == 0 || output.cols == 0)
81 Scalar
const*
const lhs_data = lhs.data;
82 Scalar
const*
const rhs_data = rhs.data;
83 Scalar*
const output_data = output.data;
84 ::uni20::blas::gemm(transa, transb, output.rows, output.cols, lhs_cols, alpha, lhs_data, lhs.leading_dimension,
85 rhs_data, rhs.leading_dimension,
beta, output_data, output.leading_dimension);
88template <uni20::BlasScalar Scalar>
struct GemmPlan
90 BlasWritableMatrix<Scalar, Scalar*> output{};
91 BlasReadableMatrix<Scalar, Scalar const*> lhs{};
92 BlasReadableMatrix<Scalar, Scalar const*> rhs{};
93 bool has_work =
false;
96template <uni20::BlasScalar Scalar>
struct GemmPreparation
99 GemmPlan<Scalar> plan{};
102struct GemmMetadataPreparation
105 MdspanMatrixMetadata output{};
106 MdspanMatrixMetadata lhs{};
107 MdspanMatrixMetadata rhs{};
108 bool has_work =
false;
111template <uni20::BlasScalar Scalar,
class Handle>
112auto provider_writable_matrix(BlasWritableMatrix<Scalar, Handle> matrix) -> BlasWritableMatrix<Scalar, Scalar*>
114 return {.data = matrix.data, .rows = matrix.rows, .cols = matrix.cols, .leading_dimension = matrix.leading_dimension};
117template <uni20::BlasScalar Scalar,
class Handle>
118auto provider_readable_matrix(BlasReadableMatrix<Scalar, Handle> matrix) -> BlasReadableMatrix<Scalar, Scalar const*>
120 return {.data = matrix.data,
123 .leading_dimension = matrix.leading_dimension,
124 .transform = matrix.transform};
127template <uni20::BlasScalar Scalar,
class OutputMdspan,
class LhsMdspan,
class RhsMdspan>
128 requires writable_blas_mdspec_for<std::remove_cvref_t<OutputMdspan>, Scalar> &&
129 readable_blas_mdspec_for<std::remove_cvref_t<LhsMdspan>, Scalar> &&
130 readable_blas_mdspec_for<std::remove_cvref_t<RhsMdspan>, Scalar>
131auto prepare_gemm_metadata(OutputMdspan&& output, LhsMdspan&& lhs, RhsMdspan&& rhs) -> GemmMetadataPreparation
137 if (output.extent(0) == 0 || output.extent(1) == 0)
141 if (lhs.extent(1) == 0)
149 if (!output_metadata || !lhs_metadata || !rhs_metadata)
157 if (output_metadata->needs_conjugation)
163 if (lhs_metadata->needs_conjugation)
168 if (rhs_metadata->needs_conjugation)
173 if (output_metadata->unit_stride_axis != 0)
175 auto const original_lhs_transform = lhs_transform;
179 if (!blas_trans_char_is_supported<Scalar>(lhs_transform) || !blas_trans_char_is_supported<Scalar>(rhs_transform))
185 .output = *output_metadata,
186 .lhs = *lhs_metadata,
187 .rhs = *rhs_metadata,
191template <uni20::BlasScalar Scalar,
class OutputMdspan,
class LhsMdspan,
class RhsMdspan>
192 requires writable_blas_mdspan_for<std::remove_cvref_t<OutputMdspan>, Scalar> &&
193 readable_blas_mdspan_for<std::remove_cvref_t<LhsMdspan>, Scalar> &&
194 readable_blas_mdspan_for<std::remove_cvref_t<RhsMdspan>, Scalar>
195auto prepare_gemm(OutputMdspan&& output, LhsMdspan&& lhs, RhsMdspan&& rhs)
197 using preparation_type = GemmPreparation<Scalar>;
198 auto metadata = prepare_gemm_metadata<Scalar>(output, lhs, rhs);
201 return preparation_type{.attempt = metadata.attempt};
204 auto output_stage = make_mdspan_matrix_stage(output, metadata.output);
205 auto lhs_stage = make_mdspan_matrix_stage(lhs, metadata.lhs);
206 auto rhs_stage = make_mdspan_matrix_stage(rhs, metadata.rhs);
208 if (metadata.output.unit_stride_axis == 0)
213 .plan = {.output = output_matrix, .lhs = lhs_matrix, .rhs = rhs_matrix, .has_work =
true}};
216 auto const lhs_matrix =
218 auto const rhs_matrix =
221 .plan = {.output = output_matrix, .lhs = lhs_matrix, .rhs = rhs_matrix, .has_work =
true}};
224template <uni20::BlasScalar Scalar>
void execute_gemm(GemmPlan<Scalar>
const& plan, Scalar alpha, Scalar
beta)
226 if (plan.has_work) gemm(plan.output, plan.lhs, plan.rhs, alpha,
beta);
237template <uni20::BlasScalar Scalar,
class OutputMdspan,
class LhsMdspan,
class RhsMdspan>
238 requires detail::writable_blas_mdspec_for<std::remove_cvref_t<OutputMdspan>, Scalar> &&
239 detail::readable_blas_mdspec_for<std::remove_cvref_t<LhsMdspan>, Scalar> &&
240 detail::readable_blas_mdspec_for<std::remove_cvref_t<RhsMdspan>, Scalar>
243 return detail::prepare_gemm_metadata<Scalar>(std::forward<OutputMdspan>(output), std::forward<LhsMdspan>(lhs),
244 std::forward<RhsMdspan>(rhs))
251template <uni20::BlasScalar Scalar,
class OutputMdspan,
class LhsMdspan,
class RhsMdspan>
252 requires detail::writable_blas_mdspan_for<std::remove_cvref_t<OutputMdspan>,
Scalar> &&
253 detail::readable_blas_mdspan_for<std::remove_cvref_t<LhsMdspan>,
Scalar> &&
254 detail::readable_blas_mdspan_for<std::remove_cvref_t<RhsMdspan>,
Scalar>
257 auto preparation = detail::prepare_gemm<Scalar>(std::forward<OutputMdspan>(output), std::forward<LhsMdspan>(lhs),
258 std::forward<RhsMdspan>(rhs));
261 detail::execute_gemm(preparation.plan, alpha,
beta);
266template <uni20::BlasScalar Scalar,
class OutputMdspan,
class LhsMdspan,
class RhsMdspan>
267 requires detail::writable_blas_mdspan_for<std::remove_cvref_t<OutputMdspan>,
Scalar> &&
268 detail::readable_blas_mdspan_for<std::remove_cvref_t<LhsMdspan>,
Scalar> &&
269 detail::readable_blas_mdspan_for<std::remove_cvref_t<RhsMdspan>,
Scalar>
Central include that selects the configured BLAS backend wrappers.
Concept for numeric scalar types (integer, real, or complex).
Definition scalar_concepts.hpp:81
Allocation-free runtime results for kernel backend attempts.
Lower mdspan matrix views to provider-ready BLAS operands.
void gemm(char transa, char transb, blas_int m, blas_int n, blas_int k, BLASTYPE alpha, BLASTYPE const *A, blas_int lda, BLASTYPE const *B, blas_int ldb, BLASTYPE beta, BLASTYPE *C, blas_int ldc)
Definition blasproto.hpp:121
KernelAttempt try_gemm(OutputMdspan &&output, Scalar alpha, LhsMdspan &&lhs, RhsMdspan &&rhs, Scalar beta)
Try a direct no-copy BLAS GEMM from mdspan-like operands.
Definition linalg/blas/gemm.hpp:255
constexpr MatrixTransform storage_transform(MdspanMatrixMetadata const &metadata)
Transform from the provider matrix shape to the logical mdspan shape.
Definition mdspan_matrix.hpp:211
void gemm(OutputMdspan &&output, Scalar alpha, LhsMdspan &&lhs, RhsMdspan &&rhs, Scalar beta)
Direct no-copy BLAS GEMM from mdspan-like operands.
Definition linalg/blas/gemm.hpp:270
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
MatrixTransform
Logical matrix transform independent of a provider-specific opcode, although it happens to coincide w...
Definition blas_matrix.hpp:23
constexpr auto blas_writable_matrix(MdspanMatrixStage< Scalar, Handle > const &stage) -> BlasWritableMatrix< Scalar, Handle >
Return the provider-ready writable operand for a staged mdspan matrix.
Definition mdspan_matrix.hpp:225
auto try_mdspan_matrix_metadata(Mdspan const &span) -> std::optional< MdspanMatrixMetadata >
Inspect matrix layout and accessor semantics without resolving a data handle.
Definition mdspan_matrix.hpp:99
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
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
KernelAttempt probe_gemm(OutputMdspan &&output, LhsMdspan &&lhs, RhsMdspan &&rhs)
Probe direct no-copy BLAS GEMM without invoking the provider.
Definition linalg/blas/gemm.hpp:241
constexpr MatrixTransform compose(MatrixTransform outer, MatrixTransform inner)
Compose two matrix transforms as outer(inner(A)).
Definition blas_matrix.hpp:58
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