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:5
49 // Unit test for reduction of native data type.
50 // Assigns an index based value to elements of an array.
51 // Performs an reduction over the addition operation.
52 
53 namespace Test {
54 
55 using value_type       = double;
56 constexpr double value = 0.5;
57 
58 struct ReduceFunctor {
59   KOKKOS_INLINE_FUNCTION
operator ()Test::ReduceFunctor60   void operator()(const int i, double &UpdateSum) const {
61     UpdateSum += (i + 1) * value;
62   }
63 };
64 
65 struct NonTrivialReduceFunctor {
66   KOKKOS_INLINE_FUNCTION
operator ()Test::NonTrivialReduceFunctor67   void operator()(const int i, double &UpdateSum) const {
68     UpdateSum += (i + 1) * value;
69   }
70 
71   NonTrivialReduceFunctor()                                = default;
72   NonTrivialReduceFunctor(NonTrivialReduceFunctor const &) = default;
73   NonTrivialReduceFunctor(NonTrivialReduceFunctor &&)      = default;
74   NonTrivialReduceFunctor &operator=(NonTrivialReduceFunctor &&) = default;
75   NonTrivialReduceFunctor &operator=(NonTrivialReduceFunctor const &) = default;
~NonTrivialReduceFunctorTest::NonTrivialReduceFunctor76   ~NonTrivialReduceFunctor() {}
77 };
78 
79 template <class ExecSpace>
80 struct TestReduction {
81   value_type sum = 0.0;
82   const int m_num_elements;
83 
TestReductionTest::TestReduction84   TestReduction(int num_elements) : m_num_elements(num_elements) {}
85 
86   // compare and equal
check_correctnessTest::TestReduction87   void check_correctness() {
88     const int sum_local = (m_num_elements * (m_num_elements + 1)) / 2;
89 
90     ASSERT_EQ(sum, sum_local * value)
91         << "The reduced value does not match the expected answer";
92   }
93 
94   // Routine to allocate memory in a specific memory space.
95   template <class MemSpace>
allocate_memTest::TestReduction96   value_type *allocate_mem(int N) {
97     return (static_cast<value_type *>(
98         Kokkos::kokkos_malloc<MemSpace>("deviceData", N * sizeof(value_type))));
99   }
100 
101   // Routine to free the memory from a specific memory space.
102   template <class MemSpace>
free_memTest::TestReduction103   void free_mem(value_type *data) {
104     Kokkos::kokkos_free<MemSpace>(data);
105   }
106 
sum_reductionTest::TestReduction107   void sum_reduction() {
108     sum = 0.0;
109 
110     // Creates a range policy that uses dynamic schedule.
111     using range_policy =
112         Kokkos::RangePolicy<ExecSpace, Kokkos::Schedule<Kokkos::Dynamic> >;
113 
114     // parallel_reduce call with range policy over num_elements number of
115     // iterations
116     Kokkos::parallel_reduce("Reduction", range_policy(0, m_num_elements),
117                             ReduceFunctor{}, sum);
118 
119     check_correctness();
120   }
121 
non_trivial_sum_reductionTest::TestReduction122   void non_trivial_sum_reduction() {
123     sum = 0.0;
124 
125     // Creates a range policy that uses dynamic schedule.
126     using range_policy =
127         Kokkos::RangePolicy<ExecSpace, Kokkos::Schedule<Kokkos::Dynamic> >;
128 
129     // parallel_reduce call with range policy over num_elements number of
130     // iterations
131     Kokkos::parallel_reduce("Reduction", range_policy(0, m_num_elements),
132                             NonTrivialReduceFunctor{}, sum);
133 
134     check_correctness();
135   }
136 };
137 
TEST(TEST_CATEGORY,IncrTest_05_reduction)138 TEST(TEST_CATEGORY, IncrTest_05_reduction) {
139   for (unsigned int i = 0; i < 100; ++i) {
140     TestReduction<TEST_EXECSPACE> test(i);
141     test.sum_reduction();
142     test.non_trivial_sum_reduction();
143   }
144 }
145 
146 }  // namespace Test
147