Uni20
Asynchronous tensor and runtime library.
Loading...
Searching...
No Matches
ops/matrix_product.hpp
Go to the documentation of this file.
1#pragma once
2
14
15#include <concepts>
16#include <memory>
17#include <type_traits>
18#include <utility>
19
20namespace uni20::linalg
21{
22namespace detail
23{
24template <class OutputTensor, class InputTensor>
25[[nodiscard]] constexpr bool is_obvious_tensor_alias(OutputTensor& output, InputTensor const& input) noexcept
26{
27 if constexpr (std::same_as<std::remove_cvref_t<OutputTensor>, std::remove_cvref_t<InputTensor>>)
28 {
29 return static_cast<void const*>(std::addressof(output)) == static_cast<void const*>(std::addressof(input));
30 }
31 return false;
32}
33
34template <uni20::MutableRankedTensorView<2> OutputTensor, uni20::RankedTensorView<2> LhsTensor,
35 uni20::RankedTensorView<2> RhsTensor>
36void validate_matrix_product_aliasing(OutputTensor& output, LhsTensor const& lhs, RhsTensor const& rhs)
37{
38 ERROR_IF(is_obvious_tensor_alias(output, lhs) || is_obvious_tensor_alias(output, rhs),
39 "matrix product output must not alias an input tensor");
40}
41
42template <class OutputTensor, class LhsTensor, class RhsTensor>
43concept CompatibleMatrixProductTensors =
44 std::same_as<uni20::tensor_element_t<OutputTensor>, uni20::tensor_element_t<LhsTensor>> &&
45 std::same_as<uni20::tensor_element_t<OutputTensor>, uni20::tensor_element_t<RhsTensor>>;
46} // namespace detail
47
52template <KernelBackendSelector Selector, MutableRankedTensorView<2> Output, RankedTensorView<2> A,
53 RankedTensorView<2> B, class Alpha>
54 requires detail::CompatibleMatrixProductTensors<Output, A, B> && OperationScalar<Alpha, tensor_element_t<Output>>
55void assign_product(Selector&& selector, Output&& output, A const& a, B const& b, Alpha const& alpha,
56 std::optional<Precision> requested = {})
57{
59 detail::validate_matrix_product_aliasing(output, a, b);
60 auto p = requested ? *requested : common_default_precision(a, b);
61 require_precision<S>(p);
62 if constexpr (has_runtime_precision_v<S>)
63 {
64 prepare_output(output, detail::matrix_product_shape(a, b), p);
65 gemm(std::forward<Selector>(selector), output, S(alpha), a, b, S{}, p);
66 }
67 else
68 {
69 auto ad = mdspec_of(a);
70 auto bd = mdspec_of(b);
71 dispatch_kernel(std::forward<Selector>(selector), assign_product_op{}, output, S(alpha), ad, bd);
72 }
73}
74
76template <MutableRankedTensorView<2> Output, RankedTensorView<2> A, RankedTensorView<2> B, class Alpha>
77 requires detail::CompatibleMatrixProductTensors<Output, A, B> && OperationScalar<Alpha, tensor_element_t<Output>>
78void assign_product(Output&& output, A const& a, B const& b, Alpha const& alpha, std::optional<Precision> p = {})
79{
80 assign_product(select_backend(assign_product_op{}, output, a, b), std::forward<Output>(output), a, b, alpha, p);
81}
82
84template <KernelBackendSelector Selector, MutableRankedTensorView<2> Output, RankedTensorView<2> A,
85 RankedTensorView<2> B>
86 requires detail::CompatibleMatrixProductTensors<Output, A, B>
87void assign_product(Selector&& selector, Output&& output, A const& a, B const& b, std::optional<Precision> p = {})
88{
89 assign_product(std::forward<Selector>(selector), std::forward<Output>(output), a, b, tensor_element_t<Output>{1}, p);
90}
91
93template <MutableRankedTensorView<2> Output, RankedTensorView<2> A, RankedTensorView<2> B>
94 requires detail::CompatibleMatrixProductTensors<Output, A, B>
95void assign_product(Output&& output, A const& a, B const& b, std::optional<Precision> p = {})
96{
97 assign_product(select_backend(assign_product_op{}, output, a, b), std::forward<Output>(output), a, b,
98 tensor_element_t<Output>{1}, p);
99}
100
105template <KernelBackendSelector Selector, MutableRankedTensorView<2> Output, RankedTensorView<2> A,
106 RankedTensorView<2> B, class Alpha>
107 requires detail::CompatibleMatrixProductTensors<Output, A, B> && OperationScalar<Alpha, tensor_element_t<Output>>
108void add_product(Selector&& selector, Output&& output, A const& a, B const& b, Alpha const& alpha,
109 std::optional<Precision> requested = {})
110{
111 using S = tensor_element_t<Output>;
112 detail::validate_matrix_product_aliasing(output, a, b);
113 require_output(output, detail::matrix_product_shape(a, b));
114 gemm(std::forward<Selector>(selector), std::forward<Output>(output), S(alpha), a, b, S{1}, requested);
115}
116
118template <MutableRankedTensorView<2> Output, RankedTensorView<2> A, RankedTensorView<2> B, class Alpha>
119 requires detail::CompatibleMatrixProductTensors<Output, A, B> && OperationScalar<Alpha, tensor_element_t<Output>>
120void add_product(Output&& output, A const& a, B const& b, Alpha const& alpha, std::optional<Precision> p = {})
121{
122 add_product(select_backend(gemm_op{}, output, a, b), std::forward<Output>(output), a, b, alpha, p);
123}
124
126template <KernelBackendSelector Selector, MutableRankedTensorView<2> Output, RankedTensorView<2> A,
127 RankedTensorView<2> B>
128 requires detail::CompatibleMatrixProductTensors<Output, A, B>
129void add_product(Selector&& selector, Output&& output, A const& a, B const& b, std::optional<Precision> p = {})
130{
131 add_product(std::forward<Selector>(selector), std::forward<Output>(output), a, b, tensor_element_t<Output>{1}, p);
132}
133
135template <MutableRankedTensorView<2> Output, RankedTensorView<2> A, RankedTensorView<2> B>
136 requires detail::CompatibleMatrixProductTensors<Output, A, B>
137void add_product(Output&& output, A const& a, B const& b, std::optional<Precision> p = {})
138{
139 add_product(select_backend(gemm_op{}, output, a, b), std::forward<Output>(output), a, b, tensor_element_t<Output>{1},
140 p);
141}
142
143} // namespace uni20::linalg
Fixed-output Tensor GEMM front end.
Backend-independent dense matrix-product shape validation.
Configured gateway to Uni20's mdspan implementation.
Definition linalg/async.hpp:28
void gemm(BackendSelector selector, async::Async< OutputTensor > &output, Alpha &&alpha, async::Async< LhsTensor > const &lhs, async::Async< RhsTensor > const &rhs, Beta &&beta, std::optional< Precision > p={})
Schedule fixed-output GEMM with an explicit backend selector.
Definition async/matrix_product.hpp:162
void assign_product(BackendSelector selector, async::Async< OutputTensor > &output, async::Async< LhsTensor > const &lhs, async::Async< RhsTensor > const &rhs, Alpha &&alpha, std::optional< Precision > p={})
Schedule output = alpha * lhs * rhs with an explicit backend selector.
Definition async/matrix_product.hpp:198
void add_product(BackendSelector selector, async::Async< OutputTensor > &output, async::Async< LhsTensor > const &lhs, async::Async< RhsTensor > const &rhs, Alpha &&alpha, std::optional< Precision > p={})
Schedule output += alpha * lhs * rhs with an explicit backend selector.
Definition async/matrix_product.hpp:234
constexpr auto select_backend(Operation const &operation, FirstTensor const &, RestTensors const &...)
Select the default backend list for an operation on Tensor operands.
Definition backend_selector.hpp:252
void dispatch_kernel(BackendSelector &&selector, Op op, Args &&... args)
Normalize a selector and dispatch or report that every eligible backend declined.
Definition dispatch.hpp:374
Definition data_table.cpp:8
Output & prepare_output(Output &output, RequiredExtents const &required)
Prepare a mutable tensor output with the specified shape.
Definition tensor/output.hpp:104
void require_output(Output const &output, RequiredExtents const &required)
Require an existing tensor output to have the specified shape.
Definition tensor/output.hpp:84
constexpr Precision common_default_precision(A const &a, B const &b)
Select a binary operation's default without inspecting element precisions.
Definition tensor/precision.hpp:43
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
std::remove_cv_t< typename tensor_mdspec_t< T >::element_type > tensor_element_t
Scalar value type exposed by a tensor-level object.
Definition tensor/concepts.hpp:126
Shape preparation contracts for tensor operation outputs.
#define ERROR_IF(cond,...)
Definition trace.hpp:389