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 #ifndef KOKKOS_TEST_DYNAMICVIEW_HPP
46 #define KOKKOS_TEST_DYNAMICVIEW_HPP
47 
48 #include <gtest/gtest.h>
49 #include <iostream>
50 #include <cstdlib>
51 #include <cstdio>
52 #include <Kokkos_Core.hpp>
53 
54 #include <Kokkos_DynamicView.hpp>
55 #include <impl/Kokkos_Timer.hpp>
56 
57 namespace Test {
58 
59 template <typename Scalar, class Space>
60 struct TestDynamicView {
61   using execution_space = typename Space::execution_space;
62   using memory_space    = typename Space::memory_space;
63 
64   using view_type = Kokkos::Experimental::DynamicView<Scalar*, Space>;
65 
66   using value_type = double;
67 
runTest::TestDynamicView68   static void run(unsigned arg_total_size) {
69     // Test: Create DynamicView, initialize size (via resize), run through
70     // parallel_for to set values, check values (via parallel_reduce); resize
71     // values and repeat
72     //   Case 1: min_chunk_size is a power of 2
73     {
74       {
75         view_type d1;
76         ASSERT_FALSE(d1.is_allocated());
77 
78         d1 = view_type("d1", 1024, arg_total_size);
79         view_type d2(d1);
80         view_type d3("d3", 1024, arg_total_size);
81 
82         ASSERT_FALSE(d1.is_allocated());
83         ASSERT_FALSE(d2.is_allocated());
84         ASSERT_FALSE(d3.is_allocated());
85 
86         unsigned d_size = arg_total_size / 8;
87         d1.resize_serial(d_size);
88         d2.resize_serial(d_size);
89         d3.resize_serial(d_size);
90 
91         ASSERT_TRUE(d1.is_allocated());
92         ASSERT_TRUE(d2.is_allocated());
93         ASSERT_TRUE(d3.is_allocated());
94       }
95       view_type da("da", 1024, arg_total_size);
96       ASSERT_EQ(da.size(), 0);
97       // Init
98       unsigned da_size = arg_total_size / 8;
99       da.resize_serial(da_size);
100       ASSERT_EQ(da.size(), da_size);
101 
102 #if defined(KOKKOS_ENABLE_CXX11_DISPATCH_LAMBDA)
103       Kokkos::parallel_for(
104           Kokkos::RangePolicy<execution_space>(0, da_size),
105           KOKKOS_LAMBDA(const int i) { da(i) = Scalar(i); });
106 
107       value_type result_sum = 0.0;
108       Kokkos::parallel_reduce(
109           Kokkos::RangePolicy<execution_space>(0, da_size),
110           KOKKOS_LAMBDA(const int i, value_type& partial_sum) {
111             partial_sum += (value_type)da(i);
112           },
113           result_sum);
114 
115       ASSERT_EQ(result_sum, (value_type)(da_size * (da_size - 1) / 2));
116 #endif
117 
118       // add 3x more entries i.e. 4x larger than previous size
119       // the first 1/4 should remain the same
120       unsigned da_resize = arg_total_size / 2;
121       da.resize_serial(da_resize);
122       ASSERT_EQ(da.size(), da_resize);
123 
124 #if defined(KOKKOS_ENABLE_CXX11_DISPATCH_LAMBDA)
125       Kokkos::parallel_for(
126           Kokkos::RangePolicy<execution_space>(da_size, da_resize),
127           KOKKOS_LAMBDA(const int i) { da(i) = Scalar(i); });
128 
129       value_type new_result_sum = 0.0;
130       Kokkos::parallel_reduce(
131           Kokkos::RangePolicy<execution_space>(da_size, da_resize),
132           KOKKOS_LAMBDA(const int i, value_type& partial_sum) {
133             partial_sum += (value_type)da(i);
134           },
135           new_result_sum);
136 
137       ASSERT_EQ(new_result_sum + result_sum,
138                 (value_type)(da_resize * (da_resize - 1) / 2));
139 #endif
140     }  // end scope
141 
142     // Test: Create DynamicView, initialize size (via resize), run through
143     // parallel_for to set values, check values (via parallel_reduce); resize
144     // values and repeat
145     //   Case 2: min_chunk_size is NOT a power of 2
146     {
147       view_type da("da", 1023, arg_total_size);
148       ASSERT_EQ(da.size(), 0);
149       // Init
150       unsigned da_size = arg_total_size / 8;
151       da.resize_serial(da_size);
152       ASSERT_EQ(da.size(), da_size);
153 
154 #if defined(KOKKOS_ENABLE_CXX11_DISPATCH_LAMBDA)
155       Kokkos::parallel_for(
156           Kokkos::RangePolicy<execution_space>(0, da_size),
157           KOKKOS_LAMBDA(const int i) { da(i) = Scalar(i); });
158 
159       value_type result_sum = 0.0;
160       Kokkos::parallel_reduce(
161           Kokkos::RangePolicy<execution_space>(0, da_size),
162           KOKKOS_LAMBDA(const int i, value_type& partial_sum) {
163             partial_sum += (value_type)da(i);
164           },
165           result_sum);
166 
167       ASSERT_EQ(result_sum, (value_type)(da_size * (da_size - 1) / 2));
168 #endif
169 
170       // add 3x more entries i.e. 4x larger than previous size
171       // the first 1/4 should remain the same
172       unsigned da_resize = arg_total_size / 2;
173       da.resize_serial(da_resize);
174       ASSERT_EQ(da.size(), da_resize);
175 
176 #if defined(KOKKOS_ENABLE_CXX11_DISPATCH_LAMBDA)
177       Kokkos::parallel_for(
178           Kokkos::RangePolicy<execution_space>(da_size, da_resize),
179           KOKKOS_LAMBDA(const int i) { da(i) = Scalar(i); });
180 
181       value_type new_result_sum = 0.0;
182       Kokkos::parallel_reduce(
183           Kokkos::RangePolicy<execution_space>(da_size, da_resize),
184           KOKKOS_LAMBDA(const int i, value_type& partial_sum) {
185             partial_sum += (value_type)da(i);
186           },
187           new_result_sum);
188 
189       ASSERT_EQ(new_result_sum + result_sum,
190                 (value_type)(da_resize * (da_resize - 1) / 2));
191 #endif
192     }  // end scope
193 
194     // Test: Create DynamicView, initialize size (via resize), run through
195     // parallel_for to set values, check values (via parallel_reduce); resize
196     // values and repeat
197     //   Case 3: resize reduces the size
198     {
199       view_type da("da", 1023, arg_total_size);
200       ASSERT_EQ(da.size(), 0);
201       // Init
202       unsigned da_size = arg_total_size / 2;
203       da.resize_serial(da_size);
204       ASSERT_EQ(da.size(), da_size);
205 
206 #if defined(KOKKOS_ENABLE_CXX11_DISPATCH_LAMBDA)
207       Kokkos::parallel_for(
208           Kokkos::RangePolicy<execution_space>(0, da_size),
209           KOKKOS_LAMBDA(const int i) { da(i) = Scalar(i); });
210 
211       value_type result_sum = 0.0;
212       Kokkos::parallel_reduce(
213           Kokkos::RangePolicy<execution_space>(0, da_size),
214           KOKKOS_LAMBDA(const int i, value_type& partial_sum) {
215             partial_sum += (value_type)da(i);
216           },
217           result_sum);
218 
219       ASSERT_EQ(result_sum, (value_type)(da_size * (da_size - 1) / 2));
220 #endif
221 
222       // remove the final 3/4 entries i.e. first 1/4 remain
223       unsigned da_resize = arg_total_size / 8;
224       da.resize_serial(da_resize);
225       ASSERT_EQ(da.size(), da_resize);
226 
227 #if defined(KOKKOS_ENABLE_CXX11_DISPATCH_LAMBDA)
228       Kokkos::parallel_for(
229           Kokkos::RangePolicy<execution_space>(0, da_resize),
230           KOKKOS_LAMBDA(const int i) { da(i) = Scalar(i); });
231 
232       value_type new_result_sum = 0.0;
233       Kokkos::parallel_reduce(
234           Kokkos::RangePolicy<execution_space>(0, da_resize),
235           KOKKOS_LAMBDA(const int i, value_type& partial_sum) {
236             partial_sum += (value_type)da(i);
237           },
238           new_result_sum);
239 
240       ASSERT_EQ(new_result_sum, (value_type)(da_resize * (da_resize - 1) / 2));
241 #endif
242     }  // end scope
243   }
244 };
245 
TEST(TEST_CATEGORY,dynamic_view)246 TEST(TEST_CATEGORY, dynamic_view) {
247   using TestDynView = TestDynamicView<double, TEST_EXECSPACE>;
248 
249   for (int i = 0; i < 10; ++i) {
250     TestDynView::run(100000 + 100 * i);
251   }
252 }
253 
254 }  // namespace Test
255 
256 #endif /* #ifndef KOKKOS_TEST_DYNAMICVIEW_HPP */
257