batmat 0.0.14
Batched linear algebra routines
Loading...
Searching...
No Matches
uview.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <batmat/assume.hpp>
4#include <batmat/config.hpp>
7#include <batmat/simd.hpp>
8#include <batmat/unroll.h>
9
10#include <cstddef>
11#include <type_traits>
12#include <utility>
13
14namespace batmat::linalg {
15
17
18template <class T, class Abi>
20 using value_type = T;
22 using mask = typename simd::mask_type;
23 using isimd = datapar::deduced_simd<index_t, simd::size()>;
26 static constexpr auto simd_stride = simd_stride_t::value;
27 static constexpr auto simd_align = simd_align_t::value;
28 static_assert(simd_align <= simd_stride * sizeof(T));
29 using one_t = std::integral_constant<index_t, 1>;
30 template <class S = T, StorageOrder O = StorageOrder::ColMajor>
32 template <class S = T, StorageOrder O = StorageOrder::ColMajor>
34 template <class S = T, StorageOrder O = StorageOrder::ColMajor>
36 template <class S = T, StorageOrder O = StorageOrder::ColMajor>
38 template <class S = T, StorageOrder O = StorageOrder::ColMajor>
40
41 static simd aligned_load(const T *p) noexcept { return datapar::aligned_load<simd>(p); }
42
43 template <int MaskL = 0>
44 [[gnu::always_inline]] static void aligned_store(simd x, value_type *p) noexcept {
45 if constexpr (MaskL == 0) {
47 } else if constexpr (MaskL > 0) {
48#if BATMAT_WITH_GSI_HPC_SIMD
49 typename simd::mask_type m{[&](size_t i) { return i >= MaskL; }};
50#else
51 typename simd::mask_type m{};
52 for (int i = 0; i < static_cast<int>(m.size()); ++i)
53 m[i] = i >= MaskL;
54#endif
56 } else {
57#if BATMAT_WITH_GSI_HPC_SIMD
58 typename simd::mask_type m{[&](size_t i) { return i < m.size() + MaskL; }};
59#else
60 typename simd::mask_type m{};
61 for (int i = 0; i < static_cast<int>(m.size()); ++i)
62 m[i] = i < static_cast<int>(m.size()) + MaskL;
63#endif
65 }
66 }
67};
68
69template <class T, class Abi, StorageOrder Order = StorageOrder::ColMajor>
71template <class T, class Abi, StorageOrder Order = StorageOrder::ColMajor>
73
74template <class Abi, StorageOrder Order = StorageOrder::ColMajor>
76template <class Abi, StorageOrder Order = StorageOrder::ColMajor>
78
79template <class T, class Abi, StorageOrder Order>
80struct uview {
81 using value_type = T;
83 index_t outer_stride;
84
86 using view = types::template view<T, Order>;
87 using mut_view = types::template view<std::remove_const_t<T>, Order>;
89 using simd = typename types::simd;
90 static constexpr ptrdiff_t inner_stride = typename types::simd_stride_t();
91
92 [[gnu::always_inline]] value_type *get(index_t r, index_t c) const noexcept {
93 ptrdiff_t i0 = Order == StorageOrder::RowMajor ? c : r;
94 ptrdiff_t i1 = Order == StorageOrder::RowMajor ? r : c;
95 return data + inner_stride * (i0 + i1 * static_cast<ptrdiff_t>(outer_stride));
96 }
97 [[gnu::always_inline]] value_type &operator()(index_t r, index_t c) const noexcept {
98 return *get(r, c);
99 }
100 [[gnu::always_inline]] simd load(index_t r, index_t c) const noexcept {
101 return types::aligned_load(get(r, c));
102 }
103 template <int MaskL = 0>
104 [[gnu::always_inline]] void store(simd x, index_t r, index_t c) const noexcept
105 requires(!std::is_const_v<T>)
106 {
107 types::template aligned_store<MaskL>(x, get(r, c));
108 }
109 template <class Self>
110 [[gnu::always_inline]] Self block(this const Self &self, index_t r, index_t c) noexcept {
111 return {self.get(r, c), self.outer_stride};
112 }
113 template <class Self>
114 [[gnu::always_inline]] Self middle_rows(this const Self &self, index_t r) noexcept {
115 return {self.get(r, 0), self.outer_stride};
116 }
117 template <class Self>
118 [[gnu::always_inline]] Self middle_cols(this const Self &self, index_t c) noexcept {
119 return {self.get(0, c), self.outer_stride};
120 }
121
122 [[gnu::always_inline]] uview(value_type *data, index_t outer_stride) noexcept
124 [[gnu::always_inline]] uview(const mut_view &v) noexcept
125 requires std::is_const_v<T>
126 : data{v.data()}, outer_stride{v.outer_stride()} {}
127 [[gnu::always_inline]] uview(const view &v) noexcept
128 : data{v.data()}, outer_stride{v.outer_stride()} {}
129 [[gnu::always_inline]] uview(const mut_uview &o) noexcept
130 requires std::is_const_v<T>
131 : data{o.data}, outer_stride{o.outer_stride} {}
132 [[gnu::always_inline]] uview(const uview &o) = default;
133};
134
135template <class T, class Abi>
136struct uview_vec {
137 using value_type = T;
139
141 template <StorageOrder Order>
142 using view = types::template view<T, Order>;
143 template <StorageOrder Order>
144 using mut_view = types::template view<std::remove_const_t<T>, Order>;
146 using simd = typename types::simd;
147 static constexpr ptrdiff_t inner_stride = typename types::simd_stride_t();
148
149 [[gnu::always_inline]] value_type &operator()(index_t r) const noexcept {
150 return data[inner_stride * static_cast<ptrdiff_t>(r)];
151 }
152 [[gnu::always_inline]] simd load(index_t r) const noexcept {
153 return types::aligned_load(&operator()(r));
154 }
155 template <int MaskL = 0>
156 [[gnu::always_inline]] void store(simd x, index_t r) const noexcept
157 requires(!std::is_const_v<T>)
158 {
159 types::template aligned_store<MaskL>(x, &operator()(r));
160 }
161 template <class Self>
162 [[gnu::always_inline]] Self segment(this const Self &self, index_t r) noexcept {
163 return {&self(r)};
164 }
165
166 [[gnu::always_inline]] uview_vec(value_type *data) noexcept : data{data} {}
167 template <StorageOrder Order>
168 [[gnu::always_inline]] explicit uview_vec(const mut_view<Order> &v) noexcept
169 requires std::is_const_v<T>
170 : data{v.data()} {
171 BATMAT_ASSUME(v.outer_size() == 1);
172 }
173 template <StorageOrder Order>
174 [[gnu::always_inline]] explicit uview_vec(const view<Order> &v) noexcept : data{v.data()} {
175 BATMAT_ASSUME(v.outer_size() == 1);
176 }
177 [[gnu::always_inline]] uview_vec(const mut_uview &o) noexcept
178 requires std::is_const_v<T>
179 : data{o.data} {}
180 [[gnu::always_inline]] uview_vec(const uview_vec &o) = default;
181};
182
183template <index_t Size, class T, class Abi, StorageOrder Order>
185 using value_type = T;
186 value_type *const data[Size];
187
189 using simd = typename types::simd;
190 static constexpr ptrdiff_t inner_stride = typename types::simd_stride_t();
191
192 [[gnu::always_inline]] value_type &operator()(index_t r, index_t c) const noexcept {
193 ptrdiff_t i0 = Order == StorageOrder::RowMajor ? c : r;
194 index_t i1 = Order == StorageOrder::RowMajor ? r : c;
195 assert(i1 < Size);
196 return data[i1][i0 * inner_stride];
197 }
198 [[gnu::always_inline]] simd load(index_t r, index_t c) const noexcept {
199 return types::aligned_load(&operator()(r, c));
200 }
201 template <int MaskL = 0>
202 [[gnu::always_inline]] void store(simd x, index_t r, index_t c) const noexcept
203 requires(!std::is_const_v<T>)
204 {
205 types::template aligned_store<MaskL>(x, &operator()(r, c));
206 }
207
208 template <index_t... Is>
209 [[gnu::always_inline]] cached_uview(const uview<T, Abi, Order> &o,
210 std::integer_sequence<index_t, Is...>) noexcept
211 : data{(o.data + Is * o.inner_stride * static_cast<ptrdiff_t>(o.outer_stride))...} {}
212 [[gnu::always_inline]] cached_uview(const uview<T, Abi, Order> &o) noexcept
213 : cached_uview{o, std::make_integer_sequence<index_t, Size>()} {}
214};
215
216#ifdef __INTEL_LLVM_COMPILER
217// No caching on Intel icx to avoid issues with icpx codegen. See test/icpx-repro.cpp.
218template <index_t Rows, index_t Cols, class T, class Abi, StorageOrder Order>
219[[gnu::always_inline]] inline auto with_cached_access(uview<T, Abi, Order> o) noexcept {
220 return o;
221}
222#else
223
224template <index_t Rows, index_t Cols, class T, class Abi, StorageOrder Order>
225 requires(Rows > 0 && Cols > 0)
226[[gnu::always_inline]] inline cached_uview<Order == StorageOrder::ColMajor ? Cols : Rows, T, Abi,
227 Order>
228with_cached_access(const uview<T, Abi, Order> &o) noexcept {
229 return {o};
230}
231
232template <index_t Rows, index_t Cols, class T, class Abi>
233 requires(Rows == 0 && Cols > 0)
234[[gnu::always_inline]] inline cached_uview<Cols, T, Abi, StorageOrder::ColMajor>
236 return {o};
237}
238
239template <index_t Rows, index_t Cols, class T, class Abi>
240 requires(Rows == 0 && Cols > 0)
241[[gnu::always_inline]] inline uview<T, Abi, StorageOrder::RowMajor>
243 return o;
244}
245
246template <index_t Rows, index_t Cols, class T, class Abi>
247 requires(Rows > 0 && Cols == 0)
248[[gnu::always_inline]] inline cached_uview<Rows, T, Abi, StorageOrder::RowMajor>
250 return {o};
251}
252
253template <index_t Rows, index_t Cols, class T, class Abi>
254 requires(Rows > 0 && Cols == 0)
255[[gnu::always_inline]] inline uview<T, Abi, StorageOrder::ColMajor>
257 return o;
258}
259
260#endif
261
262} // namespace batmat::linalg
#define BATMAT_ASSUME(x)
Invokes undefined behavior if the expression x does not evaluate to true.
Definition assume.hpp:17
Class for a batch of matrices that owns its storage.
void aligned_store(V v, typename V::value_type *p)
Definition simd.hpp:121
stdx::memory_alignment< simd< Tp, Abi > > simd_align
Definition simd.hpp:139
stdx::simd_size< Tp, Abi > simd_size
Definition simd.hpp:137
V aligned_load(const typename V::value_type *p)
Definition simd.hpp:111
simd< Tp, deduced_abi< Tp, Np > > deduced_simd
Definition simd.hpp:103
void masked_aligned_store(V v, typename V::mask_type m, typename V::value_type *p)
Definition simd.hpp:126
stdx::simd< Tp, Abi > simd
Definition simd.hpp:99
simd_view_types< real_t, Abi >::template view< real_t, Order > mut_real_view
Definition uview.hpp:77
simd_view_types< std::remove_const_t< T >, Abi >::template matrix< T, Order > matrix
Definition uview.hpp:72
simd_view_types< real_t, Abi >::template view< const real_t, Order > real_view
Definition uview.hpp:75
cached_uview< Order==StorageOrder::ColMajor ? Cols :Rows, T, Abi, Order > with_cached_access(const uview< T, Abi, Order > &o) noexcept
Definition uview.hpp:228
simd_view_types< std::remove_const_t< T >, Abi >::template view< T, Order > view
Definition uview.hpp:70
value_type *const data[Size]
Definition uview.hpp:186
value_type & operator()(index_t r, index_t c) const noexcept
Definition uview.hpp:192
cached_uview(const uview< T, Abi, Order > &o, std::integer_sequence< index_t, Is... >) noexcept
Definition uview.hpp:209
simd_view_types< std::remove_const_t< T >, Abi > types
Definition uview.hpp:188
cached_uview(const uview< T, Abi, Order > &o) noexcept
Definition uview.hpp:212
simd load(index_t r, index_t c) const noexcept
Definition uview.hpp:198
static constexpr ptrdiff_t inner_stride
Definition uview.hpp:190
typename types::simd simd
Definition uview.hpp:189
void store(simd x, index_t r, index_t c) const noexcept
Definition uview.hpp:202
static void aligned_store(simd x, value_type *p) noexcept
Definition uview.hpp:44
typename simd::mask_type mask
Definition uview.hpp:22
matrix::View< S, index_t, one_t, index_t, index_t, O > multi_scalar_view
Definition uview.hpp:37
datapar::deduced_simd< index_t, simd::size()> isimd
Definition uview.hpp:23
datapar::simd_size< T, Abi > simd_stride_t
Definition uview.hpp:24
datapar::simd< T, Abi > simd
Definition uview.hpp:21
matrix::View< S, index_t, simd_stride_t, simd_stride_t, matrix::DefaultStride, O > view
Definition uview.hpp:31
matrix::Matrix< S, index_t, simd_stride_t, index_t, O, simd_align_t > matrix
Definition uview.hpp:39
matrix::View< S, index_t, simd_stride_t, index_t, index_t, O > multi_view
Definition uview.hpp:33
static simd aligned_load(const T *p) noexcept
Definition uview.hpp:41
matrix::View< S, index_t, one_t, simd_stride_t, matrix::DefaultStride, O > scalar_view
Definition uview.hpp:35
std::integral_constant< index_t, 1 > one_t
Definition uview.hpp:29
datapar::simd_align< T, Abi > simd_align_t
Definition uview.hpp:25
static constexpr auto simd_stride
Definition uview.hpp:26
simd_view_types< std::remove_const_t< T >, Abi > types
Definition uview.hpp:140
void store(simd x, index_t r) const noexcept
Definition uview.hpp:156
uview_vec(const mut_view< Order > &v) noexcept
Definition uview.hpp:168
value_type & operator()(index_t r) const noexcept
Definition uview.hpp:149
uview_vec(const view< Order > &v) noexcept
Definition uview.hpp:174
Self segment(this const Self &self, index_t r) noexcept
Definition uview.hpp:162
simd load(index_t r) const noexcept
Definition uview.hpp:152
types::template view< T, Order > view
Definition uview.hpp:142
uview_vec< std::remove_const_t< T >, Abi > mut_uview
Definition uview.hpp:145
types::template view< std::remove_const_t< T >, Order > mut_view
Definition uview.hpp:144
uview_vec(const mut_uview &o) noexcept
Definition uview.hpp:177
uview_vec(const uview_vec &o)=default
uview_vec(value_type *data) noexcept
Definition uview.hpp:166
types::template view< T, Order > view
Definition uview.hpp:86
Self block(this const Self &self, index_t r, index_t c) noexcept
Definition uview.hpp:110
types::template view< std::remove_const_t< T >, Order > mut_view
Definition uview.hpp:87
uview(const view &v) noexcept
Definition uview.hpp:127
uview(const mut_view &v) noexcept
Definition uview.hpp:124
void store(simd x, index_t r, index_t c) const noexcept
Definition uview.hpp:104
simd load(index_t r, index_t c) const noexcept
Definition uview.hpp:100
uview< std::remove_const_t< T >, Abi, Order > mut_uview
Definition uview.hpp:88
Self middle_rows(this const Self &self, index_t r) noexcept
Definition uview.hpp:114
Self middle_cols(this const Self &self, index_t c) noexcept
Definition uview.hpp:118
value_type & operator()(index_t r, index_t c) const noexcept
Definition uview.hpp:97
uview(const uview &o)=default
simd_view_types< std::remove_const_t< T >, Abi > types
Definition uview.hpp:85
value_type * get(index_t r, index_t c) const noexcept
Definition uview.hpp:92
uview(value_type *data, index_t outer_stride) noexcept
Definition uview.hpp:122
uview(const mut_uview &o) noexcept
Definition uview.hpp:129
Class for a batch of matrices that owns its storage.
Definition matrix.hpp:52
Non-owning view of a batch of matrices.
Definition view.hpp:32
Non-owning view of a batch of matrices.