diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 4dfd2fbc10..7262b9c79f 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -3,6 +3,10 @@ # SPDX-License-Identifier: (BSD-3-Clause) ############################################################################### +raja_add_executable( + NAME reshape + SOURCES reshape.cpp) + raja_add_executable( NAME tut_launch_basic SOURCES tut_launch_basic.cpp) diff --git a/examples/reshape.cpp b/examples/reshape.cpp new file mode 100644 index 0000000000..e670e7754a --- /dev/null +++ b/examples/reshape.cpp @@ -0,0 +1,163 @@ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// +// Copyright (c) 2016-24, Lawrence Livermore National Security, LLC +// and RAJA project contributors. See the RAJA/LICENSE file for details. +// +// SPDX-License-Identifier: (BSD-3-Clause) +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// + +#include +#include +#include +#include + +#include "RAJA/RAJA.hpp" +#include "RAJA/util/Timer.hpp" + + +#include "memoryManager.hpp" + +/* + * RAJA Reshape method + * + * This example will intialize array using + * the RAJA Reshape method. The Reshape + * method offers right and left most unit + * stride. + * + */ + +/* + * Define number of threads in a GPU thread block + */ +#if defined(RAJA_ENABLE_CUDA) +constexpr int CUDA_BLOCK_SIZE = 256; +#endif + +#if defined(RAJA_ENABLE_HIP) +constexpr int HIP_BLOCK_SIZE = 256; +#endif + +// +//Function for checking results +// +void checkResult(int *ptr, int K, int N, int M); + +int main(int RAJA_UNUSED_ARG(argc), char **RAJA_UNUSED_ARG(argv[])) +{ + + std::cout << "\n\nRAJA reshape method example....\n"<< std::endl; + + const int K = 3; + const int N = 1; + const int M = 2; + + // Allocate memory for pointer + int *Rptr = memoryManager::allocate(K * N * M); + int *Lptr = memoryManager::allocate(K * N * M); + int *Cptr = memoryManager::allocate(K * N * M); + +//----------------------------------------------------------------------------// +// +// Initialize memory using right most unit stride +// +//----------------------------------------------------------------------------// + std::cout << "\n\nInitialize array with right most indexing...\n"; + auto Rview = RAJA::Reshape::get(Rptr, K, N, M); + + for(int k = 0; k < K; ++k) { + for(int n = 0; n < N; ++n) { + for(int m = 0; m < M; ++m) { + const int idx = m + M * (n + N * k); + Rview(k,n,m) = idx; + } + } + } + + checkResult(Rptr, K, N, M); + + +//----------------------------------------------------------------------------// +// +// Initialize memory using left most unit stride +// +//----------------------------------------------------------------------------// + std::cout << "\n\nInitialize array with left most indexing...\n"; + + auto Lview = RAJA::Reshape::get(Lptr, K, N, M); + + //Note the loop ordering has change from above + for(int m = 0; m < M; ++m) { + for(int n = 0; n < N; ++n) { + for(int k = 0; k < K; ++k) { + + const int idx = k + K * (n + N * m); + Lview(k,n,m) = idx; + } + } + } + + checkResult(Lptr, K, N, M); + + +//----------------------------------------------------------------------------// +// +// Initialize memory using custom ordering, longest stride starts at the left, +// right most is assumed to have unit stride. +// +//----------------------------------------------------------------------------// + std::cout << "\n\nInitialize array with custom indexing...\n"; + + using custom_seq = std::index_sequence<2U,0U,1U>; + + + auto Cview = RAJA::Reshape::get(Cptr, K, N, M); + + //Note the loop ordering has change from above + for(int m = 0; m < M; ++m) { + for(int k = 0; k < K; ++k) { + for(int n = 0; n < N; ++n) { + + const int idx = n + N * (k + K * m); + Cview(k,n,m) = idx; + } + } + } + + checkResult(Cptr, K, N, M); + + +// +// Clean up. +// + memoryManager::deallocate(Rptr); + memoryManager::deallocate(Lptr); + + std::cout << "\n DONE!...\n"; + return 0; +} + +// +// check result +// +void checkResult(int *ptr, int K, int N, int M) +{ + + bool status = true; + + for(int k = 0; k < K; ++k) { + for(int n = 0; n < N; ++n) { + for(int m = 0; m < M; ++m) { + const int idx = m + M * (n + N * k); + if (ptr[idx] != idx) { + status = false; + } + } + } + } + + if ( status ) { + std::cout << "\tresult -- PASS\n"; + } else { + std::cout << "\tresult -- FAIL\n"; + } +} diff --git a/include/RAJA/util/View.hpp b/include/RAJA/util/View.hpp index fcaee67f98..3d50beb120 100644 --- a/include/RAJA/util/View.hpp +++ b/include/RAJA/util/View.hpp @@ -1,3 +1,4 @@ + /*! ****************************************************************************** * @@ -18,12 +19,11 @@ #ifndef RAJA_VIEW_HPP #define RAJA_VIEW_HPP +#include #include #include "RAJA/config.hpp" - #include "RAJA/pattern/atomic.hpp" - #include "RAJA/util/IndexLayout.hpp" #include "RAJA/util/Layout.hpp" #include "RAJA/util/OffsetLayout.hpp" @@ -81,14 +81,14 @@ RAJA_INLINE View > make // select certain indices from a tuple, given a curated index sequence // returns linear index of layout(ar...) template -RAJA_HOST_DEVICE RAJA_INLINE +RAJA_HOST_DEVICE RAJA_INLINE auto selecttuple( Lay lyout, Tup&& tup, camp::idx_seq ) -> decltype( lyout( camp::get(std::forward(tup))... ) ) -{ +{ return lyout( camp::get(std::forward(tup))... ); @@ -234,7 +234,7 @@ struct MultiView { { RAJA_ABORT_OR_THROW( "Negative index while accessing array of pointers.\n" ); } - + auto idx = stripIndexType( removenth( layout, camp::forward_as_tuple( ar... ) ) ); return data[pidx][idx]; } @@ -296,6 +296,89 @@ RAJA_INLINE AtomicViewWrapper make_atomic_view( return RAJA::AtomicViewWrapper(view); } +struct layout_left { +}; +struct layout_right { +}; + +template +struct Reshape; + +namespace detail +{ +template +constexpr auto get_last_index(T last) +{ + return last; +} + +template +constexpr auto get_last_index(T0, T1 t1, Args... args) +{ + return get_last_index(t1, args...); +} +} // namespace detail + +template +struct Reshape> { + template + static auto get(T *ptr, Ts... s) + { + constexpr int N = sizeof...(Ts); + std::array extent{s...}; + + auto custom_layout = + RAJA::make_permuted_layout(extent, std::array{Is...}); + + constexpr auto unit_stride = detail::get_last_index(Is...); + using view_t = RAJA::View>; + + return view_t(ptr, custom_layout); + } +}; + +template <> +struct Reshape { + template + static auto get(T *ptr, Ts... s) + { + constexpr int N = sizeof...(Ts); + using view_t = RAJA::View>; + + return view_t(ptr, s...); + } +}; + +namespace detail +{ + +template +constexpr std::array make_reverse_array( + std::index_sequence) +{ + return std::array{sizeof...(Is) - 1U - Is...}; +} + +} // namespace detail + +template <> +struct Reshape { + template + static auto get(T *ptr, Ts... s) + { + constexpr int N = sizeof...(Ts); + + std::array extent{s...}; + + constexpr auto reverse_array = + detail::make_reverse_array(std::make_index_sequence{}); + + auto reverse_layout = RAJA::make_permuted_layout(extent, reverse_array); + using view_t = RAJA::View>; + + return view_t(ptr, reverse_layout); + } +}; } // namespace RAJA