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 <Kokkos_Core.hpp>
46 #include <gtest/gtest.h>
47
48 /// @Kokkos_Feature_Level_Required:6
49 // Unit Test for MDRangePolicy without Views uptil 4 ranks.
50 // For each of the MDRangePolicy test from 2-to-4 ranks, we create an equivalent
51 // dimensional array implemented in 1D. In each of these arrays we update the
52 // elements as a product of iterator indexes and a constant. At the end, we
53 // check for correctness.
54
55 namespace Test06 {
56
57 using value_type = double;
58
59 struct MDFunctor {
60 value_type *_data;
61 const value_type _delta;
62 const int N = 10;
63 const int M = 10;
64
MDFunctorTest06::MDFunctor65 MDFunctor(value_type *data, const value_type delta)
66 : _data(data), _delta(delta) {}
67
68 // 2D
69 KOKKOS_INLINE_FUNCTION
operator ()Test06::MDFunctor70 void operator()(const int i, const int j) const {
71 _data[i * M + j] = i * j * _delta;
72 }
73
74 // 3D
75 KOKKOS_INLINE_FUNCTION
operator ()Test06::MDFunctor76 void operator()(const int i, const int j, const int k) const {
77 _data[i * M * N + j * M + k] = i * j * k * _delta;
78 }
79
80 // 4D
81 KOKKOS_INLINE_FUNCTION
operator ()Test06::MDFunctor82 void operator()(const int i, const int j, const int k, const int l) const {
83 _data[i * M * N * M + j * M * N + k * M + l] = i * j * k * l * _delta;
84 }
85 };
86
87 template <class ExecSpace>
88 struct TestMDRangePolicy {
89 // Memory space type for Device and Host data
90 using d_memspace_type = typename ExecSpace::memory_space;
91 using h_memspace_type = Kokkos::HostSpace;
92
93 // Index Type for the iterator
94 using int_index = Kokkos::IndexType<int>;
95
96 // An MDRangePolicy for 2 nested loops
97 using MDPolicyType_2D = typename Kokkos::Experimental::MDRangePolicy<
98 ExecSpace, Kokkos::Experimental::Rank<2>, int_index>;
99
100 // An MDRangePolicy for 3 nested loops
101 using MDPolicyType_3D = typename Kokkos::Experimental::MDRangePolicy<
102 ExecSpace, Kokkos::Experimental::Rank<3>, int_index>;
103
104 // An MDRangePolicy for 4 nested loops
105 using MDPolicyType_4D = typename Kokkos::Experimental::MDRangePolicy<
106 ExecSpace, Kokkos::Experimental::Rank<4>, int_index>;
107
108 // Device and Host Data structure pointer
109 value_type *deviceData, *hostData;
110 const value_type delta = 0.5;
111 const int N = 10;
112 const int M = 10;
113
114 // Routine to allocate memory in a specific memory space.
115 template <class MemSpace>
allocate_memTest06::TestMDRangePolicy116 value_type *allocate_mem(int N_) {
117 return (static_cast<value_type *>(
118 Kokkos::kokkos_malloc<MemSpace>("Data", N_ * sizeof(value_type))));
119 }
120
121 // Routine to free the memory from a specific memory space.
122 template <class MemSpace>
free_memTest06::TestMDRangePolicy123 void free_mem(value_type *data) {
124 Kokkos::kokkos_free<MemSpace>(data);
125 }
126
127 // compare and equal
compare_equal_2DTest06::TestMDRangePolicy128 void compare_equal_2D() {
129 for (int i = 0; i < N; ++i)
130 for (int j = 0; j < M; ++j) ASSERT_EQ(hostData[i * M + j], i * j * delta);
131 }
132
133 // compare and equal
compare_equal_3DTest06::TestMDRangePolicy134 void compare_equal_3D() {
135 for (int i = 0; i < N; ++i)
136 for (int j = 0; j < M; ++j)
137 for (int k = 0; k < N; ++k)
138 ASSERT_EQ(hostData[i * M * N + j * M + k], i * j * k * delta);
139 }
140
141 // compare and equal
compare_equal_4DTest06::TestMDRangePolicy142 void compare_equal_4D() {
143 for (int i = 0; i < N; ++i)
144 for (int j = 0; j < M; ++j)
145 for (int k = 0; k < N; ++k)
146 for (int l = 0; l < M; ++l)
147 ASSERT_EQ(hostData[i * M * N * M + j * M * N + k * M + l],
148 i * j * k * l * delta);
149 }
150
151 // A 2-D MDRangePolicy
mdRange2DTest06::TestMDRangePolicy152 void mdRange2D() {
153 MDPolicyType_2D mdPolicy_2D({0, 0}, {N, M});
154
155 // Total number of elements
156 int num_elements = N * M;
157
158 // Allocate Memory for both device and host memory spaces
159 // Data[M*N]
160 deviceData = allocate_mem<d_memspace_type>(num_elements);
161 ASSERT_NE(deviceData, nullptr);
162
163 hostData = allocate_mem<h_memspace_type>(num_elements);
164 ASSERT_NE(hostData, nullptr);
165
166 // parallel_for call
167 MDFunctor Functor_2D(deviceData, delta);
168 Kokkos::parallel_for("MDRange2D", mdPolicy_2D, Functor_2D);
169
170 // Copy the data back to Host memory space
171 Kokkos::Impl::DeepCopy<h_memspace_type, d_memspace_type>(
172 hostData, deviceData, num_elements * sizeof(value_type));
173
174 // Check if all data has been update correctly
175 compare_equal_2D();
176
177 // free the allocated memory
178 free_mem<d_memspace_type>(deviceData);
179 free_mem<h_memspace_type>(hostData);
180 }
181
182 // A 3-D MDRangePolicy
mdRange3DTest06::TestMDRangePolicy183 void mdRange3D() {
184 MDPolicyType_3D mdPolicy_3D({0, 0, 0}, {N, M, N});
185
186 // Total number of elements
187 int num_elements = N * M * N;
188
189 // Allocate Memory for both device and host memory spaces
190 // Data[M*N*N]
191 deviceData = allocate_mem<d_memspace_type>(num_elements);
192 ASSERT_NE(deviceData, nullptr);
193
194 hostData = allocate_mem<h_memspace_type>(num_elements);
195 ASSERT_NE(hostData, nullptr);
196
197 // parallel_for call
198 MDFunctor Functor_3D(deviceData, delta);
199 Kokkos::parallel_for("MDRange3D", mdPolicy_3D, Functor_3D);
200
201 // Copy the data back to Host memory space
202 Kokkos::Impl::DeepCopy<h_memspace_type, d_memspace_type>(
203 hostData, deviceData, num_elements * sizeof(value_type));
204
205 // Check if all data has been update correctly
206 compare_equal_3D();
207
208 // free the allocated memory
209 free_mem<d_memspace_type>(deviceData);
210 free_mem<h_memspace_type>(hostData);
211 }
212
213 // A 4-D MDRangePolicy
mdRange4DTest06::TestMDRangePolicy214 void mdRange4D() {
215 MDPolicyType_4D mdPolicy_4D({0, 0, 0, 0}, {N, M, N, M});
216
217 // Total number of elements
218 int num_elements = N * M * N * M;
219
220 // Allocate Memory for both device and host memory spaces
221 // Data[M*N*N*M]
222 deviceData = allocate_mem<d_memspace_type>(num_elements);
223 ASSERT_NE(deviceData, nullptr);
224
225 hostData = allocate_mem<h_memspace_type>(num_elements);
226 ASSERT_NE(hostData, nullptr);
227
228 // parallel_for call
229 MDFunctor Functor_4D(deviceData, delta);
230 Kokkos::parallel_for("MDRange4D", mdPolicy_4D, Functor_4D);
231
232 // Copy the data back to Host memory space
233 Kokkos::Impl::DeepCopy<h_memspace_type, d_memspace_type>(
234 hostData, deviceData, num_elements * sizeof(value_type));
235
236 // Check if all data has been update correctly
237 compare_equal_4D();
238
239 // free the allocated memory
240 free_mem<d_memspace_type>(deviceData);
241 free_mem<h_memspace_type>(hostData);
242 }
243 };
244
245 } // namespace Test06
246
247 namespace Test {
248
249 // 2D MDRangePolicy
TEST(TEST_CATEGORY,IncrTest_06_mdrange2D)250 TEST(TEST_CATEGORY, IncrTest_06_mdrange2D) {
251 Test06::TestMDRangePolicy<TEST_EXECSPACE> test;
252 test.mdRange2D();
253 }
254
255 // 3D MDRangePolicy
TEST(TEST_CATEGORY,IncrTest_06_mdrange3D)256 TEST(TEST_CATEGORY, IncrTest_06_mdrange3D) {
257 Test06::TestMDRangePolicy<TEST_EXECSPACE> test;
258 test.mdRange3D();
259 }
260
261 // 4D MDRangePolicy
TEST(TEST_CATEGORY,IncrTest_06_mdrange4D)262 TEST(TEST_CATEGORY, IncrTest_06_mdrange4D) {
263 Test06::TestMDRangePolicy<TEST_EXECSPACE> test;
264 test.mdRange4D();
265 }
266
267 } // namespace Test
268