Kokkos Core Kernels Package Version of the Day
Kokkos_Layout.hpp
Go to the documentation of this file.
1/*
2//@HEADER
3// ************************************************************************
4//
5// Kokkos v. 3.0
6// Copyright (2020) National Technology & Engineering
7// Solutions of Sandia, LLC (NTESS).
8//
9// Under the terms of Contract DE-NA0003525 with NTESS,
10// the U.S. Government retains certain rights in this software.
11//
12// Redistribution and use in source and binary forms, with or without
13// modification, are permitted provided that the following conditions are
14// met:
15//
16// 1. Redistributions of source code must retain the above copyright
17// notice, this list of conditions and the following disclaimer.
18//
19// 2. Redistributions in binary form must reproduce the above copyright
20// notice, this list of conditions and the following disclaimer in the
21// documentation and/or other materials provided with the distribution.
22//
23// 3. Neither the name of the Corporation nor the names of the
24// contributors may be used to endorse or promote products derived from
25// this software without specific prior written permission.
26//
27// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
28// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
31// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
35// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38//
39// Questions? Contact Christian R. Trott (crtrott@sandia.gov)
40//
41// ************************************************************************
42//@HEADER
43*/
44
47
48#ifndef KOKKOS_LAYOUT_HPP
49#define KOKKOS_LAYOUT_HPP
50
51#include <cstddef>
52#include <impl/Kokkos_Traits.hpp>
53#include <impl/Kokkos_Tags.hpp>
54
55namespace Kokkos {
56
57enum { ARRAY_LAYOUT_MAX_RANK = 8 };
58
59//----------------------------------------------------------------------------
74struct LayoutLeft {
77
78 size_t dimension[ARRAY_LAYOUT_MAX_RANK];
79
80 enum : bool { is_extent_constructible = true };
81
82 LayoutLeft(LayoutLeft const&) = default;
83 LayoutLeft(LayoutLeft&&) = default;
84 LayoutLeft& operator=(LayoutLeft const&) = default;
85 LayoutLeft& operator=(LayoutLeft&&) = default;
86
87 KOKKOS_INLINE_FUNCTION
88 explicit constexpr LayoutLeft(size_t N0 = 0, size_t N1 = 0, size_t N2 = 0,
89 size_t N3 = 0, size_t N4 = 0, size_t N5 = 0,
90 size_t N6 = 0, size_t N7 = 0)
91 : dimension{N0, N1, N2, N3, N4, N5, N6, N7} {}
92};
93
94//----------------------------------------------------------------------------
111
112 size_t dimension[ARRAY_LAYOUT_MAX_RANK];
113
114 enum : bool { is_extent_constructible = true };
115
116 LayoutRight(LayoutRight const&) = default;
117 LayoutRight(LayoutRight&&) = default;
118 LayoutRight& operator=(LayoutRight const&) = default;
119 LayoutRight& operator=(LayoutRight&&) = default;
120
121 KOKKOS_INLINE_FUNCTION
122 explicit constexpr LayoutRight(size_t N0 = 0, size_t N1 = 0, size_t N2 = 0,
123 size_t N3 = 0, size_t N4 = 0, size_t N5 = 0,
124 size_t N6 = 0, size_t N7 = 0)
125 : dimension{N0, N1, N2, N3, N4, N5, N6, N7} {}
126};
127
128//----------------------------------------------------------------------------
135
136 size_t dimension[ARRAY_LAYOUT_MAX_RANK];
137 size_t stride[ARRAY_LAYOUT_MAX_RANK];
138
139 enum : bool { is_extent_constructible = false };
140
141 LayoutStride(LayoutStride const&) = default;
142 LayoutStride(LayoutStride&&) = default;
143 LayoutStride& operator=(LayoutStride const&) = default;
144 LayoutStride& operator=(LayoutStride&&) = default;
145
153 template <typename iTypeOrder, typename iTypeDimen>
154 KOKKOS_INLINE_FUNCTION static LayoutStride order_dimensions(
155 int const rank, iTypeOrder const* const order,
156 iTypeDimen const* const dimen) {
157 LayoutStride tmp;
158 // Verify valid rank order:
159 int check_input = ARRAY_LAYOUT_MAX_RANK < rank ? 0 : int(1 << rank) - 1;
160 for (int r = 0; r < ARRAY_LAYOUT_MAX_RANK; ++r) {
161 tmp.dimension[r] = 0;
162 tmp.stride[r] = 0;
163 }
164 for (int r = 0; r < rank; ++r) {
165 check_input &= ~int(1 << order[r]);
166 }
167 if (0 == check_input) {
168 size_t n = 1;
169 for (int r = 0; r < rank; ++r) {
170 tmp.stride[order[r]] = n;
171 n *= (dimen[order[r]]);
172 tmp.dimension[r] = dimen[r];
173 }
174 }
175 return tmp;
176 }
177
178 KOKKOS_INLINE_FUNCTION
179 explicit constexpr LayoutStride(size_t N0 = 0, size_t S0 = 0, size_t N1 = 0,
180 size_t S1 = 0, size_t N2 = 0, size_t S2 = 0,
181 size_t N3 = 0, size_t S3 = 0, size_t N4 = 0,
182 size_t S4 = 0, size_t N5 = 0, size_t S5 = 0,
183 size_t N6 = 0, size_t S6 = 0, size_t N7 = 0,
184 size_t S7 = 0)
185 : dimension{N0, N1, N2, N3, N4, N5, N6, N7}, stride{S0, S1, S2, S3,
186 S4, S5, S6, S7} {}
187};
188
189// ===================================================================================
190
192
193enum class Iterate {
194 Default,
195 Left, // Left indices stride fastest
196 Right // Right indices stride fastest
197};
198
199// To check for LayoutTiled
200// This is to hide extra compile-time 'identifier' info within the LayoutTiled
201// class by not relying on template specialization to include the ArgN*'s
202template <typename LayoutTiledCheck, class Enable = void>
203struct is_layouttiled : std::false_type {};
204
205template <typename LayoutTiledCheck>
206struct is_layouttiled<
207 LayoutTiledCheck,
208 typename std::enable_if<LayoutTiledCheck::is_array_layout_tiled>::type>
209 : std::true_type {};
210
211namespace Experimental {
212
214// Must have Rank >= 2
215template <
216 Kokkos::Iterate OuterP, Kokkos::Iterate InnerP, unsigned ArgN0,
217 unsigned ArgN1, unsigned ArgN2 = 0, unsigned ArgN3 = 0, unsigned ArgN4 = 0,
218 unsigned ArgN5 = 0, unsigned ArgN6 = 0, unsigned ArgN7 = 0,
219 bool IsPowerOfTwo =
220 (Kokkos::Impl::is_integral_power_of_two(ArgN0) &&
221 Kokkos::Impl::is_integral_power_of_two(ArgN1) &&
222 (Kokkos::Impl::is_integral_power_of_two(ArgN2) || (ArgN2 == 0)) &&
223 (Kokkos::Impl::is_integral_power_of_two(ArgN3) || (ArgN3 == 0)) &&
224 (Kokkos::Impl::is_integral_power_of_two(ArgN4) || (ArgN4 == 0)) &&
225 (Kokkos::Impl::is_integral_power_of_two(ArgN5) || (ArgN5 == 0)) &&
226 (Kokkos::Impl::is_integral_power_of_two(ArgN6) || (ArgN6 == 0)) &&
227 (Kokkos::Impl::is_integral_power_of_two(ArgN7) || (ArgN7 == 0)))>
229 static_assert(IsPowerOfTwo,
230 "LayoutTiled must be given power-of-two tile dimensions");
231
232#if 0
233 static_assert( (Impl::is_integral_power_of_two(ArgN0) ) &&
234 (Impl::is_integral_power_of_two(ArgN1) ) &&
235 (Impl::is_integral_power_of_two(ArgN2) || (ArgN2 == 0) ) &&
236 (Impl::is_integral_power_of_two(ArgN3) || (ArgN3 == 0) ) &&
237 (Impl::is_integral_power_of_two(ArgN4) || (ArgN4 == 0) ) &&
238 (Impl::is_integral_power_of_two(ArgN5) || (ArgN5 == 0) ) &&
239 (Impl::is_integral_power_of_two(ArgN6) || (ArgN6 == 0) ) &&
240 (Impl::is_integral_power_of_two(ArgN7) || (ArgN7 == 0) )
241 , "LayoutTiled must be given power-of-two tile dimensions" );
242#endif
243
244 using array_layout = LayoutTiled<OuterP, InnerP, ArgN0, ArgN1, ArgN2, ArgN3,
245 ArgN4, ArgN5, ArgN6, ArgN7, IsPowerOfTwo>;
246 static constexpr Iterate outer_pattern = OuterP;
247 static constexpr Iterate inner_pattern = InnerP;
248
249 enum { N0 = ArgN0 };
250 enum { N1 = ArgN1 };
251 enum { N2 = ArgN2 };
252 enum { N3 = ArgN3 };
253 enum { N4 = ArgN4 };
254 enum { N5 = ArgN5 };
255 enum { N6 = ArgN6 };
256 enum { N7 = ArgN7 };
257
258 size_t dimension[ARRAY_LAYOUT_MAX_RANK];
259
260 enum : bool { is_extent_constructible = true };
261
262 LayoutTiled(LayoutTiled const&) = default;
263 LayoutTiled(LayoutTiled&&) = default;
264 LayoutTiled& operator=(LayoutTiled const&) = default;
265 LayoutTiled& operator=(LayoutTiled&&) = default;
266
267 KOKKOS_INLINE_FUNCTION
268 explicit constexpr LayoutTiled(size_t argN0 = 0, size_t argN1 = 0,
269 size_t argN2 = 0, size_t argN3 = 0,
270 size_t argN4 = 0, size_t argN5 = 0,
271 size_t argN6 = 0, size_t argN7 = 0)
272 : dimension{argN0, argN1, argN2, argN3, argN4, argN5, argN6, argN7} {}
273};
274
275} // namespace Experimental
276
277// For use with view_copy
278template <typename... Layout>
279struct layout_iterate_type_selector {
280 static const Kokkos::Iterate outer_iteration_pattern =
281 Kokkos::Iterate::Default;
282 static const Kokkos::Iterate inner_iteration_pattern =
283 Kokkos::Iterate::Default;
284};
285
286template <>
287struct layout_iterate_type_selector<Kokkos::LayoutRight> {
288 static const Kokkos::Iterate outer_iteration_pattern = Kokkos::Iterate::Right;
289 static const Kokkos::Iterate inner_iteration_pattern = Kokkos::Iterate::Right;
290};
291
292template <>
293struct layout_iterate_type_selector<Kokkos::LayoutLeft> {
294 static const Kokkos::Iterate outer_iteration_pattern = Kokkos::Iterate::Left;
295 static const Kokkos::Iterate inner_iteration_pattern = Kokkos::Iterate::Left;
296};
297
298template <>
299struct layout_iterate_type_selector<Kokkos::LayoutStride> {
300 static const Kokkos::Iterate outer_iteration_pattern =
301 Kokkos::Iterate::Default;
302 static const Kokkos::Iterate inner_iteration_pattern =
303 Kokkos::Iterate::Default;
304};
305
306template <unsigned ArgN0, unsigned ArgN1, unsigned ArgN2, unsigned ArgN3,
307 unsigned ArgN4, unsigned ArgN5, unsigned ArgN6, unsigned ArgN7>
308struct layout_iterate_type_selector<Kokkos::Experimental::LayoutTiled<
309 Kokkos::Iterate::Left, Kokkos::Iterate::Left, ArgN0, ArgN1, ArgN2, ArgN3,
310 ArgN4, ArgN5, ArgN6, ArgN7, true> > {
311 static const Kokkos::Iterate outer_iteration_pattern = Kokkos::Iterate::Left;
312 static const Kokkos::Iterate inner_iteration_pattern = Kokkos::Iterate::Left;
313};
314
315template <unsigned ArgN0, unsigned ArgN1, unsigned ArgN2, unsigned ArgN3,
316 unsigned ArgN4, unsigned ArgN5, unsigned ArgN6, unsigned ArgN7>
317struct layout_iterate_type_selector<Kokkos::Experimental::LayoutTiled<
318 Kokkos::Iterate::Right, Kokkos::Iterate::Left, ArgN0, ArgN1, ArgN2, ArgN3,
319 ArgN4, ArgN5, ArgN6, ArgN7, true> > {
320 static const Kokkos::Iterate outer_iteration_pattern = Kokkos::Iterate::Right;
321 static const Kokkos::Iterate inner_iteration_pattern = Kokkos::Iterate::Left;
322};
323
324template <unsigned ArgN0, unsigned ArgN1, unsigned ArgN2, unsigned ArgN3,
325 unsigned ArgN4, unsigned ArgN5, unsigned ArgN6, unsigned ArgN7>
326struct layout_iterate_type_selector<Kokkos::Experimental::LayoutTiled<
327 Kokkos::Iterate::Left, Kokkos::Iterate::Right, ArgN0, ArgN1, ArgN2, ArgN3,
328 ArgN4, ArgN5, ArgN6, ArgN7, true> > {
329 static const Kokkos::Iterate outer_iteration_pattern = Kokkos::Iterate::Left;
330 static const Kokkos::Iterate inner_iteration_pattern = Kokkos::Iterate::Right;
331};
332
333template <unsigned ArgN0, unsigned ArgN1, unsigned ArgN2, unsigned ArgN3,
334 unsigned ArgN4, unsigned ArgN5, unsigned ArgN6, unsigned ArgN7>
335struct layout_iterate_type_selector<Kokkos::Experimental::LayoutTiled<
336 Kokkos::Iterate::Right, Kokkos::Iterate::Right, ArgN0, ArgN1, ArgN2, ArgN3,
337 ArgN4, ArgN5, ArgN6, ArgN7, true> > {
338 static const Kokkos::Iterate outer_iteration_pattern = Kokkos::Iterate::Right;
339 static const Kokkos::Iterate inner_iteration_pattern = Kokkos::Iterate::Right;
340};
341
342} // namespace Kokkos
343
344#endif // #ifndef KOKKOS_LAYOUT_HPP
Memory layout tag indicating left-to-right (Fortran scheme) striding of multi-indices.
Memory layout tag indicating right-to-left (C or lexigraphical scheme) striding of multi-indices.
Memory layout tag indicated arbitrarily strided multi-index mapping into contiguous memory.
static KOKKOS_INLINE_FUNCTION LayoutStride order_dimensions(int const rank, iTypeOrder const *const order, iTypeDimen const *const dimen)
Compute strides from ordered dimensions.