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 <TestHPX_Category.hpp>
47 
48 #include <hpx/config.hpp>
49 #include <hpx/include/lcos.hpp>
50 
51 #ifdef KOKKOS_ENABLE_HPX_ASYNC_DISPATCH
52 #ifndef HPX_COMPUTE_DEVICE_CODE
53 
54 namespace Test {
55 
56 namespace {
57 struct FunctorInitConstant {
58   Kokkos::View<int *, Kokkos::Experimental::HPX> a;
59   int c;
FunctorInitConstantTest::__anon6a1d44e30111::FunctorInitConstant60   FunctorInitConstant(Kokkos::View<int *, Kokkos::Experimental::HPX> a_, int c_)
61       : a(a_), c(c_) {}
62 
63   KOKKOS_INLINE_FUNCTION
operator ()Test::__anon6a1d44e30111::FunctorInitConstant64   void operator()(const int i) const { a(i) = c; }
65 };
66 
67 struct FunctorAdd {
68   Kokkos::View<int *, Kokkos::Experimental::HPX> a;
69   Kokkos::View<int *, Kokkos::Experimental::HPX> b;
70   int c;
FunctorAddTest::__anon6a1d44e30111::FunctorAdd71   FunctorAdd(Kokkos::View<int *, Kokkos::Experimental::HPX> a_,
72              Kokkos::View<int *, Kokkos::Experimental::HPX> b_, int c_)
73       : a(a_), b(b_), c(c_) {}
74 
75   KOKKOS_INLINE_FUNCTION
operator ()Test::__anon6a1d44e30111::FunctorAdd76   void operator()(const int i) const { b(i) += a(i) + c; }
77 };
78 
79 struct FunctorAddIndex {
80   Kokkos::View<int *, Kokkos::Experimental::HPX> a;
81   Kokkos::View<int *, Kokkos::Experimental::HPX> b;
FunctorAddIndexTest::__anon6a1d44e30111::FunctorAddIndex82   FunctorAddIndex(Kokkos::View<int *, Kokkos::Experimental::HPX> a_,
83                   Kokkos::View<int *, Kokkos::Experimental::HPX> b_)
84       : a(a_), b(b_) {}
85 
86   KOKKOS_INLINE_FUNCTION
operator ()Test::__anon6a1d44e30111::FunctorAddIndex87   void operator()(const int i) const { b(i) += a(i) + i; }
88 };
89 
90 struct FunctorPointwiseSum {
91   Kokkos::View<int *, Kokkos::Experimental::HPX> a;
92   Kokkos::View<int *, Kokkos::Experimental::HPX> b;
93   Kokkos::View<int *, Kokkos::Experimental::HPX> c;
FunctorPointwiseSumTest::__anon6a1d44e30111::FunctorPointwiseSum94   FunctorPointwiseSum(Kokkos::View<int *, Kokkos::Experimental::HPX> a_,
95                       Kokkos::View<int *, Kokkos::Experimental::HPX> b_,
96                       Kokkos::View<int *, Kokkos::Experimental::HPX> c_)
97       : a(a_), b(b_), c(c_) {}
98 
99   KOKKOS_INLINE_FUNCTION
operator ()Test::__anon6a1d44e30111::FunctorPointwiseSum100   void operator()(const int i) const { c(i) = a(i) + b(i); }
101 };
102 
103 struct FunctorReduce {
104   Kokkos::View<int *, Kokkos::Experimental::HPX> a;
FunctorReduceTest::__anon6a1d44e30111::FunctorReduce105   FunctorReduce(Kokkos::View<int *, Kokkos::Experimental::HPX> a_) : a(a_) {}
106 
107   KOKKOS_INLINE_FUNCTION
operator ()Test::__anon6a1d44e30111::FunctorReduce108   void operator()(const int i, int &lsum) const { lsum += a(i); }
109 };
110 }  // namespace
111 
TEST(hpx,independent_instances)112 TEST(hpx, independent_instances) {
113   Kokkos::InitArguments arguments{-1, -1, -1, false};
114   Kokkos::initialize(arguments);
115 
116   const int n = 100;
117   const int c = 1;
118   const int d = 3;
119 
120   {
121     Kokkos::View<int *, Kokkos::Experimental::HPX> v1("v1", n);
122     Kokkos::View<int *, Kokkos::Experimental::HPX> v2("v2", n);
123     Kokkos::View<int *, Kokkos::Experimental::HPX> v3("v3", n);
124     Kokkos::View<int *, Kokkos::Experimental::HPX> v4("v4", n);
125     Kokkos::View<int, Kokkos::Experimental::HPX> sum_v("sum_v");
126 
127     Kokkos::Experimental::HPX hpx1(
128         Kokkos::Experimental::HPX::instance_mode::independent);
129     Kokkos::parallel_for(
130         "Test::hpx::independent_instances::init",
131         Kokkos::Experimental::require(
132             Kokkos::RangePolicy<Kokkos::Experimental::HPX>(hpx1, 0, n),
133             Kokkos::Experimental::WorkItemProperty::HintLightWeight),
134         FunctorInitConstant(v1, c));
135 
136     Kokkos::Experimental::HPX hpx2(hpx1.impl_get_future());
137     Kokkos::parallel_for(
138         "Test::hpx::independent_instances::add",
139         Kokkos::Experimental::require(
140             Kokkos::RangePolicy<Kokkos::Experimental::HPX>(hpx2, 0, n),
141             Kokkos::Experimental::WorkItemProperty::HintLightWeight),
142         FunctorAdd(v1, v2, d));
143 
144     Kokkos::Experimental::HPX hpx3(hpx1.impl_get_future());
145     Kokkos::parallel_for(
146         "Test::hpx::independent_instances::add_index",
147         Kokkos::Experimental::require(
148             Kokkos::RangePolicy<Kokkos::Experimental::HPX>(hpx3, 0, n),
149             Kokkos::Experimental::WorkItemProperty::HintLightWeight),
150         FunctorAddIndex(v1, v3));
151 
152     // NOTE: This monstrosity is used to collapse a future<tuple<future<void>,
153     // future<void>>> (return type of when_all) into a future<void> which is
154     // ready whenever the un-collapsed future would've been ready. HPX does not
155     // currently have the functionality to collapse this automatically.
156     Kokkos::Experimental::HPX hpx4(hpx::util::get<0>(hpx::split_future(
157         hpx::when_all(hpx2.impl_get_future(), hpx3.impl_get_future()))));
158     Kokkos::parallel_for(
159         "Test::hpx::independent_instances::pointwise_sum",
160         Kokkos::Experimental::require(
161             Kokkos::RangePolicy<Kokkos::Experimental::HPX>(hpx4, 0, n),
162             Kokkos::Experimental::WorkItemProperty::HintLightWeight),
163         FunctorPointwiseSum(v2, v3, v4));
164 
165     Kokkos::parallel_reduce(
166         "Test::hpx::independent_instances::reduce",
167         Kokkos::Experimental::require(
168             Kokkos::RangePolicy<Kokkos::Experimental::HPX>(hpx4, 0, n),
169             Kokkos::Experimental::WorkItemProperty::HintLightWeight),
170         FunctorReduce(v4), Kokkos::Sum<int>(sum_v));
171 
172     hpx4.fence();
173 
174     ASSERT_EQ(true, hpx1.impl_get_future().is_ready());
175     ASSERT_EQ(true, hpx2.impl_get_future().is_ready());
176     ASSERT_EQ(true, hpx3.impl_get_future().is_ready());
177     ASSERT_EQ(true, hpx4.impl_get_future().is_ready());
178 
179     const int expected_sum = n * (2 * c + d) + (n * (n - 1) / 2);
180     ASSERT_EQ(expected_sum, sum_v());
181   }
182 
183   Kokkos::finalize();
184 }
185 }  // namespace Test
186 
187 #endif
188 #endif
189