/* //@HEADER // ************************************************************************ // // Kokkos v. 3.0 // Copyright (2020) National Technology & Engineering // Solutions of Sandia, LLC (NTESS). // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // 3. Neither the name of the Corporation nor the names of the // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Questions? Contact Christian R. Trott (crtrott@sandia.gov) // // ************************************************************************ //@HEADER */ #ifndef KOKKOS_EXPERIMENTAL_VIEWLAYOUTTILE_HPP #define KOKKOS_EXPERIMENTAL_VIEWLAYOUTTILE_HPP #include #include //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- namespace Kokkos { // View offset and mapping for tiled view's template struct is_array_layout > : public std::true_type {}; template struct is_array_layout > : public std::true_type {}; template struct is_array_layout > : public std::true_type {}; template struct is_array_layout > : public std::true_type {}; template struct is_array_layout > : public std::true_type {}; template struct is_array_layout > : public std::true_type {}; template struct is_array_layout< Kokkos::Experimental::LayoutTiled > : public std::true_type {}; template struct is_array_layout_tiled : public std::false_type {}; template struct is_array_layout_tiled > : public std::true_type { }; // Last template parameter "true" meaning this currently only supports // powers-of-two namespace Impl { template struct ViewOffset< Dimension, Layout, typename std::enable_if<((Dimension::rank <= 8) && (Dimension::rank >= 2) && is_array_layout::value && is_array_layout_tiled::value)>::type> { public: static constexpr Kokkos::Iterate outer_pattern = Layout::outer_pattern; static constexpr Kokkos::Iterate inner_pattern = Layout::inner_pattern; static constexpr int VORank = Dimension::rank; static constexpr unsigned SHIFT_0 = Kokkos::Impl::integral_power_of_two(Layout::N0); static constexpr unsigned SHIFT_1 = Kokkos::Impl::integral_power_of_two(Layout::N1); static constexpr unsigned SHIFT_2 = Kokkos::Impl::integral_power_of_two(Layout::N2); static constexpr unsigned SHIFT_3 = Kokkos::Impl::integral_power_of_two(Layout::N3); static constexpr unsigned SHIFT_4 = Kokkos::Impl::integral_power_of_two(Layout::N4); static constexpr unsigned SHIFT_5 = Kokkos::Impl::integral_power_of_two(Layout::N5); static constexpr unsigned SHIFT_6 = Kokkos::Impl::integral_power_of_two(Layout::N6); static constexpr unsigned SHIFT_7 = Kokkos::Impl::integral_power_of_two(Layout::N7); static constexpr int MASK_0 = Layout::N0 - 1; static constexpr int MASK_1 = Layout::N1 - 1; static constexpr int MASK_2 = Layout::N2 - 1; static constexpr int MASK_3 = Layout::N3 - 1; static constexpr int MASK_4 = Layout::N4 - 1; static constexpr int MASK_5 = Layout::N5 - 1; static constexpr int MASK_6 = Layout::N6 - 1; static constexpr int MASK_7 = Layout::N7 - 1; static constexpr unsigned SHIFT_2T = SHIFT_0 + SHIFT_1; static constexpr unsigned SHIFT_3T = SHIFT_0 + SHIFT_1 + SHIFT_2; static constexpr unsigned SHIFT_4T = SHIFT_0 + SHIFT_1 + SHIFT_2 + SHIFT_3; static constexpr unsigned SHIFT_5T = SHIFT_0 + SHIFT_1 + SHIFT_2 + SHIFT_3 + SHIFT_4; static constexpr unsigned SHIFT_6T = SHIFT_0 + SHIFT_1 + SHIFT_2 + SHIFT_3 + SHIFT_4 + SHIFT_5; static constexpr unsigned SHIFT_7T = SHIFT_0 + SHIFT_1 + SHIFT_2 + SHIFT_3 + SHIFT_4 + SHIFT_5 + SHIFT_6; static constexpr unsigned SHIFT_8T = SHIFT_0 + SHIFT_1 + SHIFT_2 + SHIFT_3 + SHIFT_4 + SHIFT_5 + SHIFT_6 + SHIFT_7; // Is an irregular layout that does not have uniform striding for each index. using is_mapping_plugin = std::true_type; using is_regular = std::false_type; using size_type = size_t; using dimension_type = Dimension; using array_layout = Layout; dimension_type m_dim; size_type m_tile_N0; // Num tiles dim 0 size_type m_tile_N1; size_type m_tile_N2; size_type m_tile_N3; size_type m_tile_N4; size_type m_tile_N5; size_type m_tile_N6; size_type m_tile_N7; //---------------------------------------- #define DEBUG_OUTPUT_CHECK 0 // Rank 2 template KOKKOS_INLINE_FUNCTION size_type operator()(I0 const& i0, I1 const& i1) const { auto tile_offset = (outer_pattern == (Kokkos::Iterate::Left)) ? (((i0 >> SHIFT_0) + m_tile_N0 * ((i1 >> SHIFT_1))) << SHIFT_2T) : (((m_tile_N1 * (i0 >> SHIFT_0) + (i1 >> SHIFT_1))) << SHIFT_2T); // ( num_tiles[1] * ti0 + ti1 ) * FTD auto local_offset = (inner_pattern == (Kokkos::Iterate::Left)) ? ((i0 & MASK_0) + ((i1 & MASK_1) << SHIFT_0)) : (((i0 & MASK_0) << SHIFT_1) + (i1 & MASK_1)); // ( tile_dim[1] * li0 + li1 ) #if DEBUG_OUTPUT_CHECK std::cout << "Am I Outer Left? " << (outer_pattern == (Kokkos::Iterate::Left)) << std::endl; std::cout << "Am I Inner Left? " << (inner_pattern == (Kokkos::Iterate::Left)) << std::endl; std::cout << "i0 = " << i0 << " i1 = " << i1 << "\ntilei0 = " << (i0 >> SHIFT_0) << " tilei1 = " << (i1 >> SHIFT_1) << "locali0 = " << (i0 & MASK_0) << "\nlocali1 = " << (i1 & MASK_1) << std::endl; #endif return tile_offset + local_offset; } // Rank 3 template KOKKOS_INLINE_FUNCTION size_type operator()(I0 const& i0, I1 const& i1, I2 const& i2) const { auto tile_offset = (outer_pattern == Kokkos::Iterate::Left) ? (((i0 >> SHIFT_0) + m_tile_N0 * ((i1 >> SHIFT_1) + m_tile_N1 * (i2 >> SHIFT_2))) << SHIFT_3T) : ((m_tile_N2 * (m_tile_N1 * (i0 >> SHIFT_0) + (i1 >> SHIFT_1)) + (i2 >> SHIFT_2)) << SHIFT_3T); auto local_offset = (inner_pattern == Kokkos::Iterate::Left) ? ((i0 & MASK_0) + ((i1 & MASK_1) << SHIFT_0) + ((i2 & MASK_2) << (SHIFT_0 + SHIFT_1))) : (((i0 & MASK_0) << (SHIFT_2 + SHIFT_1)) + ((i1 & MASK_1) << (SHIFT_2)) + (i2 & MASK_2)); #if DEBUG_OUTPUT_CHECK std::cout << "Am I Outer Left? " << (outer_pattern == (Kokkos::Iterate::Left)) << std::endl; std::cout << "Am I Inner Left? " << (inner_pattern == (Kokkos::Iterate::Left)) << std::endl; std::cout << "i0 = " << i0 << " i1 = " << i1 << " i2 = " << i2 << "\ntilei0 = " << (i0 >> SHIFT_0) << " tilei1 = " << (i1 >> SHIFT_1) << " tilei2 = " << (i2 >> SHIFT_2) << "\nlocali0 = " << (i0 & MASK_0) << "locali1 = " << (i1 & MASK_1) << "locali2 = " << (i2 & MASK_2) << std::endl; #endif return tile_offset + local_offset; } // Rank 4 template KOKKOS_INLINE_FUNCTION size_type operator()(I0 const& i0, I1 const& i1, I2 const& i2, I3 const& i3) const { auto tile_offset = (outer_pattern == Kokkos::Iterate::Left) ? (((i0 >> SHIFT_0) + m_tile_N0 * ((i1 >> SHIFT_1) + m_tile_N1 * ((i2 >> SHIFT_2) + m_tile_N2 * (i3 >> SHIFT_3)))) << SHIFT_4T) : ((m_tile_N3 * (m_tile_N2 * (m_tile_N1 * (i0 >> SHIFT_0) + (i1 >> SHIFT_1)) + (i2 >> SHIFT_2)) + (i3 >> SHIFT_3)) << SHIFT_4T); auto local_offset = (inner_pattern == Kokkos::Iterate::Left) ? ((i0 & MASK_0) + ((i1 & MASK_1) << SHIFT_0) + ((i2 & MASK_2) << (SHIFT_0 + SHIFT_1)) + ((i3 & MASK_3) << (SHIFT_0 + SHIFT_1 + SHIFT_2))) : (((i0 & MASK_0) << (SHIFT_3 + SHIFT_2 + SHIFT_1)) + ((i1 & MASK_1) << (SHIFT_3 + SHIFT_2)) + ((i2 & MASK_2) << (SHIFT_3)) + (i3 & MASK_3)); return tile_offset + local_offset; } // Rank 5 template KOKKOS_INLINE_FUNCTION size_type operator()(I0 const& i0, I1 const& i1, I2 const& i2, I3 const& i3, I4 const& i4) const { auto tile_offset = (outer_pattern == Kokkos::Iterate::Left) ? (((i0 >> SHIFT_0) + m_tile_N0 * ((i1 >> SHIFT_1) + m_tile_N1 * ((i2 >> SHIFT_2) + m_tile_N2 * ((i3 >> SHIFT_3) + m_tile_N3 * (i4 >> SHIFT_4))))) << SHIFT_5T) : ((m_tile_N4 * (m_tile_N3 * (m_tile_N2 * (m_tile_N1 * (i0 >> SHIFT_0) + (i1 >> SHIFT_1)) + (i2 >> SHIFT_2)) + (i3 >> SHIFT_3)) + (i4 >> SHIFT_4)) << SHIFT_5T); auto local_offset = (inner_pattern == Kokkos::Iterate::Left) ? ((i0 & MASK_0) + ((i1 & MASK_1) << SHIFT_0) + ((i2 & MASK_2) << (SHIFT_0 + SHIFT_1)) + ((i3 & MASK_3) << (SHIFT_0 + SHIFT_1 + SHIFT_2)) + ((i4 & MASK_4) << (SHIFT_0 + SHIFT_1 + SHIFT_2 + SHIFT_3))) : (((i0 & MASK_0) << (SHIFT_4 + SHIFT_3 + SHIFT_2 + SHIFT_1)) + ((i1 & MASK_1) << (SHIFT_4 + SHIFT_3 + SHIFT_2)) + ((i2 & MASK_2) << (SHIFT_4 + SHIFT_3)) + ((i3 & MASK_3) << (SHIFT_4)) + (i4 & MASK_4)); return tile_offset + local_offset; } // Rank 6 template KOKKOS_INLINE_FUNCTION size_type operator()(I0 const& i0, I1 const& i1, I2 const& i2, I3 const& i3, I4 const& i4, I5 const& i5) const { auto tile_offset = (outer_pattern == Kokkos::Iterate::Left) ? (((i0 >> SHIFT_0) + m_tile_N0 * ((i1 >> SHIFT_1) + m_tile_N1 * ((i2 >> SHIFT_2) + m_tile_N2 * ((i3 >> SHIFT_3) + m_tile_N3 * ((i4 >> SHIFT_4) + m_tile_N4 * (i5 >> SHIFT_5)))))) << SHIFT_6T) : ((m_tile_N5 * (m_tile_N4 * (m_tile_N3 * (m_tile_N2 * (m_tile_N1 * (i0 >> SHIFT_0) + (i1 >> SHIFT_1)) + (i2 >> SHIFT_2)) + (i3 >> SHIFT_3)) + (i4 >> SHIFT_4)) + (i5 >> SHIFT_5)) << SHIFT_6T); auto local_offset = (inner_pattern == Kokkos::Iterate::Left) ? ((i0 & MASK_0) + ((i1 & MASK_1) << SHIFT_0) + ((i2 & MASK_2) << (SHIFT_0 + SHIFT_1)) + ((i3 & MASK_3) << (SHIFT_0 + SHIFT_1 + SHIFT_2)) + ((i4 & MASK_4) << (SHIFT_0 + SHIFT_1 + SHIFT_2 + SHIFT_3)) + ((i5 & MASK_5) << (SHIFT_0 + SHIFT_1 + SHIFT_2 + SHIFT_3 + SHIFT_4))) : (((i0 & MASK_0) << (SHIFT_5 + SHIFT_4 + SHIFT_3 + SHIFT_2 + SHIFT_1)) + ((i1 & MASK_1) << (SHIFT_5 + SHIFT_4 + SHIFT_3 + SHIFT_2)) + ((i2 & MASK_2) << (SHIFT_5 + SHIFT_4 + SHIFT_3)) + ((i3 & MASK_3) << (SHIFT_5 + SHIFT_4)) + ((i4 & MASK_4) << (SHIFT_5)) + (i5 & MASK_5)); return tile_offset + local_offset; } // Rank 7 template KOKKOS_INLINE_FUNCTION size_type operator()(I0 const& i0, I1 const& i1, I2 const& i2, I3 const& i3, I4 const& i4, I5 const& i5, I6 const& i6) const { auto tile_offset = (outer_pattern == Kokkos::Iterate::Left) ? (((i0 >> SHIFT_0) + m_tile_N0 * ((i1 >> SHIFT_1) + m_tile_N1 * ((i2 >> SHIFT_2) + m_tile_N2 * ((i3 >> SHIFT_3) + m_tile_N3 * ((i4 >> SHIFT_4) + m_tile_N4 * ((i5 >> SHIFT_5) + m_tile_N5 * (i6 >> SHIFT_6))))))) << SHIFT_7T) : ((m_tile_N6 * (m_tile_N5 * (m_tile_N4 * (m_tile_N3 * (m_tile_N2 * (m_tile_N1 * (i0 >> SHIFT_0) + (i1 >> SHIFT_1)) + (i2 >> SHIFT_2)) + (i3 >> SHIFT_3)) + (i4 >> SHIFT_4)) + (i5 >> SHIFT_5)) + (i6 >> SHIFT_6)) << SHIFT_7T); auto local_offset = (inner_pattern == Kokkos::Iterate::Left) ? ((i0 & MASK_0) + ((i1 & MASK_1) << SHIFT_0) + ((i2 & MASK_2) << (SHIFT_0 + SHIFT_1)) + ((i3 & MASK_3) << (SHIFT_0 + SHIFT_1 + SHIFT_2)) + ((i4 & MASK_4) << (SHIFT_0 + SHIFT_1 + SHIFT_2 + SHIFT_3)) + ((i5 & MASK_5) << (SHIFT_0 + SHIFT_1 + SHIFT_2 + SHIFT_3 + SHIFT_4)) + ((i6 & MASK_6) << (SHIFT_0 + SHIFT_1 + SHIFT_2 + SHIFT_3 + SHIFT_4 + SHIFT_5))) : (((i0 & MASK_0) << (SHIFT_6 + SHIFT_5 + SHIFT_4 + SHIFT_3 + SHIFT_2 + SHIFT_1)) + ((i1 & MASK_1) << (SHIFT_6 + SHIFT_5 + SHIFT_4 + SHIFT_3 + SHIFT_2)) + ((i2 & MASK_2) << (SHIFT_6 + SHIFT_5 + SHIFT_4 + SHIFT_3)) + ((i3 & MASK_3) << (SHIFT_6 + SHIFT_5 + SHIFT_4)) + ((i4 & MASK_4) << (SHIFT_6 + SHIFT_5)) + ((i5 & MASK_5) << (SHIFT_6)) + (i6 & MASK_6)); return tile_offset + local_offset; } // Rank 8 template KOKKOS_INLINE_FUNCTION size_type operator()(I0 const& i0, I1 const& i1, I2 const& i2, I3 const& i3, I4 const& i4, I5 const& i5, I6 const& i6, I7 const& i7) const { auto tile_offset = (outer_pattern == Kokkos::Iterate::Left) ? (((i0 >> SHIFT_0) + m_tile_N0 * ((i1 >> SHIFT_1) + m_tile_N1 * ((i2 >> SHIFT_2) + m_tile_N2 * ((i3 >> SHIFT_3) + m_tile_N3 * ((i4 >> SHIFT_4) + m_tile_N4 * ((i5 >> SHIFT_5) + m_tile_N5 * ((i6 >> SHIFT_6) + m_tile_N6 * (i7 >> SHIFT_7)))))))) << SHIFT_8T) : ((m_tile_N7 * (m_tile_N6 * (m_tile_N5 * (m_tile_N4 * (m_tile_N3 * (m_tile_N2 * (m_tile_N1 * (i0 >> SHIFT_0) + (i1 >> SHIFT_1)) + (i2 >> SHIFT_2)) + (i3 >> SHIFT_3)) + (i4 >> SHIFT_4)) + (i5 >> SHIFT_5)) + (i6 >> SHIFT_6)) + (i7 >> SHIFT_7)) << SHIFT_8T); auto local_offset = (inner_pattern == Kokkos::Iterate::Left) ? ((i0 & MASK_0) + ((i1 & MASK_1) << SHIFT_0) + ((i2 & MASK_2) << (SHIFT_0 + SHIFT_1)) + ((i3 & MASK_3) << (SHIFT_0 + SHIFT_1 + SHIFT_2)) + ((i4 & MASK_4) << (SHIFT_0 + SHIFT_1 + SHIFT_2 + SHIFT_3)) + ((i5 & MASK_5) << (SHIFT_0 + SHIFT_1 + SHIFT_2 + SHIFT_3 + SHIFT_4)) + ((i6 & MASK_6) << (SHIFT_0 + SHIFT_1 + SHIFT_2 + SHIFT_3 + SHIFT_4 + SHIFT_5)) + ((i7 & MASK_7) << (SHIFT_0 + SHIFT_1 + SHIFT_2 + SHIFT_3 + SHIFT_4 + SHIFT_5 + SHIFT_6))) : (((i0 & MASK_0) << (SHIFT_7 + SHIFT_6 + SHIFT_5 + SHIFT_4 + SHIFT_3 + SHIFT_2 + SHIFT_1)) + ((i1 & MASK_1) << (SHIFT_7 + SHIFT_6 + SHIFT_5 + SHIFT_4 + SHIFT_3 + SHIFT_2)) + ((i2 & MASK_2) << (SHIFT_7 + SHIFT_6 + SHIFT_5 + SHIFT_4 + SHIFT_3)) + ((i3 & MASK_3) << (SHIFT_7 + SHIFT_6 + SHIFT_5 + SHIFT_4)) + ((i4 & MASK_4) << (SHIFT_7 + SHIFT_6 + SHIFT_5)) + ((i5 & MASK_5) << (SHIFT_7 + SHIFT_6)) + ((i6 & MASK_6) << (SHIFT_7)) + (i7 & MASK_7)); return tile_offset + local_offset; } //---------------------------------------- KOKKOS_INLINE_FUNCTION constexpr array_layout layout() const { return array_layout(m_dim.N0, m_dim.N1, m_dim.N2, m_dim.N2, m_dim.N3, m_dim.N4, m_dim.N5, m_dim.N6, m_dim.N7); } KOKKOS_INLINE_FUNCTION constexpr size_type dimension_0() const { return m_dim.N0; } KOKKOS_INLINE_FUNCTION constexpr size_type dimension_1() const { return m_dim.N1; } KOKKOS_INLINE_FUNCTION constexpr size_type dimension_2() const { return m_dim.N2; } KOKKOS_INLINE_FUNCTION constexpr size_type dimension_3() const { return m_dim.N3; } KOKKOS_INLINE_FUNCTION constexpr size_type dimension_4() const { return m_dim.N4; } KOKKOS_INLINE_FUNCTION constexpr size_type dimension_5() const { return m_dim.N5; } KOKKOS_INLINE_FUNCTION constexpr size_type dimension_6() const { return m_dim.N6; } KOKKOS_INLINE_FUNCTION constexpr size_type dimension_7() const { return m_dim.N7; } KOKKOS_INLINE_FUNCTION constexpr size_type size() const { return m_dim.N0 * m_dim.N1 * m_dim.N2 * m_dim.N3 * m_dim.N4 * m_dim.N5 * m_dim.N6 * m_dim.N7; } // Strides are meaningless due to irregularity KOKKOS_INLINE_FUNCTION constexpr size_type stride_0() const { return 0; } KOKKOS_INLINE_FUNCTION constexpr size_type stride_1() const { return 0; } KOKKOS_INLINE_FUNCTION constexpr size_type stride_2() const { return 0; } KOKKOS_INLINE_FUNCTION constexpr size_type stride_3() const { return 0; } KOKKOS_INLINE_FUNCTION constexpr size_type stride_4() const { return 0; } KOKKOS_INLINE_FUNCTION constexpr size_type stride_5() const { return 0; } KOKKOS_INLINE_FUNCTION constexpr size_type stride_6() const { return 0; } KOKKOS_INLINE_FUNCTION constexpr size_type stride_7() const { return 0; } // Stride with [ rank ] value is the total length template KOKKOS_INLINE_FUNCTION void stride(iType* const s) const { s[0] = 0; if (0 < dimension_type::rank) { s[1] = 0; } if (1 < dimension_type::rank) { s[2] = 0; } if (2 < dimension_type::rank) { s[3] = 0; } if (3 < dimension_type::rank) { s[4] = 0; } if (4 < dimension_type::rank) { s[5] = 0; } if (5 < dimension_type::rank) { s[6] = 0; } if (6 < dimension_type::rank) { s[7] = 0; } if (7 < dimension_type::rank) { s[8] = 0; } } KOKKOS_INLINE_FUNCTION constexpr size_type span() const { // Rank2: ( NumTile0 * ( NumTile1 ) ) * TileSize, etc return (VORank == 2) ? (m_tile_N0 * m_tile_N1) << SHIFT_2T : (VORank == 3) ? (m_tile_N0 * m_tile_N1 * m_tile_N2) << SHIFT_3T : (VORank == 4) ? (m_tile_N0 * m_tile_N1 * m_tile_N2 * m_tile_N3) << SHIFT_4T : (VORank == 5) ? (m_tile_N0 * m_tile_N1 * m_tile_N2 * m_tile_N3 * m_tile_N4) << SHIFT_5T : (VORank == 6) ? (m_tile_N0 * m_tile_N1 * m_tile_N2 * m_tile_N3 * m_tile_N4 * m_tile_N5) << SHIFT_6T : (VORank == 7) ? (m_tile_N0 * m_tile_N1 * m_tile_N2 * m_tile_N3 * m_tile_N4 * m_tile_N5 * m_tile_N6) << SHIFT_7T : (m_tile_N0 * m_tile_N1 * m_tile_N2 * m_tile_N3 * m_tile_N4 * m_tile_N5 * m_tile_N6 * m_tile_N7) << SHIFT_8T; } KOKKOS_INLINE_FUNCTION constexpr bool span_is_contiguous() const { return true; } //---------------------------------------- #ifdef KOKKOS_IMPL_WINDOWS_CUDA KOKKOS_FUNCTION ViewOffset() {} KOKKOS_FUNCTION ViewOffset(const ViewOffset& src) { m_dim = src.m_dim; m_tile_N0 = src.m_tile_N0; m_tile_N1 = src.m_tile_N1; m_tile_N2 = src.m_tile_N2; m_tile_N3 = src.m_tile_N3; m_tile_N4 = src.m_tile_N4; m_tile_N5 = src.m_tile_N5; m_tile_N6 = src.m_tile_N6; m_tile_N7 = src.m_tile_N7; } KOKKOS_FUNCTION ViewOffset& operator=(const ViewOffset& src) { m_dim = src.m_dim; m_tile_N0 = src.m_tile_N0; m_tile_N1 = src.m_tile_N1; m_tile_N2 = src.m_tile_N2; m_tile_N3 = src.m_tile_N3; m_tile_N4 = src.m_tile_N4; m_tile_N5 = src.m_tile_N5; m_tile_N6 = src.m_tile_N6; m_tile_N7 = src.m_tile_N7; return *this; } #else KOKKOS_DEFAULTED_FUNCTION ~ViewOffset() = default; KOKKOS_DEFAULTED_FUNCTION ViewOffset() = default; KOKKOS_DEFAULTED_FUNCTION ViewOffset(const ViewOffset&) = default; KOKKOS_DEFAULTED_FUNCTION ViewOffset& operator=(const ViewOffset&) = default; #endif template KOKKOS_INLINE_FUNCTION constexpr ViewOffset( std::integral_constant const&, array_layout const arg_layout) : m_dim(arg_layout.dimension[0], arg_layout.dimension[1], arg_layout.dimension[2], arg_layout.dimension[3], arg_layout.dimension[4], arg_layout.dimension[5], arg_layout.dimension[6], arg_layout.dimension[7]), m_tile_N0((arg_layout.dimension[0] + MASK_0) >> SHIFT_0 /* number of tiles in first dimension */), m_tile_N1((arg_layout.dimension[1] + MASK_1) >> SHIFT_1), m_tile_N2((VORank > 2) ? (arg_layout.dimension[2] + MASK_2) >> SHIFT_2 : 0), m_tile_N3((VORank > 3) ? (arg_layout.dimension[3] + MASK_3) >> SHIFT_3 : 0), m_tile_N4((VORank > 4) ? (arg_layout.dimension[4] + MASK_4) >> SHIFT_4 : 0), m_tile_N5((VORank > 5) ? (arg_layout.dimension[5] + MASK_5) >> SHIFT_5 : 0), m_tile_N6((VORank > 6) ? (arg_layout.dimension[6] + MASK_6) >> SHIFT_6 : 0), m_tile_N7((VORank > 7) ? (arg_layout.dimension[7] + MASK_7) >> SHIFT_7 : 0) {} }; // FIXME Remove the out-of-class definitions when we require C++17 #define KOKKOS_ITERATE_VIEW_OFFSET_ENABLE \ typename std::enable_if<((Dimension::rank <= 8) && (Dimension::rank >= 2) && \ is_array_layout::value && \ is_array_layout_tiled::value)>::type template constexpr Kokkos::Iterate ViewOffset< Dimension, Layout, KOKKOS_ITERATE_VIEW_OFFSET_ENABLE>::outer_pattern; template constexpr Kokkos::Iterate ViewOffset< Dimension, Layout, KOKKOS_ITERATE_VIEW_OFFSET_ENABLE>::inner_pattern; template constexpr int ViewOffset::VORank; template constexpr unsigned ViewOffset::SHIFT_0; template constexpr unsigned ViewOffset::SHIFT_1; template constexpr unsigned ViewOffset::SHIFT_2; template constexpr unsigned ViewOffset::SHIFT_3; template constexpr unsigned ViewOffset::SHIFT_4; template constexpr unsigned ViewOffset::SHIFT_5; template constexpr unsigned ViewOffset::SHIFT_6; template constexpr unsigned ViewOffset::SHIFT_7; template constexpr int ViewOffset::MASK_0; template constexpr int ViewOffset::MASK_1; template constexpr int ViewOffset::MASK_2; template constexpr int ViewOffset::MASK_3; template constexpr int ViewOffset::MASK_4; template constexpr int ViewOffset::MASK_5; template constexpr int ViewOffset::MASK_6; template constexpr int ViewOffset::MASK_7; template constexpr unsigned ViewOffset::SHIFT_2T; template constexpr unsigned ViewOffset::SHIFT_3T; template constexpr unsigned ViewOffset::SHIFT_4T; template constexpr unsigned ViewOffset::SHIFT_5T; template constexpr unsigned ViewOffset::SHIFT_6T; template constexpr unsigned ViewOffset::SHIFT_7T; template constexpr unsigned ViewOffset::SHIFT_8T; #undef KOKKOS_ITERATE_VIEW_OFFSET_ENABLE //---------------------------------------- // ViewMapping assign method needed in order to return a 'subview' tile as a // proper View The outer iteration pattern determines the mapping of the pointer // offset to the beginning of requested tile The inner iteration pattern is // needed for the layout of the tile's View to be returned Rank 2 template class ViewMapping< typename std::enable_if<(N2 == 0 && N3 == 0 && N4 == 0 && N5 == 0 && N6 == 0 && N7 == 0)>::type // void , Kokkos::ViewTraits< T**, Kokkos::Experimental::LayoutTiled, P...>, Kokkos::Experimental::LayoutTiled, iType0, iType1> { public: using src_layout = Kokkos::Experimental::LayoutTiled; using src_traits = Kokkos::ViewTraits; static constexpr bool is_outer_left = (OuterP == Kokkos::Iterate::Left); static constexpr bool is_inner_left = (InnerP == Kokkos::Iterate::Left); using array_layout = typename std::conditional::type; using traits = Kokkos::ViewTraits; using type = Kokkos::View; KOKKOS_INLINE_FUNCTION static void assign( ViewMapping& dst, const ViewMapping& src, const src_layout&, const iType0 i_tile0, const iType1 i_tile1) { using dst_map_type = ViewMapping; using src_map_type = ViewMapping; using dst_handle_type = typename dst_map_type::handle_type; using dst_offset_type = typename dst_map_type::offset_type; using src_offset_type = typename src_map_type::offset_type; dst = dst_map_type( dst_handle_type( src.m_impl_handle + (is_outer_left ? ((i_tile0 + src.m_impl_offset.m_tile_N0 * i_tile1) << src_offset_type::SHIFT_2T) : ((src.m_impl_offset.m_tile_N1 * i_tile0 + i_tile1) << src_offset_type::SHIFT_2T)) // offset to start // of the tile ), dst_offset_type()); } }; // Rank 3 template class ViewMapping::type // void , Kokkos::ViewTraits< T***, Kokkos::Experimental::LayoutTiled< OuterP, InnerP, N0, N1, N2, N3, N4, N5, N6, N7, true>, P...>, Kokkos::Experimental::LayoutTiled, iType0, iType1, iType2> { public: using src_layout = Kokkos::Experimental::LayoutTiled; using src_traits = Kokkos::ViewTraits; static constexpr bool is_outer_left = (OuterP == Kokkos::Iterate::Left); static constexpr bool is_inner_left = (InnerP == Kokkos::Iterate::Left); using array_layout = typename std::conditional::type; using traits = Kokkos::ViewTraits; using type = Kokkos::View; KOKKOS_INLINE_FUNCTION static void assign( ViewMapping& dst, const ViewMapping& src, const src_layout&, const iType0 i_tile0, const iType1 i_tile1, const iType2 i_tile2) { using dst_map_type = ViewMapping; using src_map_type = ViewMapping; using dst_handle_type = typename dst_map_type::handle_type; using dst_offset_type = typename dst_map_type::offset_type; using src_offset_type = typename src_map_type::offset_type; dst = dst_map_type( dst_handle_type( src.m_impl_handle + (is_outer_left ? ((i_tile0 + src.m_impl_offset.m_tile_N0 * (i_tile1 + src.m_impl_offset.m_tile_N1 * i_tile2)) << src_offset_type::SHIFT_3T) : ((src.m_impl_offset.m_tile_N2 * (src.m_impl_offset.m_tile_N1 * i_tile0 + i_tile1) + i_tile2) << src_offset_type::SHIFT_3T))) // offset to start of the // tile , dst_offset_type()); } }; // Rank 4 template class ViewMapping::type // void , Kokkos::ViewTraits< T****, Kokkos::Experimental::LayoutTiled< OuterP, InnerP, N0, N1, N2, N3, N4, N5, N6, N7, true>, P...>, Kokkos::Experimental::LayoutTiled, iType0, iType1, iType2, iType3> { public: using src_layout = Kokkos::Experimental::LayoutTiled; using src_traits = Kokkos::ViewTraits; static constexpr bool is_outer_left = (OuterP == Kokkos::Iterate::Left); static constexpr bool is_inner_left = (InnerP == Kokkos::Iterate::Left); using array_layout = typename std::conditional::type; using traits = Kokkos::ViewTraits; using type = Kokkos::View; KOKKOS_INLINE_FUNCTION static void assign( ViewMapping& dst, const ViewMapping& src, const src_layout&, const iType0 i_tile0, const iType1 i_tile1, const iType2 i_tile2, const iType3 i_tile3) { using dst_map_type = ViewMapping; using src_map_type = ViewMapping; using dst_handle_type = typename dst_map_type::handle_type; using dst_offset_type = typename dst_map_type::offset_type; using src_offset_type = typename src_map_type::offset_type; dst = dst_map_type( dst_handle_type( src.m_impl_handle + (is_outer_left ? ((i_tile0 + src.m_impl_offset.m_tile_N0 * (i_tile1 + src.m_impl_offset.m_tile_N1 * (i_tile2 + src.m_impl_offset.m_tile_N2 * i_tile3))) << src_offset_type::SHIFT_4T) : ((src.m_impl_offset.m_tile_N3 * (src.m_impl_offset.m_tile_N2 * (src.m_impl_offset.m_tile_N1 * i_tile0 + i_tile1) + i_tile2) + i_tile3) << src_offset_type::SHIFT_4T))) // offset to start of the // tile , dst_offset_type()); } }; // Rank 5 template class ViewMapping< typename std::enable_if<(N5 == 0 && N6 == 0 && N7 == 0)>::type // void , Kokkos::ViewTraits< T*****, Kokkos::Experimental::LayoutTiled, P...>, Kokkos::Experimental::LayoutTiled, iType0, iType1, iType2, iType3, iType4> { public: using src_layout = Kokkos::Experimental::LayoutTiled; using src_traits = Kokkos::ViewTraits; static constexpr bool is_outer_left = (OuterP == Kokkos::Iterate::Left); static constexpr bool is_inner_left = (InnerP == Kokkos::Iterate::Left); using array_layout = typename std::conditional::type; using traits = Kokkos::ViewTraits; using type = Kokkos::View; KOKKOS_INLINE_FUNCTION static void assign( ViewMapping& dst, const ViewMapping& src, const src_layout&, const iType0 i_tile0, const iType1 i_tile1, const iType2 i_tile2, const iType3 i_tile3, const iType4 i_tile4) { using dst_map_type = ViewMapping; using src_map_type = ViewMapping; using dst_handle_type = typename dst_map_type::handle_type; using dst_offset_type = typename dst_map_type::offset_type; using src_offset_type = typename src_map_type::offset_type; dst = dst_map_type( dst_handle_type( src.m_impl_handle + (is_outer_left ? ((i_tile0 + src.m_impl_offset.m_tile_N0 * (i_tile1 + src.m_impl_offset.m_tile_N1 * (i_tile2 + src.m_impl_offset.m_tile_N2 * (i_tile3 + src.m_impl_offset.m_tile_N3 * i_tile4)))) << src_offset_type::SHIFT_5T) : ((src.m_impl_offset.m_tile_N4 * (src.m_impl_offset.m_tile_N3 * (src.m_impl_offset.m_tile_N2 * (src.m_impl_offset.m_tile_N1 * i_tile0 + i_tile1) + i_tile2) + i_tile3) + i_tile4) << src_offset_type::SHIFT_5T))) // offset to start of the // tile , dst_offset_type()); } }; // Rank 6 template class ViewMapping::type // void , Kokkos::ViewTraits< T******, Kokkos::Experimental::LayoutTiled< OuterP, InnerP, N0, N1, N2, N3, N4, N5, N6, N7, true>, P...>, Kokkos::Experimental::LayoutTiled, iType0, iType1, iType2, iType3, iType4, iType5> { public: using src_layout = Kokkos::Experimental::LayoutTiled; using src_traits = Kokkos::ViewTraits; static constexpr bool is_outer_left = (OuterP == Kokkos::Iterate::Left); static constexpr bool is_inner_left = (InnerP == Kokkos::Iterate::Left); using array_layout = typename std::conditional::type; using traits = Kokkos::ViewTraits; using type = Kokkos::View; KOKKOS_INLINE_FUNCTION static void assign( ViewMapping& dst, const ViewMapping& src, const src_layout&, const iType0 i_tile0, const iType1 i_tile1, const iType2 i_tile2, const iType3 i_tile3, const iType4 i_tile4, const iType5 i_tile5) { using dst_map_type = ViewMapping; using src_map_type = ViewMapping; using dst_handle_type = typename dst_map_type::handle_type; using dst_offset_type = typename dst_map_type::offset_type; using src_offset_type = typename src_map_type::offset_type; dst = dst_map_type( dst_handle_type( src.m_impl_handle + (is_outer_left ? ((i_tile0 + src.m_impl_offset.m_tile_N0 * (i_tile1 + src.m_impl_offset.m_tile_N1 * (i_tile2 + src.m_impl_offset.m_tile_N2 * (i_tile3 + src.m_impl_offset.m_tile_N3 * (i_tile4 + src.m_impl_offset.m_tile_N4 * i_tile5))))) << src_offset_type::SHIFT_6T) : ((src.m_impl_offset.m_tile_N5 * (src.m_impl_offset.m_tile_N4 * (src.m_impl_offset.m_tile_N3 * (src.m_impl_offset.m_tile_N2 * (src.m_impl_offset.m_tile_N1 * i_tile0 + i_tile1) + i_tile2) + i_tile3) + i_tile4) + i_tile5) << src_offset_type::SHIFT_6T))) // offset to start of the // tile , dst_offset_type()); } }; // Rank 7 template class ViewMapping::type // void , Kokkos::ViewTraits< T*******, Kokkos::Experimental::LayoutTiled< OuterP, InnerP, N0, N1, N2, N3, N4, N5, N6, N7, true>, P...>, Kokkos::Experimental::LayoutTiled, iType0, iType1, iType2, iType3, iType4, iType5, iType6> { public: using src_layout = Kokkos::Experimental::LayoutTiled; using src_traits = Kokkos::ViewTraits; static constexpr bool is_outer_left = (OuterP == Kokkos::Iterate::Left); static constexpr bool is_inner_left = (InnerP == Kokkos::Iterate::Left); using array_layout = typename std::conditional::type; using traits = Kokkos::ViewTraits; using type = Kokkos::View; KOKKOS_INLINE_FUNCTION static void assign( ViewMapping& dst, const ViewMapping& src, const src_layout&, const iType0 i_tile0, const iType1 i_tile1, const iType2 i_tile2, const iType3 i_tile3, const iType4 i_tile4, const iType5 i_tile5, const iType6 i_tile6) { using dst_map_type = ViewMapping; using src_map_type = ViewMapping; using dst_handle_type = typename dst_map_type::handle_type; using dst_offset_type = typename dst_map_type::offset_type; using src_offset_type = typename src_map_type::offset_type; dst = dst_map_type( dst_handle_type( src.m_impl_handle + (is_outer_left ? ((i_tile0 + src.m_impl_offset.m_tile_N0 * (i_tile1 + src.m_impl_offset.m_tile_N1 * (i_tile2 + src.m_impl_offset.m_tile_N2 * (i_tile3 + src.m_impl_offset.m_tile_N3 * (i_tile4 + src.m_impl_offset.m_tile_N4 * (i_tile5 + src.m_impl_offset.m_tile_N5 * i_tile6)))))) << src_offset_type::SHIFT_7T) : ((src.m_impl_offset.m_tile_N6 * (src.m_impl_offset.m_tile_N5 * (src.m_impl_offset.m_tile_N4 * (src.m_impl_offset.m_tile_N3 * (src.m_impl_offset.m_tile_N2 * (src.m_impl_offset.m_tile_N1 * i_tile0 + i_tile1) + i_tile2) + i_tile3) + i_tile4) + i_tile5) + i_tile6) << src_offset_type::SHIFT_7T))) // offset to start of the // tile , dst_offset_type()); } }; // Rank 8 template class ViewMapping::type // void , Kokkos::ViewTraits< T********, Kokkos::Experimental::LayoutTiled< OuterP, InnerP, N0, N1, N2, N3, N4, N5, N6, N7, true>, P...>, Kokkos::Experimental::LayoutTiled, iType0, iType1, iType2, iType3, iType4, iType5, iType6, iType7> { public: using src_layout = Kokkos::Experimental::LayoutTiled; using src_traits = Kokkos::ViewTraits; static constexpr bool is_outer_left = (OuterP == Kokkos::Iterate::Left); static constexpr bool is_inner_left = (InnerP == Kokkos::Iterate::Left); using array_layout = typename std::conditional::type; using traits = Kokkos::ViewTraits; using type = Kokkos::View; KOKKOS_INLINE_FUNCTION static void assign( ViewMapping& dst, const ViewMapping& src, const src_layout&, const iType0 i_tile0, const iType1 i_tile1, const iType2 i_tile2, const iType3 i_tile3, const iType4 i_tile4, const iType5 i_tile5, const iType6 i_tile6, const iType7 i_tile7) { using dst_map_type = ViewMapping; using src_map_type = ViewMapping; using dst_handle_type = typename dst_map_type::handle_type; using dst_offset_type = typename dst_map_type::offset_type; using src_offset_type = typename src_map_type::offset_type; dst = dst_map_type( dst_handle_type( src.m_impl_handle + (is_outer_left ? ((i_tile0 + src.m_impl_offset.m_tile_N0 * (i_tile1 + src.m_impl_offset.m_tile_N1 * (i_tile2 + src.m_impl_offset.m_tile_N2 * (i_tile3 + src.m_impl_offset.m_tile_N3 * (i_tile4 + src.m_impl_offset.m_tile_N4 * (i_tile5 + src.m_impl_offset.m_tile_N5 * (i_tile6 + src.m_impl_offset.m_tile_N6 * i_tile7))))))) << src_offset_type::SHIFT_8T) : ((src.m_impl_offset.m_tile_N7 * (src.m_impl_offset.m_tile_N6 * (src.m_impl_offset.m_tile_N5 * (src.m_impl_offset.m_tile_N4 * (src.m_impl_offset.m_tile_N3 * (src.m_impl_offset.m_tile_N2 * (src.m_impl_offset.m_tile_N1 * i_tile0 + i_tile1) + i_tile2) + i_tile3) + i_tile4) + i_tile5) + i_tile6) + i_tile7) << src_offset_type::SHIFT_8T))) // offset to start of the // tile , dst_offset_type()); } }; } /* namespace Impl */ } /* namespace Kokkos */ //---------------------------------------- namespace Kokkos { // Rank 2 template KOKKOS_INLINE_FUNCTION Kokkos::View< T[N0][N1], typename std::conditional<(InnerP == Kokkos::Iterate::Left), Kokkos::LayoutLeft, Kokkos::LayoutRight>::type, P...> tile_subview(const Kokkos::View< T**, Kokkos::Experimental::LayoutTiled, P...>& src, const size_t i_tile0, const size_t i_tile1) { // Force the specialized ViewMapping for extracting a tile // by using the first subview argument as the layout. using array_layout = typename std::conditional<(InnerP == Kokkos::Iterate::Left), Kokkos::LayoutLeft, Kokkos::LayoutRight>::type; using SrcLayout = Kokkos::Experimental::LayoutTiled; return Kokkos::View(src, SrcLayout(), i_tile0, i_tile1); } // Rank 3 template KOKKOS_INLINE_FUNCTION Kokkos::View< T[N0][N1][N2], typename std::conditional<(InnerP == Kokkos::Iterate::Left), Kokkos::LayoutLeft, Kokkos::LayoutRight>::type, P...> tile_subview(const Kokkos::View< T***, Kokkos::Experimental::LayoutTiled, P...>& src, const size_t i_tile0, const size_t i_tile1, const size_t i_tile2) { // Force the specialized ViewMapping for extracting a tile // by using the first subview argument as the layout. using array_layout = typename std::conditional<(InnerP == Kokkos::Iterate::Left), Kokkos::LayoutLeft, Kokkos::LayoutRight>::type; using SrcLayout = Kokkos::Experimental::LayoutTiled; return Kokkos::View( src, SrcLayout(), i_tile0, i_tile1, i_tile2); } // Rank 4 template KOKKOS_INLINE_FUNCTION Kokkos::View< T[N0][N1][N2][N3], typename std::conditional<(InnerP == Kokkos::Iterate::Left), Kokkos::LayoutLeft, Kokkos::LayoutRight>::type, P...> tile_subview(const Kokkos::View< T****, Kokkos::Experimental::LayoutTiled, P...>& src, const size_t i_tile0, const size_t i_tile1, const size_t i_tile2, const size_t i_tile3) { // Force the specialized ViewMapping for extracting a tile // by using the first subview argument as the layout. using array_layout = typename std::conditional<(InnerP == Kokkos::Iterate::Left), Kokkos::LayoutLeft, Kokkos::LayoutRight>::type; using SrcLayout = Kokkos::Experimental::LayoutTiled; return Kokkos::View( src, SrcLayout(), i_tile0, i_tile1, i_tile2, i_tile3); } // Rank 5 template KOKKOS_INLINE_FUNCTION Kokkos::View< T[N0][N1][N2][N3][N4], typename std::conditional<(InnerP == Kokkos::Iterate::Left), Kokkos::LayoutLeft, Kokkos::LayoutRight>::type, P...> tile_subview(const Kokkos::View< T*****, Kokkos::Experimental::LayoutTiled, P...>& src, const size_t i_tile0, const size_t i_tile1, const size_t i_tile2, const size_t i_tile3, const size_t i_tile4) { // Force the specialized ViewMapping for extracting a tile // by using the first subview argument as the layout. using array_layout = typename std::conditional<(InnerP == Kokkos::Iterate::Left), Kokkos::LayoutLeft, Kokkos::LayoutRight>::type; using SrcLayout = Kokkos::Experimental::LayoutTiled; return Kokkos::View( src, SrcLayout(), i_tile0, i_tile1, i_tile2, i_tile3, i_tile4); } // Rank 6 template KOKKOS_INLINE_FUNCTION Kokkos::View< T[N0][N1][N2][N3][N4][N5], typename std::conditional<(InnerP == Kokkos::Iterate::Left), Kokkos::LayoutLeft, Kokkos::LayoutRight>::type, P...> tile_subview(const Kokkos::View< T******, Kokkos::Experimental::LayoutTiled, P...>& src, const size_t i_tile0, const size_t i_tile1, const size_t i_tile2, const size_t i_tile3, const size_t i_tile4, const size_t i_tile5) { // Force the specialized ViewMapping for extracting a tile // by using the first subview argument as the layout. using array_layout = typename std::conditional<(InnerP == Kokkos::Iterate::Left), Kokkos::LayoutLeft, Kokkos::LayoutRight>::type; using SrcLayout = Kokkos::Experimental::LayoutTiled; return Kokkos::View( src, SrcLayout(), i_tile0, i_tile1, i_tile2, i_tile3, i_tile4, i_tile5); } // Rank 7 template KOKKOS_INLINE_FUNCTION Kokkos::View< T[N0][N1][N2][N3][N4][N5][N6], typename std::conditional<(InnerP == Kokkos::Iterate::Left), Kokkos::LayoutLeft, Kokkos::LayoutRight>::type, P...> tile_subview(const Kokkos::View< T*******, Kokkos::Experimental::LayoutTiled, P...>& src, const size_t i_tile0, const size_t i_tile1, const size_t i_tile2, const size_t i_tile3, const size_t i_tile4, const size_t i_tile5, const size_t i_tile6) { // Force the specialized ViewMapping for extracting a tile // by using the first subview argument as the layout. using array_layout = typename std::conditional<(InnerP == Kokkos::Iterate::Left), Kokkos::LayoutLeft, Kokkos::LayoutRight>::type; using SrcLayout = Kokkos::Experimental::LayoutTiled; return Kokkos::View( src, SrcLayout(), i_tile0, i_tile1, i_tile2, i_tile3, i_tile4, i_tile5, i_tile6); } // Rank 8 template KOKKOS_INLINE_FUNCTION Kokkos::View< T[N0][N1][N2][N3][N4][N5][N6][N7], typename std::conditional<(InnerP == Kokkos::Iterate::Left), Kokkos::LayoutLeft, Kokkos::LayoutRight>::type, P...> tile_subview(const Kokkos::View< T********, Kokkos::Experimental::LayoutTiled, P...>& src, const size_t i_tile0, const size_t i_tile1, const size_t i_tile2, const size_t i_tile3, const size_t i_tile4, const size_t i_tile5, const size_t i_tile6, const size_t i_tile7) { // Force the specialized ViewMapping for extracting a tile // by using the first subview argument as the layout. using array_layout = typename std::conditional<(InnerP == Kokkos::Iterate::Left), Kokkos::LayoutLeft, Kokkos::LayoutRight>::type; using SrcLayout = Kokkos::Experimental::LayoutTiled; return Kokkos::View( src, SrcLayout(), i_tile0, i_tile1, i_tile2, i_tile3, i_tile4, i_tile5, i_tile6, i_tile7); } } /* namespace Kokkos */ //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- #endif /* #ifndef KOKKOS_EXPERIENTAL_VIEWLAYOUTTILE_HPP */