/* //@HEADER // ************************************************************************ // // Kokkos v. 2.0 // Copyright (2014) Sandia Corporation // // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, // 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 SANDIA CORPORATION "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 SANDIA CORPORATION 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 */ #include #include #include #include #include namespace Test { TEST_F( TEST_CATEGORY, view_remap ) { enum { N0 = 3, N1 = 2, N2 = 8, N3 = 9 }; #ifdef KOKKOS_ENABLE_CUDA #define EXECSPACE std::conditional::value,Kokkos::CudaHostPinnedSpace,TEST_EXECSPACE>::type #else #ifdef KOKKOS_ENABLE_ROCM #define EXECSPACE std::conditional::value,Kokkos::Experimental::ROCmHostPinnedSpace,TEST_EXECSPACE>::type #else #if defined(KOKKOS_ENABLE_OPENMPTARGET) #define EXECSPACE Kokkos::HostSpace #else #define EXECSPACE TEST_EXECSPACE #endif #endif #endif typedef Kokkos::View< double*[N1][N2][N3], Kokkos::LayoutRight, EXECSPACE > output_type; typedef Kokkos::View< int**[N2][N3], Kokkos::LayoutLeft, EXECSPACE > input_type; typedef Kokkos::View< int*[N0][N2][N3], Kokkos::LayoutLeft, EXECSPACE > diff_type; output_type output( "output", N0 ); input_type input ( "input", N0, N1 ); diff_type diff ( "diff", N0 ); Kokkos::fence(); int value = 0; for ( size_t i3 = 0; i3 < N3; ++i3 ) for ( size_t i2 = 0; i2 < N2; ++i2 ) for ( size_t i1 = 0; i1 < N1; ++i1 ) for ( size_t i0 = 0; i0 < N0; ++i0 ) { input( i0, i1, i2, i3 ) = ++value; } Kokkos::fence(); // Kokkos::deep_copy( diff, input ); // Throw with incompatible shape. Kokkos::deep_copy( output, input ); Kokkos::fence(); value = 0; for ( size_t i3 = 0; i3 < N3; ++i3 ) for ( size_t i2 = 0; i2 < N2; ++i2 ) for ( size_t i1 = 0; i1 < N1; ++i1 ) for ( size_t i0 = 0; i0 < N0; ++i0 ) { ++value; ASSERT_EQ( value, ( (int) output( i0, i1, i2, i3 ) ) ); } } TEST_F( TEST_CATEGORY, view_mirror_nonconst ) { Kokkos::View d_view("d_view", 10); Kokkos::View d_view_const = d_view; auto h_view = Kokkos::create_mirror(d_view_const); Kokkos::deep_copy(h_view, d_view_const); auto h_view2 = Kokkos::create_mirror(Kokkos::HostSpace(), d_view_const); Kokkos::deep_copy(h_view2, d_view_const); } template void test_left_stride(Extents ... extents) { using view_type = Kokkos::View; view_type view("view", extents...); size_t expected_stride = 1; size_t all_strides[view_type::rank + 1]; view.stride(all_strides); for (int i = 0; i < view_type::rank; ++i) { ASSERT_EQ(view.stride(i), expected_stride); ASSERT_EQ(all_strides[i], expected_stride); expected_stride *= view.extent(i); } } template void test_right_stride(Extents ... extents) { using view_type = Kokkos::View; view_type view("view", extents...); size_t expected_stride = 1; size_t all_strides[view_type::rank + 1]; view.stride(all_strides); for (int ri = 0; ri < view_type::rank; ++ri) { auto i = view_type::rank - 1 - ri; ASSERT_EQ(view.stride(i), expected_stride); ASSERT_EQ(all_strides[i], expected_stride); expected_stride *= view.extent(i); } } template void test_stride(Extents ... extents) { test_right_stride(extents...); test_left_stride(extents...); } TEST_F( TEST_CATEGORY, view_stride_method ) { test_stride(); test_stride(3); test_stride(); test_stride(3, 7, 13); // factorial(8) = 40320 test_stride(); test_stride(1, 2, 3, 4, 5, 6, 7, 8); } inline void test_anonymous_space() { /* apparently TEST_EXECSPACE is sometimes a memory space. */ using ExecSpace = TEST_EXECSPACE::execution_space; int host_array[10]; Kokkos::View host_anon_stat_view(host_array); Kokkos::View host_anon_dyn_view(host_array, 10); Kokkos::View host_view("host_view", 10); Kokkos::View host_anon_assign_view = host_view; for (int i = 0; i < 10; ++i) { host_anon_stat_view(i) = host_anon_dyn_view(i) = 142; host_anon_assign_view(i) = 142; } Kokkos::View d_view("d_view", 100, 10); #ifdef KOKKOS_ENABLE_CXX11_DISPATCH_LAMBDA Kokkos::parallel_for(Kokkos::RangePolicy(0, 100), KOKKOS_LAMBDA(int i) { int* ptr = &(d_view(i, 0)); Kokkos::View d_anon_stat_view(ptr); Kokkos::View d_anon_dyn_view(ptr, 10); auto sub = Kokkos::subview(d_view, i, Kokkos::ALL()); Kokkos::View d_anon_assign_view = sub; for (int j = 0; j < 10; ++j) { d_anon_stat_view(j) = 50; d_anon_assign_view(j) += 50; d_anon_dyn_view(j) += 42; } }); Kokkos::fence(); #endif } TEST_F( TEST_CATEGORY, anonymous_space ) { test_anonymous_space(); } template struct TestViewOverloadResolution { // Overload based on value_type and rank static int foo(Kokkos::View a) { return 1; } static int foo(Kokkos::View a) { return 2; } static int foo(Kokkos::View a) { return 3; } // Overload based on compile time dimensions static int bar(Kokkos::View a) { return 4; } static int bar(Kokkos::View a) { return 5; } static void test_function_overload() { Kokkos::View a("A",10,3); int data_type_1 = foo(a); int data_type_3 = foo(Kokkos::View(a)); Kokkos::View b("B",10,3,4); int data_type_2 = foo(b); Kokkos::View c(a); int static_extent = bar(c); ASSERT_EQ(1,data_type_1); ASSERT_EQ(3,data_type_2); ASSERT_EQ(1,data_type_3); ASSERT_EQ(4,static_extent); } }; TEST_F( TEST_CATEGORY, view_overload_resolution ) { TestViewOverloadResolution::test_function_overload(); } }