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