Uni20
Asynchronous tensor and runtime library.
Loading...
Searching...
No Matches
transform_view.hpp
Go to the documentation of this file.
1#pragma once
2
10#include <uni20/core/types.hpp>
14
15#include <cstddef>
16#include <tuple>
17#include <type_traits>
18#include <utility>
19
20namespace uni20
21{
22namespace detail
23{
24
25template <class Function, class... Arguments>
26concept ConstDirectlyCallable = requires(Function const& function) { function(std::declval<Arguments>()...); };
27
28template <class Function, class... Arguments>
29using direct_call_result_t = decltype(std::declval<Function const&>()(std::declval<Arguments>()...));
30
31template <class Function, MdspanLike Span> class unary_transform_accessor {
32 public:
33 using function_type = Function;
34 using span_type = Span;
35 using wrapped_accessor_type = typename span_type::accessor_type;
36 using data_handle_type = typename span_type::data_handle_type;
37 using offset_type = span_offset_t<wrapped_accessor_type>;
38 using reference = direct_call_result_t<function_type, typename span_type::reference>;
39 using element_type = logical_value_t<remove_proxy_reference_t<reference>> const;
40 using offset_policy = unary_transform_accessor;
41
42 template <class FwdFunction>
43 UNI20_HOST_DEVICE constexpr unary_transform_accessor(FwdFunction&& function, span_type const& span)
44 : function_(std::forward<FwdFunction>(function)), accessor_(span.accessor())
45 {}
46
47 [[nodiscard]] UNI20_HOST_DEVICE constexpr auto offset(data_handle_type const& handle,
48 offset_type const& offset) const -> data_handle_type
49 {
50 return accessor_.offset(handle, offset);
51 }
52
53 [[nodiscard]] UNI20_HOST_DEVICE constexpr auto access(data_handle_type const& handle,
54 offset_type const& offset) const -> reference
55 {
56 return function_(accessor_.access(handle, offset));
57 }
58
59 private:
60 [[no_unique_address]] function_type function_;
61 [[no_unique_address]] wrapped_accessor_type accessor_;
62};
63
64template <class Function, MdspanLike... Spans> class transform_accessor {
65 public:
66 static_assert(sizeof...(Spans) >= 2);
67
68 using function_type = Function;
69 using accessor_tuple = std::tuple<typename Spans::accessor_type...>;
70 using data_handle_type = std::tuple<typename Spans::data_handle_type...>;
71 using offset_type = std::tuple<span_offset_t<typename Spans::accessor_type>...>;
72 using reference = direct_call_result_t<function_type, typename Spans::reference...>;
73 using element_type = logical_value_t<remove_proxy_reference_t<reference>> const;
74 using offset_policy = transform_accessor;
75
76 template <class FwdFunction>
77 UNI20_HOST_DEVICE constexpr transform_accessor(FwdFunction&& function, Spans const&... spans)
78 : function_(std::forward<FwdFunction>(function)), accessors_(spans.accessor()...)
79 {}
80
81 [[nodiscard]] UNI20_HOST_DEVICE constexpr auto offset(data_handle_type const& handles,
82 offset_type const& offsets) const -> data_handle_type
83 {
84 return offset_impl(handles, offsets, std::index_sequence_for<Spans...>{});
85 }
86
87 [[nodiscard]] UNI20_HOST_DEVICE constexpr auto access(data_handle_type const& handles,
88 offset_type const& offsets) const -> reference
89 {
90 return access_impl(handles, offsets, std::index_sequence_for<Spans...>{});
91 }
92
93 private:
94 template <std::size_t... Index>
95 [[nodiscard]] UNI20_HOST_DEVICE constexpr auto offset_impl(data_handle_type const& handles,
96 offset_type const& offsets,
97 std::index_sequence<Index...>) const -> data_handle_type
98 {
99 return {std::get<Index>(accessors_).offset(std::get<Index>(handles), std::get<Index>(offsets))...};
100 }
101
102 template <std::size_t... Index>
103 [[nodiscard]] UNI20_HOST_DEVICE constexpr auto access_impl(data_handle_type const& handles,
104 offset_type const& offsets,
105 std::index_sequence<Index...>) const -> reference
106 {
107 return function_(std::get<Index>(accessors_).access(std::get<Index>(handles), std::get<Index>(offsets))...);
108 }
109
110 [[no_unique_address]] function_type function_;
111 [[no_unique_address]] accessor_tuple accessors_;
112};
113
114} // namespace detail
115
117template <class Function, MdspanLike Span, class Domain>
118inline constexpr bool enable_accessor_in_domain<detail::unary_transform_accessor<Function, Span>, Domain> =
119 enable_accessor_in_domain<typename Span::accessor_type, Domain>;
120
122template <class Function, MdspanLike... Spans>
123inline constexpr bool enable_accessor_in_domain<detail::transform_accessor<Function, Spans...>, host_access_domain> =
124 (enable_accessor_in_domain<typename Spans::accessor_type, host_access_domain> && ...);
125
127template <class Function, MdspanLike... Spans>
128inline constexpr bool enable_accessor_in_domain<detail::transform_accessor<Function, Spans...>, cuda_access_domain> =
129 (enable_accessor_in_domain<typename Spans::accessor_type, cuda_access_domain> && ...);
130
132template <class Function, MdspanLike Span>
133 requires detail::ConstDirectlyCallable<std::decay_t<Function>, typename Span::reference>
134[[nodiscard]] constexpr auto transform_view(Function&& function, Span const& span)
135{
136 using function_type = std::decay_t<Function>;
137 using accessor_type = detail::unary_transform_accessor<function_type, Span>;
138 using element_type = typename accessor_type::element_type;
139 using extents_type = typename Span::extents_type;
140 using layout_type = typename Span::layout_type;
141
142 return stdex::mdspan<element_type, extents_type, layout_type, accessor_type>{
143 span.data_handle(), span.mapping(), accessor_type(std::forward<Function>(function), span)};
144}
145
148template <class Function, MdspanLike First, MdspanLike Second, MdspanLike... Rest>
149 requires detail::ConstDirectlyCallable<std::decay_t<Function>, typename First::reference, typename Second::reference,
150 typename Rest::reference...>
151[[nodiscard]] constexpr auto transform_view(Function&& function, First const& first, Second const& second,
152 Rest const&... rest)
153{
154 static_assert(First::rank() == Second::rank() && ((First::rank() == Rest::rank()) && ...));
155
156 using function_type = std::decay_t<Function>;
157 using extents_type = common_extents_t<First, Second, Rest...>;
158 using layout_type = zip_layout_t<First, Second, Rest...>;
159 using mapping_type = typename layout_type::template mapping<extents_type>;
160 using accessor_type = detail::transform_accessor<function_type, First, Second, Rest...>;
161 using element_type = typename accessor_type::element_type;
162
163 auto extents = make_common_extents(first, second, rest...);
164 return stdex::mdspan<element_type, extents_type, layout_type, accessor_type>{
165 std::tuple{first.data_handle(), second.data_handle(), rest.data_handle()...},
166 mapping_type{extents, first.mapping(), second.mapping(), rest.mapping()...},
167 accessor_type(std::forward<Function>(function), first, second, rest...)};
168}
169
170} // namespace uni20
Project compiler annotations shared by host and device code.
#define UNI20_HOST_DEVICE
Definition compiler_attributes.hpp:12
cuda::ResourceLease< HandleSlot > handle
Definition cublas/execution.cpp:33
Domain
MKL computation domains accepted by domain-specific thread controls.
Definition backend_mkl.hpp:35
auto make_common_extents(Spans... spans)
Build an extents object representing the common shape of the given spans.
Definition zip_layout.hpp:127
typename detail::common_extents< Spans... >::type common_extents_t
Convenience alias that represents the common extents of a set of mdspans.
Definition zip_layout.hpp:120
typename zip_layout_selector< Spans... >::type zip_layout_t
Alias to extract the chosen layout policy for the given spans.
Definition zip_layout.hpp:520
Mdspan concept and accessor extensions for Uni20.
Configured gateway to Uni20's mdspan implementation.
Definition qnum.hpp:403
Definition async/async.hpp:26
constexpr auto transform_view(Function &&function, Span const &span)
Create a lazy read-only unary transform view while preserving the input mapping.
Definition transform_view.hpp:134
constexpr bool enable_accessor_in_domain
Opt-in customization for the execution domains supported by an accessor.
Definition mdspan/concepts.hpp:85
std::size_t span
Definition presentation.cpp:2017
Additional layout helpers and policies for zipped mdspan views.