23template <
class Accessor> [[nodiscard]]
constexpr auto lower_cuda_accessor(Accessor
const& accessor)
29[[nodiscard]]
constexpr auto
30lower_cuda_accessor(conjugated_accessor<cuda::CudaPointerAccessor<standard_complex<Real>
const>>
const&)
32 return cuda::CudaConjugatingPointerAccessor<Real>{};
35template <
class Po
inter> [[nodiscard]] Pointer offset_cuda_pointer(Pointer pointer, std::size_t offset)
noexcept
37 if (offset == 0)
return pointer;
38 CHECK(pointer !=
nullptr,
"cannot offset an empty CUDA data handle", offset);
39 return pointer + offset;
42template <
class Mdspec>
void validate_cuda_descriptor_range(Mdspec
const&
span)
44 auto const& descriptor =
span.data_descriptor();
45 auto const required =
span.mapping().required_span_size();
46 CHECK(std::cmp_greater_equal(required, 0), required);
47 CHECK(std::cmp_less_equal(required, descriptor.buffer().size()), required, descriptor.buffer().size());
48 auto const count =
static_cast<std::size_t
>(required);
49 auto const offset = descriptor.element_offset();
50 CHECK(offset <= descriptor.buffer().size() && count <= descriptor.buffer().size() - offset, offset, count,
51 descriptor.buffer().size());
54template <
class Mdspec,
class Po
inter> [[nodiscard]]
auto resolve_cuda_mdspan(Mdspec
const&
span, Pointer pointer)
56 using span_type = std::remove_cvref_t<Mdspec>;
57 auto accessor = lower_cuda_accessor(
span.accessor());
58 using accessor_type =
decltype(accessor);
59 static_assert(std::same_as<typename accessor_type::element_type, typename span_type::element_type>);
60 using mdspan_type = stdex::mdspan<
typename accessor_type::element_type,
typename span_type::extents_type,
61 typename span_type::layout_type, accessor_type>;
62 return mdspan_type{pointer,
span.mapping(), std::move(accessor)};
65template <
class Mdspec,
class AccessState>
66[[nodiscard]]
auto make_cuda_read_mdspan_lease(Mdspec mdspec, std::size_t element_offset, AccessState state)
68 auto const pointer = offset_cuda_pointer(state.data(), element_offset);
69 auto mdspan = resolve_cuda_mdspan(mdspec, pointer);
70 return read_mdspan_lease<
decltype(mdspan), AccessState>{std::move(state), std::move(mdspan)};
73template <
class Mdspec,
class AccessState>
74[[nodiscard]]
auto make_cuda_write_mdspan_lease(Mdspec mdspec, AccessState state)
76 auto const offset =
static_cast<std::size_t
>(mdspec.data_descriptor().element_offset());
77 auto pointer = offset_cuda_pointer(state.data(), offset);
78 auto mdspan = resolve_cuda_mdspan(mdspec, pointer);
79 return write_mdspan_lease<
decltype(mdspan), AccessState>{std::move(state), std::move(mdspan)};
82template <
class StoragePolicy,
class Mdspec,
class AccessState,
class BackendSelector>
83[[nodiscard]]
auto make_cuda_read_tensor_lease(Mdspec mdspec, std::size_t element_offset, AccessState state,
84 BackendSelector selector)
86 auto const pointer = offset_cuda_pointer(state.data(), element_offset);
87 auto mdspan = resolve_cuda_mdspan(mdspec, pointer);
89 using mdspan_type =
decltype(mdspan);
90 using selector_type = std::remove_cvref_t<BackendSelector>;
91 return read_tensor_lease<mdspan_type, AccessState, selector_type, StoragePolicy>{std::move(state), std::move(mdspan),
95template <
class StoragePolicy,
class Mdspec,
class ConstMdspec,
class AccessState,
class BackendSelector>
96[[nodiscard]]
auto make_cuda_write_tensor_lease(Mdspec mdspec, ConstMdspec const_mdspec, AccessState state,
97 BackendSelector selector)
99 CHECK(mdspec.data_descriptor().element_offset() == const_mdspec.data_descriptor().element_offset());
101 auto const offset =
static_cast<std::size_t
>(mdspec.data_descriptor().element_offset());
102 auto pointer = offset_cuda_pointer(state.data(), offset);
103 auto mdspan = resolve_cuda_mdspan(mdspec, pointer);
104 auto const_mdspan = resolve_cuda_mdspan(const_mdspec, pointer);
106 using mdspan_type =
decltype(mdspan);
107 using const_mdspan_type =
decltype(const_mdspan);
108 using selector_type = std::remove_cvref_t<BackendSelector>;
109 return write_tensor_lease<mdspan_type, const_mdspan_type, AccessState, selector_type, StoragePolicy>{
110 std::move(state), std::move(mdspan), std::move(const_mdspan), std::move(selector)};
118template <cuda::BufferMdspec Mdspec>
119 requires std::is_const_v<typename std::remove_cvref_t<Mdspec>::element_type>
122 detail::validate_cuda_descriptor_range(
mdspec);
125 return detail::make_cuda_read_mdspan_lease(
mdspec, element_offset, std::move(state));
131template <
class Mdspec>
132 requires cuda::BufferMdspec<Mdspec> && MutableMdspecLike<Mdspec>
135 detail::validate_cuda_descriptor_range(
mdspec);
137 return detail::make_cuda_write_mdspan_lease(
mdspec, std::move(state));
142template <
class Tensor>
143 requires TensorView<Tensor> && (!ImmediateTensorView<Tensor>) && cuda::BufferMdspec<tensor_mdspec_t<Tensor>>
147 detail::validate_cuda_descriptor_range(
mdspec);
150 return detail::make_cuda_read_tensor_lease<tensor_storage_policy_t<Tensor>>(
155template <
class Tensor>
156 requires(!std::is_lvalue_reference_v<Tensor>) && TensorView<std::remove_cvref_t<Tensor>> &&
157 (!ImmediateTensorView<std::remove_cvref_t<Tensor>>) && OwningTensor<std::remove_cvref_t<Tensor>> &&
158 cuda::BufferMdspec<tensor_mdspec_t<std::remove_cvref_t<Tensor>>> &&
requires(Tensor&& tensor) {
159 { std::move(tensor).release_storage() } -> std::same_as<typename std::remove_cvref_t<Tensor>::storage_type>;
164 detail::validate_cuda_descriptor_range(
mdspec);
167 auto storage = std::move(tensor).release_storage();
168 auto state = std::move(storage).into_blocking_read_access();
169 return detail::make_cuda_read_tensor_lease<tensor_storage_policy_t<Tensor>>(std::move(
mdspec), element_offset,
170 std::move(state), std::move(selector));
175template <
class Tensor>
176 requires MutableTensorView<Tensor> && (!MutableImmediateTensorView<Tensor>) &&
177 cuda::BufferMdspec<tensor_mdspec_t<Tensor>> && cuda::BufferMdspec<mutable_tensor_mdspec_t<Tensor>>
181 auto const_mdspec =
mdspec_of(std::as_const(tensor));
182 detail::validate_cuda_descriptor_range(
mdspec);
183 detail::validate_cuda_descriptor_range(const_mdspec);
185 return detail::make_cuda_write_tensor_lease<tensor_storage_policy_t<Tensor>>(
190template <cuda::BufferMdspec Mdspec>
191 requires std::is_const_v<typename std::remove_cvref_t<Mdspec>::element_type>
194 detail::validate_cuda_descriptor_range(
mdspec);
197 return ready_access{detail::make_cuda_read_mdspan_lease(
mdspec, element_offset, std::move(state))};
201template <
class Mdspec>
202 requires cuda::BufferMdspec<Mdspec> && MutableMdspecLike<Mdspec>
205 detail::validate_cuda_descriptor_range(
mdspec);
214template <
class Tensor>
215 requires TensorView<Tensor> && (!ImmediateTensorView<Tensor>) && cuda::BufferMdspec<tensor_mdspec_t<Tensor>>
219 detail::validate_cuda_descriptor_range(
mdspec);
222 return ready_access{detail::make_cuda_read_tensor_lease<tensor_storage_policy_t<Tensor>>(
227template <
class Tensor>
228 requires(!std::is_lvalue_reference_v<Tensor>) && TensorView<std::remove_cvref_t<Tensor>> &&
229 (!ImmediateTensorView<std::remove_cvref_t<Tensor>>) && OwningTensor<std::remove_cvref_t<Tensor>> &&
230 cuda::BufferMdspec<tensor_mdspec_t<std::remove_cvref_t<Tensor>>> &&
requires(Tensor&& tensor) {
231 { std::move(tensor).release_storage() } -> std::same_as<typename std::remove_cvref_t<Tensor>::storage_type>;
236 detail::validate_cuda_descriptor_range(
mdspec);
239 auto storage = std::move(tensor).release_storage();
240 auto state = std::move(storage).into_read_synchronized_with(stream);
241 return ready_access{detail::make_cuda_read_tensor_lease<tensor_storage_policy_t<Tensor>>(
242 std::move(
mdspec), element_offset, std::move(state), std::move(selector))};
246template <
class Tensor>
247 requires MutableTensorView<Tensor> && (!MutableImmediateTensorView<Tensor>) &&
248 cuda::BufferMdspec<tensor_mdspec_t<Tensor>> && cuda::BufferMdspec<mutable_tensor_mdspec_t<Tensor>>
252 auto const_mdspec =
mdspec_of(std::as_const(tensor));
253 detail::validate_cuda_descriptor_range(
mdspec);
254 detail::validate_cuda_descriptor_range(const_mdspec);
256 return ready_access{detail::make_cuda_write_tensor_lease<tensor_storage_policy_t<Tensor>>(
RAII leases that resolve device descriptors and tensor views to mdspans.
General-purpose owning tensor with immediate or deferred mdspan metadata.
Definition basic_tensor.hpp:109
static constexpr auto backend_selector() noexcept -> backend_selector_type
Return the default backend selector associated with this tensor's storage.
Definition basic_tensor.hpp:602
Reference-counted lease of one CUDA stream-pool slot.
Definition runtime.hpp:65
Store a data descriptor with the mapping and accessor for an eventual mdspan.
Definition mdspec.hpp:31
constexpr auto data_descriptor() noexcept -> data_descriptor_type &
Return the descriptor used to acquire writable data access.
Definition mdspec.hpp:77
Always-ready awaitable that transfers one access lease.
Definition access.hpp:592
Mdspan accessor adaptor for lazy complex conjugation.
CUDA Tensor storage with deferred device-memory data descriptors.
Definition async/async.hpp:26
auto acquire_cuda_read_access_async(Mdspec const &mdspec, cuda::Stream const &stream)
Resolve borrowed CUDA read access synchronized with an operation stream.
Definition cuda_access.hpp:192
auto acquire_cuda_write_access_sync(Mdspec &mdspec)
Host-wait for prior CUDA work and resolve a borrowed write descriptor.
Definition cuda_access.hpp:133
auto acquire_cuda_write_access_async(Mdspec &mdspec, cuda::Stream const &stream)
Resolve borrowed CUDA write access synchronized with an operation stream.
Definition cuda_access.hpp:203
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 acquire_cuda_read_access_sync(Mdspec const &mdspec)
Host-wait for prior CUDA work and resolve a borrowed read descriptor.
Definition cuda_access.hpp:120
std::size_t span
Definition presentation.cpp:2017
#define CHECK(cond,...)
Definition trace.hpp:299