Uni20
Asynchronous tensor and runtime library.
Loading...
Searching...
No Matches
async/linear_solve.hpp
Go to the documentation of this file.
1#pragma once
2
15
16#include <concepts>
17#include <memory>
18#include <tuple>
19#include <type_traits>
20#include <utility>
21
22namespace uni20::linalg
23{
24namespace detail
25{
26template <class CoefficientTensor, class RhsTensor>
27using preserving_solve_result_t = std::remove_cvref_t<decltype(uni20::linalg::solve(
28 std::declval<CoefficientTensor const&>(), std::declval<RhsTensor const&>()))>;
29
30template <class CoefficientTensor, class RhsTensor> [[nodiscard]] constexpr auto select_async_solve_backend()
31{
32 using work_type = preserving_solve_result_t<CoefficientTensor, RhsTensor>;
33 return select_backend_for<work_type, work_type>(linear_solve_op{});
34}
35
36template <class BackendSelector, class ResultTensor, uni20::RankedTensorView<2> CoefficientTensor,
37 uni20::RankedTensorView<2> RhsTensor>
38async::AsyncTask co_preserving_solve(BackendSelector const selector, async::WriteBuffer<ResultTensor> output,
40 async::ReadBuffer<RhsTensor> right_hand_sides, std::optional<Precision> p)
41{
42 auto output_storage = output.storage();
43 auto awaited = co_await async::all(output_storage, coefficients, right_hand_sides);
44 auto& storage = std::get<0>(awaited);
45 auto const& coefficient_value = std::get<1>(awaited);
46 auto const& rhs_value = std::get<2>(awaited);
47
48 auto result = uni20::linalg::solve(selector, coefficient_value, rhs_value, p);
49 storage.emplace(std::move(result));
50 co_return;
51}
52
53template <class BackendSelector, uni20::AsyncTensorOutput CoefficientTensor, uni20::AsyncTensorOutput RhsTensor>
54async::AsyncTask co_solve_inplace(BackendSelector const selector, async::WriteBuffer<CoefficientTensor> coefficients,
55 async::WriteBuffer<RhsTensor> right_hand_sides, std::optional<Precision> p)
56{
57 auto coefficient_awaiter = uni20::detail::mutable_async_tensor_awaiter(coefficients);
58 auto rhs_awaiter = uni20::detail::mutable_async_tensor_awaiter(right_hand_sides);
59 auto awaited = co_await async::all(coefficient_awaiter, rhs_awaiter);
60 decltype(auto) coefficient_value = uni20::detail::mutable_async_tensor_value<CoefficientTensor>(std::get<0>(awaited));
61 decltype(auto) rhs_value = uni20::detail::mutable_async_tensor_value<RhsTensor>(std::get<1>(awaited));
62
63 uni20::linalg::solve_inplace(selector, coefficient_value, rhs_value, p);
64 co_return;
65}
66
67template <class BackendSelector, uni20::RankedTensorView<2> CoefficientTensor, uni20::RankedTensorView<2> RhsTensor>
68[[nodiscard]] auto
69schedule_preserving_solve(BackendSelector selector, async::Async<CoefficientTensor> const& coefficients,
70 async::Async<RhsTensor> const& right_hand_sides, std::optional<Precision> p = {})
71{
72 using result_type = preserving_solve_result_t<CoefficientTensor, RhsTensor>;
74 output.debug_name("solve.solution");
75 auto task = co_preserving_solve(std::move(selector), output.write(), coefficients.read(), right_hand_sides.read(), p);
76 task.debug_name("solve");
77 async::schedule(std::move(task));
78 return output;
79}
80
81template <class BackendSelector, uni20::AsyncTensorOutput CoefficientTensor, uni20::AsyncTensorOutput RhsTensor>
82void schedule_solve_inplace(BackendSelector selector, async::Async<CoefficientTensor>& coefficients,
83 async::Async<RhsTensor>& right_hand_sides, std::optional<Precision> p = {})
84{
85 ERROR_IF(std::addressof(coefficients.queue()) == std::addressof(right_hand_sides.queue()),
86 "async solve workspaces must not share an epoch queue");
87 auto task = co_solve_inplace(std::move(selector), coefficients.write(), right_hand_sides.write(), p);
88 task.debug_name("solve_inplace");
89 async::schedule(std::move(task));
90}
91} // namespace detail
92
96template <KernelBackendSelector BackendSelector, uni20::RankedTensorView<2> CoefficientTensor,
97 uni20::RankedTensorView<2> RhsTensor>
99 std::same_as<uni20::tensor_element_t<CoefficientTensor>, uni20::tensor_element_t<RhsTensor>>
100[[nodiscard]] auto solve(BackendSelector selector, async::Async<CoefficientTensor> const& coefficients,
101 async::Async<RhsTensor> const& right_hand_sides, std::optional<Precision> p = {})
102{
103 return detail::schedule_preserving_solve(std::move(selector), coefficients, right_hand_sides, p);
104}
105
107template <uni20::RankedTensorView<2> CoefficientTensor, uni20::RankedTensorView<2> RhsTensor>
109 std::same_as<uni20::tensor_element_t<CoefficientTensor>, uni20::tensor_element_t<RhsTensor>>
110[[nodiscard]] auto solve(async::Async<CoefficientTensor> const& coefficients,
111 async::Async<RhsTensor> const& right_hand_sides, std::optional<Precision> p = {})
112{
113 auto selector = detail::select_async_solve_backend<CoefficientTensor, RhsTensor>();
114 return detail::schedule_preserving_solve(std::move(selector), coefficients, right_hand_sides, p);
115}
116
122template <KernelBackendSelector BackendSelector, uni20::AsyncTensorOutput CoefficientTensor,
123 uni20::AsyncTensorOutput RhsTensor>
124 requires detail::CompatibleLinearSolveTensors<CoefficientTensor, RhsTensor>
125void solve_inplace(BackendSelector selector, async::Async<CoefficientTensor>& coefficients,
126 async::Async<RhsTensor>& right_hand_sides, std::optional<Precision> p = {})
127{
128 detail::schedule_solve_inplace(std::move(selector), coefficients, right_hand_sides, p);
129}
130
133template <uni20::AsyncTensorOutput CoefficientTensor, uni20::AsyncTensorOutput RhsTensor>
134 requires detail::CompatibleLinearSolveTensors<CoefficientTensor, RhsTensor>
136 std::optional<Precision> p = {})
137{
138 auto selector = select_backend_for<CoefficientTensor, RhsTensor>(linear_solve_op{});
139 detail::schedule_solve_inplace(std::move(selector), coefficients, right_hand_sides, p);
140}
141
142} // namespace uni20::linalg
The Async<T> container: coroutine‐safe asynchronous read/write.
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
Async & debug_name(std::string const &label)
Assign an optional debug label for task-registry graph output.
Definition async/async.hpp:212
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
auto storage() &
Awaiter yielding direct access to writer shared storage.
Definition buffers.hpp:1029
Mutable Tensor output supported by async operation wrappers.
Definition linalg/async/concepts.hpp:25
Concept for types that are either real or complex.
Definition scalar_concepts.hpp:87
Coroutine scheduler for AsyncTask.
Shared output capabilities for Async Tensor operation wrappers.
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
Definition linalg/async.hpp:28
auto solve(BackendSelector selector, async::Async< CoefficientTensor > const &coefficients, async::Async< RhsTensor > const &right_hand_sides, std::optional< Precision > p={})
Schedule a preserving dense general solve through an explicit selector.
Definition async/linear_solve.hpp:100
void solve_inplace(BackendSelector selector, async::Async< CoefficientTensor > &coefficients, async::Async< RhsTensor > &right_hand_sides, std::optional< Precision > p={})
Schedule a destructive dense general solve through an explicit selector.
Definition async/linear_solve.hpp:125
Definition data_table.cpp:8
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
Destructive-workspace and value-producing dense general solves.
#define ERROR_IF(cond,...)
Definition trace.hpp:389