Uni20
Asynchronous tensor and runtime library.
Loading...
Searching...
No Matches
linalg/backends/cpu/gemm.hpp
Go to the documentation of this file.
1#pragma once
2
17
18#include <concepts>
19#include <type_traits>
20#include <utility>
21
22namespace uni20::linalg
23{
24namespace detail
25{
26template <class OutputMdspan, class LhsMdspan, class RhsMdspan>
29
30template <class OutputMdspan, class Scalar, class LhsMdspan, class RhsMdspan>
31consteval bool cpu_gemm_mdspan_types_compatible()
32{
37}
38
39template <class OutputTensor, class LhsMdspan, class RhsMdspan>
40concept HostAssignProductAccess =
41 HostGemmMdspanAccess<std::remove_cvref_t<decltype(uni20::mdspec_of(std::declval<OutputTensor&>()))>, LhsMdspan,
42 RhsMdspan>;
43
44template <class OutputTensor, class Scalar, class LhsMdspan, class RhsMdspan>
45consteval bool cpu_assign_product_types_compatible()
46{
47 using output_span = std::remove_cvref_t<decltype(uni20::mdspec_of(std::declval<OutputTensor&>()))>;
48 return cpu_gemm_mdspan_types_compatible<output_span, Scalar, LhsMdspan, RhsMdspan>();
49}
50
51template <uni20::MutableRankedMdspecLike<2> OutputMdspan, uni20::Scalar Scalar, uni20::RankedMdspecLike<2> LhsMdspan,
52 uni20::RankedMdspecLike<2> RhsMdspan>
53 requires HostGemmMdspanAccess<OutputMdspan, LhsMdspan, RhsMdspan>
54KernelAttempt try_cpu_gemm(OutputMdspan& output, Scalar alpha, LhsMdspan& lhs, RhsMdspan& rhs, Scalar beta)
55{
56 auto output_access = acquire_host_write_access_sync(output);
57 auto lhs_access = acquire_host_read_access_sync(lhs);
58 auto rhs_access = acquire_host_read_access_sync(rhs);
59 auto output_span = output_access.mdspan();
60 auto lhs_span = lhs_access.mdspan();
61 auto rhs_span = rhs_access.mdspan();
62 uni20::linalg::cpu::gemm(output_span, alpha, lhs_span, rhs_span, beta);
64}
65} // namespace detail
66
68template <uni20::MutableRankedMdspecLike<2> OutputMdspan, uni20::Scalar Scalar, uni20::RankedMdspecLike<2> LhsMdspan,
69 uni20::RankedMdspecLike<2> RhsMdspan>
70 requires detail::HostGemmMdspanAccess<OutputMdspan, LhsMdspan, RhsMdspan>
71consteval auto kernel_accepts_types(CpuReferenceBackend const&, gemm_op const&, OutputMdspan&, Scalar const&,
72 LhsMdspan&, RhsMdspan&, Scalar const&)
73{
74 if constexpr (!has_runtime_precision_v<Scalar> &&
75 detail::cpu_gemm_mdspan_types_compatible<OutputMdspan, Scalar, LhsMdspan, RhsMdspan>())
76 return kernel_types_yes;
77 else
78 return kernel_types_no;
79}
80
82template <uni20::MutableRankedMdspecLike<2> OutputMdspan, uni20::Scalar Scalar, uni20::RankedMdspecLike<2> LhsMdspan,
83 uni20::RankedMdspecLike<2> RhsMdspan>
84 requires detail::HostGemmMdspanAccess<OutputMdspan, LhsMdspan, RhsMdspan>
85KernelAttempt try_kernel(CpuReferenceBackend, gemm_op const&, OutputMdspan& output, Scalar alpha, LhsMdspan& lhs,
86 RhsMdspan& rhs, Scalar beta)
87{
88 return detail::try_cpu_gemm(output, alpha, lhs, rhs, beta);
89}
90
91#if UNI20_HAS_MPREAL
94template <MutableRankedMdspecLike<2> C, Scalar S, RankedMdspecLike<2> A, RankedMdspecLike<2> B>
95 requires has_runtime_precision_v<S> && detail::HostGemmMdspanAccess<C, A, B>
96consteval auto kernel_accepts_types(CpuReferenceBackend, gemm_op const&, C&, S const&, A&, B&, S const&, Precision)
97{
98 if constexpr (detail::cpu_gemm_mdspan_types_compatible<C, S, A, B>())
99 return kernel_types_maybe;
100 else
101 return kernel_types_no;
102}
103
107template <MutableRankedMdspecLike<2> C, Scalar S, RankedMdspecLike<2> A, RankedMdspecLike<2> B>
108 requires has_runtime_precision_v<S> && detail::HostGemmMdspanAccess<C, A, B>
109KernelAttempt try_kernel(CpuReferenceBackend, gemm_op const&, C& c, S const& alpha, A& a, B& b, S const& beta,
110 Precision p)
111{
112 if (!p.is_exact()) return KernelAttempt::unsupported_instance;
113 return detail::try_cpu_gemm(c, alpha, a, b, beta);
114}
115#endif
116
118template <uni20::MutableRankedTensorView<2> OutputTensor, uni20::Scalar Scalar, uni20::RankedMdspecLike<2> LhsMdspan,
119 uni20::RankedMdspecLike<2> RhsMdspan>
120 requires detail::HostAssignProductAccess<OutputTensor, LhsMdspan, RhsMdspan>
121consteval auto kernel_accepts_types(CpuReferenceBackend const&, assign_product_op const&, OutputTensor&, Scalar const&,
122 LhsMdspan&, RhsMdspan&)
123{
124 if constexpr (!has_runtime_precision_v<Scalar> &&
125 detail::cpu_assign_product_types_compatible<OutputTensor, Scalar, LhsMdspan, RhsMdspan>())
126 return kernel_types_yes;
127 else
128 return kernel_types_no;
129}
130
132template <uni20::MutableRankedTensorView<2> OutputTensor, uni20::Scalar Scalar, uni20::RankedMdspecLike<2> LhsMdspan,
133 uni20::RankedMdspecLike<2> RhsMdspan>
134 requires detail::HostAssignProductAccess<OutputTensor, LhsMdspan, RhsMdspan>
136 LhsMdspan& lhs, RhsMdspan& rhs)
137{
138 auto const shape = detail::matrix_product_shape(lhs, rhs);
139 uni20::prepare_output(output, shape);
140 auto output_span = uni20::mdspec_of(output);
141 return detail::try_cpu_gemm(output_span, alpha, lhs, rhs, Scalar{});
142}
143
145template <uni20::MutableRankedTensorView<2> OutputTensor, uni20::Scalar Scalar, uni20::RankedMdspecLike<2> LhsMdspan,
146 uni20::RankedMdspecLike<2> RhsMdspan>
147 requires detail::HostAssignProductAccess<OutputTensor, LhsMdspan, RhsMdspan>
149 async::shared_storage<OutputTensor>&, Scalar const&, LhsMdspan&, RhsMdspan&)
150{
151 if constexpr (!has_runtime_precision_v<Scalar> &&
152 detail::cpu_assign_product_types_compatible<OutputTensor, Scalar, LhsMdspan, RhsMdspan>())
153 return kernel_types_yes;
154 else
155 return kernel_types_no;
156}
157
159template <uni20::MutableRankedTensorView<2> OutputTensor, uni20::Scalar Scalar, uni20::RankedMdspecLike<2> LhsMdspan,
160 uni20::RankedMdspecLike<2> RhsMdspan>
161 requires detail::HostAssignProductAccess<OutputTensor, LhsMdspan, RhsMdspan>
163 async::shared_storage<OutputTensor>& output_storage, Scalar alpha, LhsMdspan& lhs,
164 RhsMdspan& rhs)
165{
166 auto const shape = detail::matrix_product_shape(lhs, rhs);
167 auto& output = uni20::prepare_output(output_storage, shape);
168 auto output_span = uni20::mdspec_of(output);
169 return detail::try_cpu_gemm(output_span, alpha, lhs, rhs, Scalar{});
170}
171
172} // namespace uni20::linalg
RAII leases that resolve device descriptors and tensor views to mdspans.
Exact arithmetic or an explicit binary working precision.
Definition core/precision.hpp:13
A lightweight, thread-safe, reference-counted storage for a single object.
Definition shared_storage.hpp:94
Mdspec metadata supporting host read acquisition.
Definition access.hpp:688
Mutable mdspec metadata supporting host write acquisition.
Definition access.hpp:694
Concept for numeric scalar types (integer, real, or complex).
Definition scalar_concepts.hpp:81
Report whether resolved mdspans support reference CPU GEMM expressions.
Definition linalg/cpu/gemm.hpp:22
Operation-tag backend dispatch over tensor-view operands.
Accessor-respecting reference CPU GEMM for resolved mdspans.
Backend-independent dense matrix-product shape validation.
Definition cli.cpp:6
void gemm(OutputMdspan &&output, Scalar alpha, LhsMdspan &&lhs, RhsMdspan &&rhs, Scalar beta)
Execute reference CPU GEMM on resolved mdspans.
Definition linalg/cpu/gemm.hpp:41
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
constexpr KernelAcceptance< KernelTypeAcceptance::yes > kernel_types_yes
Report that a backend accepts every instance of the argument types.
Definition dispatch_error.hpp:40
Definition data_table.cpp:8
std::remove_cvref_t< decltype(std::declval< detail::host_read_mdspan_lease_t< Mdspec > & >().mdspan())> host_read_mdspan_t
Read-only mdspan type resolved by host descriptor acquisition.
Definition access.hpp:679
Output & prepare_output(Output &output, RequiredExtents const &required)
Prepare a mutable tensor output with the specified shape.
Definition tensor/output.hpp:104
auto acquire_host_read_access_sync(Mdspan const &mdspan)
Acquire a directly host-accessible read-only mdspan.
Definition access.hpp:616
std::remove_cvref_t< decltype(std::declval< detail::host_write_mdspan_lease_t< Mdspec > & >().mdspan())> host_write_mdspan_t
Writable mdspan type resolved by host descriptor acquisition.
Definition access.hpp:684
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
auto acquire_host_write_access_sync(Mdspan &mdspan)
Acquire a directly host-accessible writable mdspan.
Definition access.hpp:626
Backend-independent operation values used with normalized kernel operands.
Backend value for the reference host CPU dense linalg oracle.
Definition backend_selector.hpp:55
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.