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_Macros.hpp>
46
47 #if defined(KOKKOS_ENABLE_OPENMPTARGET) && defined(_OPENMP)
48
49 // FIXME_OPENMPTARGET - macro for workaround implementation in UniqueToken
50 // constructor. undef'ed at the end
51 #define KOKKOS_IMPL_OPENMPTARGET_WORKAROUND
52
53 #include <Kokkos_OpenMPTarget.hpp>
54 #include <OpenMPTarget/Kokkos_OpenMPTarget_UniqueToken.hpp>
55 #include <OpenMPTarget/Kokkos_OpenMPTarget_Instance.hpp>
56
57 #include <sstream>
58
59 namespace Kokkos {
60 namespace Experimental {
61 namespace Impl {
fence()62 void OpenMPTargetInternal::fence() {}
concurrency()63 int OpenMPTargetInternal::concurrency() { return 128000; }
name()64 const char* OpenMPTargetInternal::name() { return "OpenMPTarget"; }
print_configuration(std::ostream &,const bool)65 void OpenMPTargetInternal::print_configuration(std::ostream& /*stream*/,
66 const bool) {
67 // FIXME_OPENMPTARGET
68 printf("Using OpenMPTarget\n");
69 }
70
impl_finalize()71 void OpenMPTargetInternal::impl_finalize() {
72 m_is_initialized = false;
73 Kokkos::Impl::OpenMPTargetExec space;
74 if (space.m_lock_array != nullptr) space.clear_lock_array();
75
76 if (space.m_uniquetoken_ptr != nullptr)
77 Kokkos::kokkos_free<Kokkos::Experimental::OpenMPTargetSpace>(
78 space.m_uniquetoken_ptr);
79 }
impl_initialize()80 void OpenMPTargetInternal::impl_initialize() { m_is_initialized = true; }
impl_is_initialized()81 int OpenMPTargetInternal::impl_is_initialized() {
82 return m_is_initialized ? 1 : 0;
83 }
84
impl_singleton()85 OpenMPTargetInternal* OpenMPTargetInternal::impl_singleton() {
86 static OpenMPTargetInternal self;
87 return &self;
88 }
89
90 } // Namespace Impl
91
OpenMPTarget()92 OpenMPTarget::OpenMPTarget()
93 : m_space_instance(Impl::OpenMPTargetInternal::impl_singleton()) {}
94
name()95 const char* OpenMPTarget::name() {
96 return Impl::OpenMPTargetInternal::impl_singleton()->name();
97 }
print_configuration(std::ostream & stream,const bool detail)98 void OpenMPTarget::print_configuration(std::ostream& stream,
99 const bool detail) {
100 m_space_instance->print_configuration(stream, detail);
101 }
102
concurrency()103 int OpenMPTarget::concurrency() {
104 return Impl::OpenMPTargetInternal::impl_singleton()->concurrency();
105 }
fence()106 void OpenMPTarget::fence() {
107 Impl::OpenMPTargetInternal::impl_singleton()->fence();
108 }
109
impl_initialize()110 void OpenMPTarget::impl_initialize() { m_space_instance->impl_initialize(); }
impl_finalize()111 void OpenMPTarget::impl_finalize() { m_space_instance->impl_finalize(); }
impl_is_initialized()112 int OpenMPTarget::impl_is_initialized() {
113 return Impl::OpenMPTargetInternal::impl_singleton()->impl_is_initialized();
114 }
115 } // Namespace Experimental
116
117 namespace Impl {
118 int g_openmptarget_space_factory_initialized =
119 Kokkos::Impl::initialize_space_factory<OpenMPTargetSpaceInitializer>(
120 "160_OpenMPTarget");
121
initialize(const InitArguments & args)122 void OpenMPTargetSpaceInitializer::initialize(const InitArguments& args) {
123 // Prevent "unused variable" warning for 'args' input struct. If
124 // Serial::initialize() ever needs to take arguments from the input
125 // struct, you may remove this line of code.
126 (void)args;
127
128 if (std::is_same<Kokkos::Experimental::OpenMPTarget,
129 Kokkos::DefaultExecutionSpace>::value) {
130 Kokkos::Experimental::OpenMPTarget().impl_initialize();
131 // std::cout << "Kokkos::initialize() fyi: OpenMP enabled and initialized"
132 // << std::endl ;
133 } else {
134 // std::cout << "Kokkos::initialize() fyi: OpenMP enabled but not
135 // initialized" << std::endl ;
136 }
137 }
138
finalize(const bool all_spaces)139 void OpenMPTargetSpaceInitializer::finalize(const bool all_spaces) {
140 if (std::is_same<Kokkos::Experimental::OpenMPTarget,
141 Kokkos::DefaultExecutionSpace>::value ||
142 all_spaces) {
143 if (Kokkos::Experimental::OpenMPTarget().impl_is_initialized())
144 Kokkos::Experimental::OpenMPTarget().impl_finalize();
145 }
146 }
147
fence()148 void OpenMPTargetSpaceInitializer::fence() {
149 Kokkos::Experimental::OpenMPTarget::fence();
150 }
151
print_configuration(std::ostream & msg,const bool detail)152 void OpenMPTargetSpaceInitializer::print_configuration(std::ostream& msg,
153 const bool detail) {
154 msg << "OpenMPTarget Execution Space:" << std::endl;
155 msg << " KOKKOS_ENABLE_OPENMPTARGET: ";
156 msg << "yes" << std::endl;
157
158 msg << "\nOpenMPTarget Runtime Configuration:" << std::endl;
159 Kokkos::Experimental::OpenMPTarget().print_configuration(msg, detail);
160 }
161
162 } // namespace Impl
163 } // Namespace Kokkos
164
165 namespace Kokkos {
166 namespace Experimental {
167
168 UniqueToken<Kokkos::Experimental::OpenMPTarget,
169 Kokkos::Experimental::UniqueTokenScope::Global>::
UniqueToken(Kokkos::Experimental::OpenMPTarget const &)170 UniqueToken(Kokkos::Experimental::OpenMPTarget const&) {
171 #ifdef KOKKOS_IMPL_OPENMPTARGET_WORKAROUND
172 uint32_t* ptr = Kokkos::Impl::OpenMPTargetExec::m_uniquetoken_ptr;
173 int count = Kokkos::Experimental::OpenMPTarget().concurrency();
174 if (ptr == nullptr) {
175 int size = count * sizeof(uint32_t);
176 ptr = static_cast<uint32_t*>(
177 Kokkos::kokkos_malloc<Kokkos::Experimental::OpenMPTargetSpace>(
178 "Kokkos::OpenMPTarget::m_uniquetoken_ptr", size));
179 std::vector<uint32_t> h_buf(count, 0);
180 OMPT_SAFE_CALL(omp_target_memcpy(ptr, h_buf.data(), size, 0, 0,
181 omp_get_default_device(),
182 omp_get_initial_device()));
183
184 Kokkos::Impl::OpenMPTargetExec::m_uniquetoken_ptr = ptr;
185 }
186 #else
187 // FIXME_OPENMPTARGET - 2 versions of non-working implementations to fill `ptr`
188 // with 0's
189 // Version 1 - Creating a target region and filling the
190 // pointer Error - CUDA error: named symbol not found
191 #pragma omp target teams distribute parallel for is_device_ptr(ptr) \
192 map(to \
193 : size)
194 for (int i = 0; i < count; ++i) ptr[i] = 0;
195
196 // Version 2 : Allocating a view on the device and filling it with a scalar
197 // value of 0.
198 Kokkos::View<uint32_t*, Kokkos::Experimental::OpenMPTargetSpace> ptr_view(
199 ptr, count);
200 Kokkos::deep_copy(ptr_view, 0);
201 #endif
202 m_buffer = ptr;
203 m_count = count;
204 }
205 } // namespace Experimental
206 } // namespace Kokkos
207
208 #undef KOKKOS_IMPL_OPENMPTARGET_WORKAROUND
209 #endif // defined(KOKKOS_ENABLE_OPENMPTARGET) && defined(_OPENMP)
210