Uni20
Asynchronous tensor and runtime library.
Loading...
Searching...
No Matches
copy_into.hpp
Go to the documentation of this file.
1#pragma once
2
15
16#if UNI20_BACKEND_CUDA
20#endif
21
22#include <cstddef>
23#include <type_traits>
24#include <utility>
25
26namespace uni20
27{
28namespace detail
29{
30template <class Output, class Input>
31concept CopySpans = MutableMdspanLike<Output> && MdspanLike<Input> &&
32 (std::remove_cvref_t<Output>::rank() == std::remove_cvref_t<Input>::rank());
33
34template <class Output, class Input>
35concept CopyTensors = MutableTensorView<Output> && TensorView<Input> &&
36 (tensor_mdspec_t<Output>::rank() == tensor_mdspec_t<Input>::rank());
37
38#if UNI20_BACKEND_CUDA
39template <class Output, class Input>
40inline constexpr bool is_pageable_cuda_transfer = (std::same_as<tensor_storage_policy_t<Output>, CudaStorage> &&
41 std::same_as<tensor_storage_policy_t<Input>, HostStorage>) ||
42 (std::same_as<tensor_storage_policy_t<Output>, HostStorage> &&
43 std::same_as<tensor_storage_policy_t<Input>, CudaStorage>);
44#endif
45
46template <MdspecLike Output, MdspecLike Input>
47[[nodiscard]] constexpr bool copy_extents_match(Output const& output, Input const& input) noexcept
48{
49 if constexpr (std::remove_cvref_t<Output>::rank() != std::remove_cvref_t<Input>::rank())
50 {
51 return false;
52 }
53 else
54 {
55 constexpr std::size_t rank = std::remove_cvref_t<Output>::rank();
56 if constexpr (rank > 0)
57 {
58 for (std::size_t axis = 0; axis < rank; ++axis)
59 {
60 if (output.extent(axis) != input.extent(axis)) return false;
61 }
62 }
63 return true;
64 }
65}
66
67} // namespace detail
68
75template <class BackendSelector, class OutputMdspan, class InputMdspan>
76 requires detail::CopySpans<OutputMdspan, InputMdspan>
77void copy(BackendSelector&& selector, OutputMdspan&& output, InputMdspan&& input)
78{
79 ERROR_IF(!detail::copy_extents_match(output, input), "copy output shape does not match input shape");
80 auto output_span = std::forward<OutputMdspan>(output);
81 auto input_span = make_const_mdspan(input);
82 linalg::dispatch_kernel(std::forward<BackendSelector>(selector), linalg::copy_op{}, output_span, input_span);
83}
84
88template <class BackendSelector, class OutputTensor, class InputTensor>
89 requires detail::CopyTensors<OutputTensor, InputTensor>
90void copy(BackendSelector&& selector, OutputTensor&& output, InputTensor const& input)
91{
92 prepare_output(output, input.extents());
93 auto output_span = mdspec_of(output);
94 auto input_span = mdspec_of(input);
95 linalg::dispatch_kernel(std::forward<BackendSelector>(selector), linalg::copy_op{}, output_span, input_span);
96}
97
99template <class OutputTensor, class InputTensor>
100 requires detail::CopyTensors<OutputTensor, InputTensor>
101void copy(OutputTensor&& output, InputTensor const& input)
102{
103#if UNI20_BACKEND_CUDA
104 if constexpr (detail::is_pageable_cuda_transfer<OutputTensor, InputTensor>)
105 {
106 copy(linalg::CudaReferenceBackend{}, output, input);
107 }
108 else
109#endif
110 {
111 auto selector = linalg::select_backend(linalg::copy_op{}, output, input);
112 copy(selector, output, input);
113 }
114}
115
119template <MutableTensorView Output, TensorView Input>
120 requires(tensor_mdspec_t<Output>::rank() == tensor_mdspec_t<Input>::rank())
121void assign_through(Output& output, Input const& input)
122{
123 copy(output, input);
124}
125
126} // namespace uni20
CUDA Tensor storage with deferred device-memory data descriptors.
Operation-tag backend dispatch over tensor-view operands.
Reference CPU backend for accessor-respecting element copies.
CUDA runtime backend for contiguous Tensor transfers.
Mdspan concept and accessor extensions for Uni20.
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 async/async.hpp:26
Output & prepare_output(Output &output, RequiredExtents const &required)
Prepare a mutable tensor output with the specified shape.
Definition tensor/output.hpp:104
void assign_through(Output &output, Input const &input)
Assign tensor values through a mutable tensor alias descriptor.
Definition copy_into.hpp:121
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
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
constexpr auto make_const_mdspan(Span const &span)
Build a read-only mdspan descriptor over the same storage and mapping.
Definition mdspan/concepts.hpp:372
Backend-independent operation values used with normalized kernel operands.
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
Shape preparation contracts for tensor operation outputs.
#define ERROR_IF(cond,...)
Definition trace.hpp:389