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 
45 #include <gtest/gtest.h>
46 
47 #include <Kokkos_Core.hpp>
48 #include <stdexcept>
49 #include <sstream>
50 #include <iostream>
51 
52 namespace Test {
53 
TEST(TEST_CATEGORY,view_remap)54 TEST(TEST_CATEGORY, view_remap) {
55   enum { N0 = 3, N1 = 2, N2 = 8, N3 = 9 };
56 
57 #ifdef KOKKOS_ENABLE_CUDA
58 #define EXECSPACE                                                     \
59   std::conditional<std::is_same<TEST_EXECSPACE, Kokkos::Cuda>::value, \
60                    Kokkos::CudaHostPinnedSpace, TEST_EXECSPACE>::type
61 #else
62 #ifdef KOKKOS_ENABLE_HIP
63 #define EXECSPACE                                                     \
64   std::conditional<                                                   \
65       std::is_same<TEST_EXECSPACE, Kokkos::Experimental::HIP>::value, \
66       Kokkos::Experimental::HIPHostPinnedSpace, TEST_EXECSPACE>::type
67 #else
68 #if defined(KOKKOS_ENABLE_OPENMPTARGET) || defined(KOKKOS_ENABLE_SYCL)
69 #define EXECSPACE Kokkos::HostSpace
70 #else
71 #define EXECSPACE TEST_EXECSPACE
72 #endif
73 #endif
74 #endif
75 
76   using output_type =
77       Kokkos::View<double * [N1][N2][N3], Kokkos::LayoutRight, EXECSPACE>;
78 
79   using input_type =
80       Kokkos::View<int* * [N2][N3], Kokkos::LayoutLeft, EXECSPACE>;
81 
82   using diff_type =
83       Kokkos::View<int * [N0][N2][N3], Kokkos::LayoutLeft, EXECSPACE>;
84 
85   output_type output("output", N0);
86   input_type input("input", N0, N1);
87   diff_type diff("diff", N0);
88 
89   Kokkos::fence();
90   int value = 0;
91 
92   for (size_t i3 = 0; i3 < N3; ++i3)
93     for (size_t i2 = 0; i2 < N2; ++i2)
94       for (size_t i1 = 0; i1 < N1; ++i1)
95         for (size_t i0 = 0; i0 < N0; ++i0) {
96           input(i0, i1, i2, i3) = ++value;
97         }
98 
99   Kokkos::fence();
100   // Kokkos::deep_copy( diff, input ); // Throw with incompatible shape.
101   Kokkos::deep_copy(output, input);
102   Kokkos::fence();
103 
104   value = 0;
105 
106   for (size_t i3 = 0; i3 < N3; ++i3)
107     for (size_t i2 = 0; i2 < N2; ++i2)
108       for (size_t i1 = 0; i1 < N1; ++i1)
109         for (size_t i0 = 0; i0 < N0; ++i0) {
110           ++value;
111           ASSERT_EQ(value, ((int)output(i0, i1, i2, i3)));
112         }
113 }
114 
TEST(TEST_CATEGORY,view_mirror_nonconst)115 TEST(TEST_CATEGORY, view_mirror_nonconst) {
116   Kokkos::View<int*, TEST_EXECSPACE> d_view("d_view", 10);
117   Kokkos::View<const int*, TEST_EXECSPACE> d_view_const = d_view;
118   auto h_view = Kokkos::create_mirror(d_view_const);
119   Kokkos::deep_copy(h_view, d_view_const);
120   auto h_view2 = Kokkos::create_mirror(Kokkos::HostSpace(), d_view_const);
121   Kokkos::deep_copy(h_view2, d_view_const);
122 }
123 
124 template <typename DataType, typename... Extents>
test_left_stride(Extents...extents)125 void test_left_stride(Extents... extents) {
126   using view_type =
127       Kokkos::View<DataType, Kokkos::LayoutLeft, Kokkos::HostSpace>;
128   view_type view("view", extents...);
129   size_t expected_stride = 1;
130   size_t all_strides[view_type::rank + 1];
131   view.stride(all_strides);
132   for (int i = 0; i < view_type::rank; ++i) {
133     ASSERT_EQ(view.stride(i), expected_stride);
134     ASSERT_EQ(all_strides[i], expected_stride);
135     expected_stride *= view.extent(i);
136   }
137 }
138 
139 template <typename DataType, typename... Extents>
test_right_stride(Extents...extents)140 void test_right_stride(Extents... extents) {
141   using view_type =
142       Kokkos::View<DataType, Kokkos::LayoutRight, Kokkos::HostSpace>;
143   view_type view("view", extents...);
144   size_t expected_stride = 1;
145   size_t all_strides[view_type::rank + 1];
146   view.stride(all_strides);
147   for (int ri = 0; ri < view_type::rank; ++ri) {
148     auto i = view_type::rank - 1 - ri;
149     ASSERT_EQ(view.stride(i), expected_stride);
150     ASSERT_EQ(all_strides[i], expected_stride);
151     expected_stride *= view.extent(i);
152   }
153 }
154 
155 template <typename DataType, typename... Extents>
test_stride(Extents...extents)156 void test_stride(Extents... extents) {
157   test_right_stride<DataType>(extents...);
158   test_left_stride<DataType>(extents...);
159 }
160 
TEST(TEST_CATEGORY,view_stride_method)161 TEST(TEST_CATEGORY, view_stride_method) {
162   test_stride<double[3]>();
163   test_stride<double*>(3);
164   test_stride<double[3][7][13]>();
165   test_stride<double***>(3, 7, 13);
166   // factorial(8) = 40320
167   test_stride<double[1][2][3][4][5][6][7][8]>();
168   test_stride<double********>(1, 2, 3, 4, 5, 6, 7, 8);
169 }
170 
test_anonymous_space()171 inline void test_anonymous_space() {
172   /* apparently TEST_EXECSPACE is sometimes a memory space. */
173   using ExecSpace = TEST_EXECSPACE::execution_space;
174   int host_array[10];
175   Kokkos::View<int[10], Kokkos::AnonymousSpace> host_anon_stat_view(host_array);
176   Kokkos::View<int*, Kokkos::AnonymousSpace> host_anon_dyn_view(host_array, 10);
177   Kokkos::View<int*, Kokkos::HostSpace> host_view("host_view", 10);
178   Kokkos::View<int*, Kokkos::AnonymousSpace> host_anon_assign_view = host_view;
179   for (int i = 0; i < 10; ++i) {
180     host_anon_stat_view(i) = host_anon_dyn_view(i) = 142;
181     host_anon_assign_view(i)                       = 142;
182   }
183   Kokkos::View<int**, Kokkos::LayoutRight, ExecSpace> d_view("d_view", 100, 10);
184 #ifdef KOKKOS_ENABLE_CXX11_DISPATCH_LAMBDA
185   Kokkos::parallel_for(
186       Kokkos::RangePolicy<ExecSpace, int>(0, 100), KOKKOS_LAMBDA(int i) {
187         int* ptr = &(d_view(i, 0));
188         Kokkos::View<int[10], Kokkos::AnonymousSpace> d_anon_stat_view(ptr);
189         Kokkos::View<int*, Kokkos::AnonymousSpace> d_anon_dyn_view(ptr, 10);
190         auto sub = Kokkos::subview(d_view, i, Kokkos::ALL());
191         Kokkos::View<int*, Kokkos::AnonymousSpace> d_anon_assign_view = sub;
192         for (int j = 0; j < 10; ++j) {
193           d_anon_stat_view(j) = 50;
194           d_anon_assign_view(j) += 50;
195           d_anon_dyn_view(j) += 42;
196         }
197       });
198   Kokkos::fence();
199 #endif
200 }
201 
TEST(TEST_CATEGORY,anonymous_space)202 TEST(TEST_CATEGORY, anonymous_space) { test_anonymous_space(); }
203 
204 template <class ExecSpace>
205 struct TestViewOverloadResolution {
206   // Overload based on value_type and rank
fooTest::TestViewOverloadResolution207   static int foo(Kokkos::View<const double**, ExecSpace> /*a*/) { return 1; }
fooTest::TestViewOverloadResolution208   static int foo(Kokkos::View<const int**, ExecSpace> /*a*/) { return 2; }
fooTest::TestViewOverloadResolution209   static int foo(Kokkos::View<const double***, ExecSpace> /*a*/) { return 3; }
210 
211   // Overload based on compile time dimensions
barTest::TestViewOverloadResolution212   static int bar(Kokkos::View<double * [3], ExecSpace> /*a*/) { return 4; }
barTest::TestViewOverloadResolution213   static int bar(Kokkos::View<double * [4], ExecSpace> /*a*/) { return 5; }
214 
test_function_overloadTest::TestViewOverloadResolution215   static void test_function_overload() {
216     Kokkos::View<double**, typename ExecSpace::execution_space::array_layout,
217                  ExecSpace>
218         a("A", 10, 3);
219     int data_type_1 = foo(a);
220     int data_type_3 =
221         foo(Kokkos::View<const double**,
222                          typename ExecSpace::execution_space::array_layout,
223                          ExecSpace>(a));
224     Kokkos::View<double***, typename ExecSpace::execution_space::array_layout,
225                  ExecSpace>
226         b("B", 10, 3, 4);
227     int data_type_2 = foo(b);
228     Kokkos::View<double * [3],
229                  typename ExecSpace::execution_space::array_layout, ExecSpace>
230         c(a);
231     int static_extent = bar(c);
232     ASSERT_EQ(1, data_type_1);
233     ASSERT_EQ(3, data_type_2);
234     ASSERT_EQ(1, data_type_3);
235     ASSERT_EQ(4, static_extent);
236   }
237 };
238 
TEST(TEST_CATEGORY,view_overload_resolution)239 TEST(TEST_CATEGORY, view_overload_resolution) {
240   TestViewOverloadResolution<TEST_EXECSPACE>::test_function_overload();
241 }
242 }  // namespace Test
243 
244 #include <TestViewIsAssignable.hpp>
245