Uni20
Asynchronous tensor and runtime library.
Loading...
Searching...
No Matches
linalg/async/contract.hpp
Go to the documentation of this file.
1#pragma once
2
17
18#include <array>
19#include <cstddef>
20#include <memory>
21#include <tuple>
22#include <utility>
23
24namespace uni20::linalg
25{
26namespace detail
27{
28template <class BackendSelector, uni20::AsyncTensorOutput OutputTensor, uni20::TensorView LhsTensor,
29 uni20::TensorView RhsTensor, class AlphaAwaiter, class BetaAwaiter, std::size_t LhsRank, std::size_t RhsRank,
30 std::size_t ContractedRank>
31async::AsyncTask co_contract(BackendSelector const selector, async::WriteBuffer<OutputTensor> output,
33 BetaAwaiter beta, ContractionAxes<LhsRank, RhsRank, ContractedRank> axes)
34{
35 auto output_awaiter = uni20::detail::mutable_async_tensor_awaiter(output);
36 auto awaited = co_await async::all(output_awaiter, lhs, rhs, alpha, beta);
37 decltype(auto) output_value = uni20::detail::mutable_async_tensor_value<OutputTensor>(std::get<0>(awaited));
38 auto const& lhs_value = std::get<1>(awaited);
39 auto const& rhs_value = std::get<2>(awaited);
40 using scalar_type = uni20::tensor_element_t<OutputTensor>;
41 scalar_type const alpha_value = static_cast<scalar_type>(std::get<3>(awaited));
42 scalar_type const beta_value = static_cast<scalar_type>(std::get<4>(awaited));
43
44 auto const required_extents = contraction_output_extents(lhs_value, rhs_value, axes);
45 uni20::require_output(output_value, required_extents);
46 auto output_descriptor = uni20::mdspec_of(output_value);
47 auto lhs_descriptor = uni20::mdspec_of(lhs_value);
48 auto rhs_descriptor = uni20::mdspec_of(rhs_value);
49 auto operation = contract_op<LhsRank, RhsRank, ContractedRank>{.axes = std::move(axes)};
50 co_await co_dispatch_kernel(selector, std::move(operation), output_descriptor, alpha_value, lhs_descriptor,
51 rhs_descriptor, beta_value);
52 co_return;
53}
54
55template <class BackendSelector, uni20::AsyncTensorOutput OutputTensor, uni20::TensorView LhsTensor,
56 uni20::TensorView RhsTensor, class AlphaAwaiter, class BetaAwaiter, std::size_t LhsRank, std::size_t RhsRank,
57 std::size_t ContractedRank>
58void schedule_async_contract(BackendSelector selector, async::Async<OutputTensor>& output,
59 async::Async<LhsTensor> const& lhs, async::Async<RhsTensor> const& rhs, AlphaAwaiter alpha,
60 BetaAwaiter beta, ContractionAxes<LhsRank, RhsRank, ContractedRank> axes)
61{
62 auto const* const output_queue = std::addressof(output.queue());
63 ERROR_IF(output_queue == std::addressof(lhs.queue()) || output_queue == std::addressof(rhs.queue()),
64 "async contraction output must not share an epoch queue with an input");
65 auto task = co_contract(std::move(selector), output.write(), lhs.read(), rhs.read(), std::move(alpha),
66 std::move(beta), std::move(axes));
67 task.debug_name("contract");
68 async::schedule(std::move(task));
69}
70} // namespace detail
71
75template <KernelBackendSelector BackendSelector, uni20::AsyncTensorOutput OutputTensor, uni20::TensorView LhsTensor,
76 uni20::TensorView RhsTensor, class Alpha, class Beta, std::size_t LhsRank, std::size_t RhsRank,
77 std::size_t ContractedRank>
78 requires detail::CompatibleContractionTensors<OutputTensor, LhsTensor, RhsTensor> &&
82 AsyncOperationScalar<Alpha, uni20::tensor_element_t<OutputTensor>> &&
83 AsyncOperationScalar<Beta, uni20::tensor_element_t<OutputTensor>>
84void contract(BackendSelector selector, async::Async<OutputTensor>& output, Alpha&& alpha,
87{
88 detail::schedule_async_contract(std::move(selector), output, lhs, rhs, async::read(std::forward<Alpha>(alpha)),
89 async::read(std::forward<Beta>(beta)), std::move(axes));
90}
91
93template <uni20::AsyncTensorOutput OutputTensor, uni20::TensorView LhsTensor, uni20::TensorView RhsTensor, class Alpha,
94 class Beta, std::size_t LhsRank, std::size_t RhsRank, std::size_t ContractedRank>
95 requires detail::CompatibleContractionTensors<OutputTensor, LhsTensor, RhsTensor> &&
99 AsyncOperationScalar<Alpha, uni20::tensor_element_t<OutputTensor>> &&
100 AsyncOperationScalar<Beta, uni20::tensor_element_t<OutputTensor>>
101void contract(async::Async<OutputTensor>& output, Alpha&& alpha, async::Async<LhsTensor> const& lhs,
103{
104 auto operation = contract_op<LhsRank, RhsRank, ContractedRank>{.axes = axes};
105 auto selector = select_backend_for<OutputTensor, LhsTensor, RhsTensor>(operation);
106 contract(std::move(selector), output, std::forward<Alpha>(alpha), lhs, rhs, std::move(axes),
107 std::forward<Beta>(beta));
108}
109
111template <KernelBackendSelector BackendSelector, uni20::AsyncTensorOutput OutputTensor, uni20::TensorView LhsTensor,
112 uni20::TensorView RhsTensor, class Alpha, class Beta, std::size_t ContractedRank>
113 requires detail::CompatibleContractionTensors<OutputTensor, LhsTensor, RhsTensor> &&
114 (ContractedRank <= uni20::tensor_mdspec_t<LhsTensor>::rank()) &&
115 (ContractedRank <= uni20::tensor_mdspec_t<RhsTensor>::rank()) &&
118 2 * ContractedRank) &&
119 AsyncOperationScalar<Alpha, uni20::tensor_element_t<OutputTensor>> &&
120 AsyncOperationScalar<Beta, uni20::tensor_element_t<OutputTensor>>
121void contract(BackendSelector selector, async::Async<OutputTensor>& output, Alpha&& alpha,
123 std::array<std::pair<std::size_t, std::size_t>, ContractedRank> requested_axes, Beta&& beta)
124{
125 constexpr std::size_t lhs_rank = uni20::tensor_mdspec_t<LhsTensor>::rank();
126 constexpr std::size_t rhs_rank = uni20::tensor_mdspec_t<RhsTensor>::rank();
127 auto axes = make_contraction_axes<lhs_rank, rhs_rank>(std::move(requested_axes));
128 contract(std::move(selector), output, std::forward<Alpha>(alpha), lhs, rhs, std::move(axes),
129 std::forward<Beta>(beta));
130}
131
133template <uni20::AsyncTensorOutput OutputTensor, uni20::TensorView LhsTensor, uni20::TensorView RhsTensor, class Alpha,
134 class Beta, std::size_t ContractedRank>
135 requires detail::CompatibleContractionTensors<OutputTensor, LhsTensor, RhsTensor> &&
136 (ContractedRank <= uni20::tensor_mdspec_t<LhsTensor>::rank()) &&
137 (ContractedRank <= uni20::tensor_mdspec_t<RhsTensor>::rank()) &&
140 2 * ContractedRank) &&
141 AsyncOperationScalar<Alpha, uni20::tensor_element_t<OutputTensor>> &&
142 AsyncOperationScalar<Beta, uni20::tensor_element_t<OutputTensor>>
143void contract(async::Async<OutputTensor>& output, Alpha&& alpha, async::Async<LhsTensor> const& lhs,
144 async::Async<RhsTensor> const& rhs,
145 std::array<std::pair<std::size_t, std::size_t>, ContractedRank> requested_axes, Beta&& beta)
146{
147 constexpr std::size_t lhs_rank = uni20::tensor_mdspec_t<LhsTensor>::rank();
148 constexpr std::size_t rhs_rank = uni20::tensor_mdspec_t<RhsTensor>::rank();
149 auto axes = make_contraction_axes<lhs_rank, rhs_rank>(std::move(requested_axes));
150 contract(output, std::forward<Alpha>(alpha), lhs, rhs, std::move(axes), std::forward<Beta>(beta));
151}
152
153} // namespace uni20::linalg
The Async<T> container: coroutine‐safe asynchronous read/write.
Coroutine-aware kernel dispatch with an ordinary blocking fallback.
Utilities for awaiting on Async<T>: co_await overload, all(), try_await().
Canonical host-oriented coroutine task type.
Definition async_task.hpp:196
Async<T> is a container for coroutine-safe asynchronous read/write.
Definition async/async.hpp:93
ReadBuffer< T > read() const
Begin an asynchronous read of the value.
Definition async/async.hpp:339
EpochQueue const & queue() const
Inspect the shared epoch queue.
Definition async/async.hpp:423
WriteBuffer< T > write()
Begin exclusive asynchronous access to the payload.
Definition async/async.hpp:346
RAII handle for reading the value from an Async container at a given epoch.
Definition buffers.hpp:53
Exclusive mutable-access buffer for one Async<T> epoch.
Definition buffers.hpp:859
Mutable Tensor output supported by async operation wrappers.
Definition linalg/async/concepts.hpp:25
MutableTensorView with a specified static rank.
Definition tensor/concepts.hpp:166
TensorView whose readable mdspec has a specified static rank.
Definition tensor/concepts.hpp:149
Tensor-level object exposing readable multidimensional metadata and a backend selector.
Definition tensor/concepts.hpp:82
Coroutine scheduler for AsyncTask.
Capabilities shared by asynchronous Tensor operation wrappers.
Shared output capabilities for Async Tensor operation wrappers.
Fixed-output pairwise Tensor contraction front end.
void schedule(AsyncTask &&task)
Schedule a task on the currently configured global scheduler.
Definition debug_scheduler.hpp:237
auto all(Aw &&... aw) noexcept
Build an awaitable that waits for all of the provided awaitables.
Definition awaiters.hpp:200
ReadBuffer< T > read(Async< T > const &a)
Convenience helper that forwards to Async<T>::read().
Definition async/async.hpp:540
Definition linalg/async.hpp:28
void contract(BackendSelector selector, async::Async< OutputTensor > &output, Alpha &&alpha, async::Async< LhsTensor > const &lhs, async::Async< RhsTensor > const &rhs, ContractionAxes< LhsRank, RhsRank, ContractedRank > axes, Beta &&beta)
Schedule a fixed-output pairwise contraction through an explicit selector.
Definition linalg/async/contract.hpp:84
auto contraction_output_extents(Lhs const &lhs, Rhs const &rhs, ContractionAxes< LhsRank, RhsRank, ContractedRank > const &axes) -> stdex::dextents< uni20::index_type, ContractionAxes< LhsRank, RhsRank, ContractedRank >::output_rank >
Validate paired extents and return the canonical contraction output shape.
Definition contraction_axes.hpp:141
async::AsyncTask co_dispatch_kernel(BackendSelector selector, Op op, Args &... args)
Dispatch a kernel from a coroutine without requiring coroutine wrappers for blocking backends.
Definition async/dispatch.hpp:106
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 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
mpreal beta(mpreal const &a, mpreal const &x)
Real Beta function; positive rational/integer pairs retain exact values.
Definition mpreal_special.hpp:164
std::remove_cvref_t< detail::normalized_const_mdspec_t< T > > tensor_mdspec_t
Normalized readable MdspecLike type exposed by a tensor-level object.
Definition tensor/concepts.hpp:123
Canonical contracted and surviving axes for two fixed-rank operands.
Definition contraction_axes.hpp:26
static constexpr std::size_t output_rank
Definition contraction_axes.hpp:35
Fixed-output pairwise tensor contraction operation.
Definition operation_tags.hpp:98
ContractionAxes< LhsRank, RhsRank, ContractedRank > axes
Definition operation_tags.hpp:100
#define ERROR_IF(cond,...)
Definition trace.hpp:389