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 
55 namespace Kokkos {
56 
57 enum { ARRAY_LAYOUT_MAX_RANK = 8 };
58 
59 //----------------------------------------------------------------------------
74 struct 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 //----------------------------------------------------------------------------
108 struct LayoutRight {
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 //----------------------------------------------------------------------------
132 struct LayoutStride {
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 
193 enum 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
202 template <typename LayoutTiledCheck, class Enable = void>
203 struct is_layouttiled : std::false_type {};
204 
205 template <typename LayoutTiledCheck>
206 struct is_layouttiled<
207  LayoutTiledCheck,
208  typename std::enable_if<LayoutTiledCheck::is_array_layout_tiled>::type>
209  : std::true_type {};
210 
211 namespace Experimental {
212 
214 // Must have Rank >= 2
215 template <
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)))>
228 struct LayoutTiled {
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
278 template <typename... Layout>
279 struct 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 
286 template <>
287 struct 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 
292 template <>
293 struct 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 
298 template <>
299 struct 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 
306 template <unsigned ArgN0, unsigned ArgN1, unsigned ArgN2, unsigned ArgN3,
307  unsigned ArgN4, unsigned ArgN5, unsigned ArgN6, unsigned ArgN7>
308 struct 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 
315 template <unsigned ArgN0, unsigned ArgN1, unsigned ArgN2, unsigned ArgN3,
316  unsigned ArgN4, unsigned ArgN5, unsigned ArgN6, unsigned ArgN7>
317 struct 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 
324 template <unsigned ArgN0, unsigned ArgN1, unsigned ArgN2, unsigned ArgN3,
325  unsigned ArgN4, unsigned ArgN5, unsigned ArgN6, unsigned ArgN7>
326 struct 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 
333 template <unsigned ArgN0, unsigned ArgN1, unsigned ArgN2, unsigned ArgN3,
334  unsigned ArgN4, unsigned ArgN5, unsigned ArgN6, unsigned ArgN7>
335 struct 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 indicated arbitrarily strided multi-index mapping into contiguous memory...
Memory layout tag indicating right-to-left (C or lexigraphical scheme) striding of multi-indices...
static KOKKOS_INLINE_FUNCTION LayoutStride order_dimensions(int const rank, iTypeOrder const *const order, iTypeDimen const *const dimen)
Compute strides from ordered dimensions.
Definition: dummy.cpp:3