33template <
class OutputTensor,
class InputTensor>
34concept AsyncCopyTensors = AsyncTensorOutput<OutputTensor> && TensorView<InputTensor> &&
35 (tensor_mdspec_t<OutputTensor>::rank() == tensor_mdspec_t<InputTensor>::rank()) &&
36 std::same_as<tensor_element_t<OutputTensor>, tensor_element_t<InputTensor>>;
39template <cuda::BufferMdspec InputMdspan>
40[[nodiscard]] cuda::DeviceResources& cuda_copy_resources(InputMdspan
const& input)
42 return input.data_descriptor().buffer().resources();
46template <AsyncTensorOutput OutputTensor, TensorView InputTensor>
48 InputTensor
const& input)
56 using extents_type = tensor_extents_t<OutputTensor>;
57 auto const extents = convert_tensor_extents<extents_type>(input.extents());
58 if constexpr (std::constructible_from<OutputTensor, extents_type const&>)
60 if constexpr (std::constructible_from<OutputTensor, uninitialized_t, extents_type const&>)
63 return storage.
emplace(extents);
66 else if constexpr (std::same_as<tensor_storage_policy_t<OutputTensor>, CudaStorage> &&
67 cuda::BufferMdspec<tensor_mdspec_t<InputTensor>>)
79template <
class BackendSelector, AsyncTensorOutput OutputTensor, TensorView InputTensor>
83 if constexpr (async::is_async_alias_v<OutputTensor>)
85 AsyncAliasWriteDescriptorAwaiter output_descriptor_awaiter(output);
86 auto awaited =
co_await async::all(output_descriptor_awaiter, input);
87 auto output_value = std::get<0>(awaited);
88 auto const& input_value = std::get<1>(awaited);
90 auto output_descriptor =
mdspec_of(output_value);
91 auto input_descriptor =
mdspec_of(input_value);
96 auto output_storage = output.
storage();
97 auto awaited =
co_await async::all(output_storage, input);
98 auto& storage = std::get<0>(awaited);
99 auto const& input_value = std::get<1>(awaited);
100 auto& output_value = prepare_async_copy_output(storage, input_value);
101 auto output_descriptor =
mdspec_of(output_value);
102 auto input_descriptor =
mdspec_of(input_value);
108template <
class BackendSelector, AsyncTensorOutput OutputTensor, TensorView InputTensor>
113 "async copy output must not share an epoch queue with its input");
114 auto task = co_copy(std::move(selector), output.
write(), input.
read());
115 task.debug_name(
"copy");
119template <TensorView InputTensor>
120using async_materialized_tensor_t =
121 std::remove_cvref_t<decltype(uni20::make_tensor(std::declval<InputTensor const&>()))>;
123template <
class BackendSelector,
class ResultTensor, TensorView InputTensor>
127 auto output_storage = output.
storage();
128 auto awaited =
co_await async::all(output_storage, input);
129 auto& storage = std::get<0>(awaited);
130 auto const& input_value = std::get<1>(awaited);
132 convert_tensor_extents<typename ResultTensor::extents_type>(input_value.extents()));
134 storage.
emplace(std::move(result));
138#if UNI20_BACKEND_CUDA
139template <TensorView InputTensor>
140using async_device_tensor_t = std::remove_cvref_t<decltype(uni20::to_device(std::declval<InputTensor const&>(),
141 std::declval<cuda::DeviceResources&>()))>;
143template <
class ResultTensor, TensorView InputTensor>
145 cuda::DeviceResources* resources)
147 auto output_storage = output.
storage();
148 auto awaited =
co_await async::all(output_storage, input);
149 auto& storage = std::get<0>(awaited);
150 auto const& input_value = std::get<1>(awaited);
152 convert_tensor_extents<typename ResultTensor::extents_type>(input_value.extents()));
153 auto output_descriptor =
mdspec_of(result);
154 auto input_descriptor =
mdspec_of(input_value);
157 storage.
emplace(std::move(result));
172template <
class BackendSelector,
class OutputTensor,
class InputTensor>
173 requires detail::AsyncCopyTensors<OutputTensor, InputTensor>
176 detail::schedule_async_copy(std::move(selector), output, input);
180template <
class OutputTensor,
class InputTensor>
181 requires detail::AsyncCopyTensors<OutputTensor, InputTensor>
184#if UNI20_BACKEND_CUDA
185 if constexpr (detail::is_pageable_cuda_transfer<OutputTensor, InputTensor>)
192 auto selector = linalg::select_backend_for<OutputTensor, InputTensor>(
linalg::copy_op{});
193 detail::schedule_async_copy(std::move(selector), output, input);
201 using result_type = detail::async_materialized_tensor_t<InputTensor>;
204#if UNI20_BACKEND_CUDA
205 auto selector = [&] {
206 if constexpr (detail::is_pageable_cuda_transfer<result_type, InputTensor>)
209 return linalg::select_backend_for<result_type, InputTensor>(
linalg::copy_op{});
212 auto selector = linalg::select_backend_for<result_type, InputTensor>(
linalg::copy_op{});
214 auto task = detail::co_make_tensor(std::move(selector), output.
write(), input.
read());
215 task.debug_name(
"make_tensor");
220#if UNI20_BACKEND_CUDA
222template <TensorView InputTensor>
223 requires std::same_as<tensor_storage_policy_t<InputTensor>, CudaStorage>
232template <TensorView InputTensor>
233 requires detail::CanonicalReshapeLayout<typename tensor_mdspec_t<InputTensor>::layout_type>
236 using result_type = detail::async_device_tensor_t<InputTensor>;
239 auto task = detail::co_to_device(output.
write(), input.
read(), std::addressof(resources));
240 task.debug_name(
"to_device");
246template <TensorView InputTensor>
247 requires detail::CanonicalReshapeLayout<typename tensor_mdspec_t<InputTensor>::layout_type>
254template <TensorView InputTensor>
255 requires detail::CanonicalReshapeLayout<typename tensor_mdspec_t<InputTensor>::layout_type>
258 return uni20::to_device(input, device.ordinal());
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
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
Raised when a writer requests a mutable reference before construction.
Definition async_errors.hpp:74
A lightweight, thread-safe, reference-counted storage for a single object.
Definition shared_storage.hpp:94
bool constructed() const noexcept
Reports whether a value is currently constructed.
Definition shared_storage.hpp:234
T & emplace(Args &&... args)
Destroy any existing value and construct a new one in place.
Definition shared_storage.hpp:270
Coroutine kernel-dispatch customization for CUDA Tensor copies.
CUDA Tensor storage with deferred device-memory data descriptors.
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
DeviceResources & device_resources()
Return canonical resources for the installed runtime's default device.
Definition runtime.cpp:820
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
Definition async/async.hpp:26
constexpr uninitialized_t uninitialized
Explicit allocation tag for overwrite outputs and scratch space.
Definition common/initialization.hpp:22
Output & prepare_output(Output &output, RequiredExtents const &required)
Prepare a mutable tensor output with the specified shape.
Definition tensor/output.hpp:104
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
auto make_tensor(async::Async< InputTensor > const &input)
Materialize an async Tensor view as an independent owning host Tensor.
Definition linalg/async/copy.hpp:199
void copy(BackendSelector selector, async::Async< OutputTensor > &output, async::Async< InputTensor > const &input)
Schedule a Tensor copy through an explicit backend selector.
Definition linalg/async/copy.hpp:174
Backend value for generic CUDA runtime kernels and transfers.
Definition backend_selector.hpp:48
Accessor-respecting element copy operation tag.
Definition operation_tags.hpp:33
Backend-dispatched tensor copies and inferred owning materialization.
#define ERROR_IF(cond,...)
Definition trace.hpp:389