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:4
49 // parallel-for unit test.
50 // In this test, different elements of an array are updated by different
51 // threads.
52
53 namespace Test {
54
55 using value_type = double;
56 int num_elements = 10;
57
58 struct ParallelForFunctor {
59 value_type *_data;
60 const value_type _value;
61
ParallelForFunctorTest::ParallelForFunctor62 ParallelForFunctor(value_type *data, const value_type value)
63 : _data(data), _value(value) {}
64
65 KOKKOS_INLINE_FUNCTION
operator ()Test::ParallelForFunctor66 void operator()(const int i) const { _data[i] = (i + 1) * _value; }
67 };
68
69 template <class ExecSpace>
70 struct TestParallel_For {
71 // Memory space type for Device and Host data
72 using d_memspace_type = typename ExecSpace::memory_space;
73 using h_memspace_type = Kokkos::HostSpace;
74
75 value_type *deviceData, *hostData;
76 const value_type value = 0.5;
77
78 // Check if the array values are updated correctly.
correctness_checkTest::TestParallel_For79 void correctness_check(value_type *data) {
80 for (int i = 0; i < num_elements; ++i) {
81 ASSERT_EQ((i + 1) * value, data[i])
82 << "Values in index " << i << " are incorrect";
83 }
84 }
85
86 // Routine to allocate memory in a specific memory space.
87 template <class MemSpace>
allocate_memTest::TestParallel_For88 value_type *allocate_mem(int N) {
89 return (static_cast<value_type *>(
90 Kokkos::kokkos_malloc<MemSpace>("deviceData", N * sizeof(value_type))));
91 }
92
93 // Routine to free the memory from a specific memory space.
94 template <class MemSpace>
free_memTest::TestParallel_For95 void free_mem(value_type *data) {
96 Kokkos::kokkos_free<MemSpace>(data);
97 }
98
initTest::TestParallel_For99 void init() {
100 // Allocate memory on Device space.
101 deviceData = allocate_mem<d_memspace_type>(num_elements);
102 ASSERT_NE(deviceData, nullptr);
103
104 // Allocate memory on Host space.
105 hostData = allocate_mem<h_memspace_type>(num_elements);
106 ASSERT_NE(hostData, nullptr);
107 }
108
check_correctness_and_cleanupTest::TestParallel_For109 void check_correctness_and_cleanup() {
110 // Copy the data back to Host memory space
111 Kokkos::Impl::DeepCopy<h_memspace_type, d_memspace_type>(
112 hostData, deviceData, num_elements * sizeof(value_type));
113
114 // Check if all data has been update correctly
115 correctness_check(hostData);
116
117 // free the allocated memory
118 free_mem<d_memspace_type>(deviceData);
119 free_mem<h_memspace_type>(hostData);
120 }
121
122 // A simple parallel for test with functors
simple_testTest::TestParallel_For123 void simple_test() {
124 // Allocates memory for num_elements number of value_type elements in the
125 // host and device memory spaces.
126 init();
127
128 // parallel-for functor called for num_elements number of iterations.
129 Kokkos::parallel_for("parallel_for",
130 Kokkos::RangePolicy<ExecSpace>(0, num_elements),
131 ParallelForFunctor(deviceData, value));
132
133 Kokkos::fence();
134 // Checks if parallel_for gave the correct results.
135 // Frees the allocated memory in init().
136 check_correctness_and_cleanup();
137 }
138
139 // A parallel_for test with user defined RangePolicy
range_policyTest::TestParallel_For140 void range_policy() {
141 // Allocates memory for num_elements number of value_type elements in the
142 // host and device memory spaces.
143 init();
144
145 // Creates a range policy that uses dynamic scheduling.
146 using range_policy_t =
147 Kokkos::RangePolicy<ExecSpace, Kokkos::Schedule<Kokkos::Dynamic> >;
148
149 // parallel-for functor with range-policy from 0 to num_elements iterations.
150 Kokkos::parallel_for("RangePolicy_ParallelFor",
151 range_policy_t(0, num_elements),
152 ParallelForFunctor(deviceData, value));
153
154 // Checks if parallel_for gave the correct results.
155 // Free the allocated memory in init().
156 check_correctness_and_cleanup();
157 }
158 };
159
TEST(TEST_CATEGORY,IncrTest_04_simple_parallelFor)160 TEST(TEST_CATEGORY, IncrTest_04_simple_parallelFor) {
161 if (std::is_same<Kokkos::DefaultExecutionSpace, TEST_EXECSPACE>::value) {
162 TestParallel_For<TEST_EXECSPACE> test;
163 test.simple_test();
164 }
165 }
166
TEST(TEST_CATEGORY,IncrTest_04_RangePolicy_parallelFor)167 TEST(TEST_CATEGORY, IncrTest_04_RangePolicy_parallelFor) {
168 TestParallel_For<TEST_EXECSPACE> test;
169 test.range_policy();
170 }
171
172 } // namespace Test
173