Kokkos Core Kernels Package  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Kokkos_OpenMPTargetSpace.hpp
1 //@HEADER
2 // ************************************************************************
3 //
4 // Kokkos v. 4.0
5 // Copyright (2022) National Technology & Engineering
6 // Solutions of Sandia, LLC (NTESS).
7 //
8 // Under the terms of Contract DE-NA0003525 with NTESS,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions.
12 // See https://kokkos.org/LICENSE for license information.
13 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
14 //
15 //@HEADER
16 
17 #ifndef KOKKOS_IMPL_PUBLIC_INCLUDE
18 #include <Kokkos_Macros.hpp>
19 static_assert(false,
20  "Including non-public Kokkos header files is not allowed.");
21 #endif
22 #ifndef KOKKOS_OPENMPTARGETSPACE_HPP
23 #define KOKKOS_OPENMPTARGETSPACE_HPP
24 
25 #include <cstring>
26 #include <string>
27 #include <iosfwd>
28 #include <typeinfo>
29 
30 #include <Kokkos_Core_fwd.hpp>
31 
32 #ifdef KOKKOS_ENABLE_OPENMPTARGET
33 
34 #include <OpenMPTarget/Kokkos_OpenMPTarget_Error.hpp>
35 #include <Kokkos_HostSpace.hpp>
36 #include <omp.h>
37 
38 /*--------------------------------------------------------------------------*/
39 
40 namespace Kokkos {
41 namespace Impl {
42 
49 // void init_lock_array_host_space();
50 
56 // bool lock_address_host_space(void* ptr);
57 
64 // void unlock_address_host_space(void* ptr);
65 
66 } // namespace Impl
67 } // namespace Kokkos
68 
69 namespace Kokkos {
70 namespace Impl {
71 
72 //----------------------------------------
73 
74 template <>
75 struct MemorySpaceAccess<Kokkos::HostSpace,
76  Kokkos::Experimental::OpenMPTargetSpace> {
77  enum : bool { assignable = false };
78  enum : bool { accessible = false };
79  enum : bool { deepcopy = true };
80 };
81 
82 //----------------------------------------
83 
84 template <>
85 struct MemorySpaceAccess<Kokkos::Experimental::OpenMPTargetSpace,
87  enum : bool { assignable = false };
88  enum : bool { accessible = false };
89  enum : bool { deepcopy = true };
90 };
91 
92 //----------------------------------------
93 } // namespace Impl
94 } // namespace Kokkos
95 
96 namespace Kokkos {
97 namespace Experimental {
98 
104 class OpenMPTargetSpace {
105  public:
107  using memory_space = OpenMPTargetSpace;
108  using size_type = unsigned;
109 
116  using execution_space = Kokkos::Experimental::OpenMPTarget;
117 
119  using device_type = Kokkos::Device<execution_space, memory_space>;
120 
121  /*--------------------------------*/
122 
124  OpenMPTargetSpace();
125  OpenMPTargetSpace(OpenMPTargetSpace&& rhs) = default;
126  OpenMPTargetSpace(const OpenMPTargetSpace& rhs) = default;
127  OpenMPTargetSpace& operator=(OpenMPTargetSpace&&) = default;
128  OpenMPTargetSpace& operator=(const OpenMPTargetSpace&) = default;
129  ~OpenMPTargetSpace() = default;
130 
132  void* allocate(const size_t arg_alloc_size) const;
133  void* allocate(const char* arg_label, const size_t arg_alloc_size,
134  const size_t arg_logical_size = 0) const;
135 
137  void deallocate(void* const arg_alloc_ptr,
138  const std::size_t arg_alloc_size) const;
139  void deallocate(const char* arg_label, void* const arg_alloc_ptr,
140  const size_t arg_alloc_size,
141  const size_t arg_logical_size = 0) const;
142 
143  static constexpr const char* name() { return "OpenMPTargetSpace"; }
144 
145  private:
146  void* impl_allocate(const char* arg_label, const size_t arg_alloc_size,
147  const size_t arg_logical_size = 0,
148  const Kokkos::Tools::SpaceHandle =
149  Kokkos::Tools::make_space_handle(name())) const;
150  void impl_deallocate(const char* arg_label, void* const arg_alloc_ptr,
151  const size_t arg_alloc_size,
152  const size_t arg_logical_size = 0,
153  const Kokkos::Tools::SpaceHandle =
154  Kokkos::Tools::make_space_handle(name())) const;
155 
156  friend class Kokkos::Impl::SharedAllocationRecord<
157  Kokkos::Experimental::OpenMPTargetSpace, void>;
158 };
159 } // namespace Experimental
160 } // namespace Kokkos
161 
162 //----------------------------------------------------------------------------
163 //----------------------------------------------------------------------------
164 
165 namespace Kokkos {
166 namespace Impl {
167 
168 template <>
169 class SharedAllocationRecord<Kokkos::Experimental::OpenMPTargetSpace, void>
170  : public HostInaccessibleSharedAllocationRecordCommon<
171  Kokkos::Experimental::OpenMPTargetSpace> {
172  private:
173  friend class HostInaccessibleSharedAllocationRecordCommon<
174  Kokkos::Experimental::OpenMPTargetSpace>;
175  friend class SharedAllocationRecordCommon<
176  Kokkos::Experimental::OpenMPTargetSpace>;
177  friend Kokkos::Experimental::OpenMPTargetSpace;
178 
179  using base_t = HostInaccessibleSharedAllocationRecordCommon<
180  Kokkos::Experimental::OpenMPTargetSpace>;
181  using RecordBase = SharedAllocationRecord<void, void>;
182 
183  SharedAllocationRecord(const SharedAllocationRecord&) = delete;
184  SharedAllocationRecord& operator=(const SharedAllocationRecord&) = delete;
185 
188  static RecordBase s_root_record;
189 
190  const Kokkos::Experimental::OpenMPTargetSpace m_space;
191 
192  protected:
193  ~SharedAllocationRecord();
194  SharedAllocationRecord() = default;
195 
196  template <typename ExecutionSpace>
197  SharedAllocationRecord(
198  const ExecutionSpace& /*exec_space*/,
199  const Kokkos::Experimental::OpenMPTargetSpace& arg_space,
200  const std::string& arg_label, const size_t arg_alloc_size,
201  const RecordBase::function_type arg_dealloc = &deallocate)
202  : SharedAllocationRecord(arg_space, arg_label, arg_alloc_size,
203  arg_dealloc) {}
204 
205  SharedAllocationRecord(
206  const Kokkos::Experimental::OpenMPTargetSpace& arg_space,
207  const std::string& arg_label, const size_t arg_alloc_size,
208  const RecordBase::function_type arg_dealloc = &deallocate);
209 
210  public:
211  KOKKOS_INLINE_FUNCTION static SharedAllocationRecord* allocate(
212  const Kokkos::Experimental::OpenMPTargetSpace& arg_space,
213  const std::string& arg_label, const size_t arg_alloc) {
214  KOKKOS_IF_ON_HOST(
215  (return new SharedAllocationRecord(arg_space, arg_label, arg_alloc);))
216  KOKKOS_IF_ON_DEVICE(
217  ((void)arg_space; (void)arg_label; (void)arg_alloc; return nullptr;))
218  }
219 };
220 
221 } // namespace Impl
222 } // namespace Kokkos
223 
224 //----------------------------------------------------------------------------
225 //----------------------------------------------------------------------------
226 
227 namespace Kokkos {
228 namespace Impl {
229 
230 // TODO: implement all possible deep_copies
231 template <class ExecutionSpace>
232 struct DeepCopy<Kokkos::Experimental::OpenMPTargetSpace,
233  Kokkos::Experimental::OpenMPTargetSpace, ExecutionSpace> {
234  DeepCopy(void* dst, const void* src, size_t n) {
235  // In the Release and RelWithDebInfo builds, the size of the memcpy should
236  // be greater than zero to avoid error. omp_target_memcpy returns zero on
237  // success.
238  if (n > 0)
239  KOKKOS_IMPL_OMPT_SAFE_CALL(omp_target_memcpy(
240  dst, const_cast<void*>(src), n, 0, 0, omp_get_default_device(),
241  omp_get_default_device()));
242  }
243  DeepCopy(const ExecutionSpace& exec, void* dst, const void* src, size_t n) {
244  exec.fence(
245  "Kokkos::Impl::DeepCopy<OpenMPTargetSpace, OpenMPTargetSpace>: fence "
246  "before "
247  "copy");
248  if (n > 0)
249  KOKKOS_IMPL_OMPT_SAFE_CALL(omp_target_memcpy(
250  dst, const_cast<void*>(src), n, 0, 0, omp_get_default_device(),
251  omp_get_default_device()));
252  }
253 };
254 
255 template <class ExecutionSpace>
256 struct DeepCopy<Kokkos::Experimental::OpenMPTargetSpace, HostSpace,
257  ExecutionSpace> {
258  DeepCopy(void* dst, const void* src, size_t n) {
259  if (n > 0)
260  KOKKOS_IMPL_OMPT_SAFE_CALL(omp_target_memcpy(
261  dst, const_cast<void*>(src), n, 0, 0, omp_get_default_device(),
262  omp_get_initial_device()));
263  }
264  DeepCopy(const ExecutionSpace& exec, void* dst, const void* src, size_t n) {
265  exec.fence(
266  "Kokkos::Impl::DeepCopy<OpenMPTargetSpace, HostSpace>: fence before "
267  "copy");
268  if (n > 0)
269  KOKKOS_IMPL_OMPT_SAFE_CALL(omp_target_memcpy(
270  dst, const_cast<void*>(src), n, 0, 0, omp_get_default_device(),
271  omp_get_initial_device()));
272  }
273 };
274 
275 template <class ExecutionSpace>
276 struct DeepCopy<HostSpace, Kokkos::Experimental::OpenMPTargetSpace,
277  ExecutionSpace> {
278  DeepCopy(void* dst, const void* src, size_t n) {
279  if (n > 0)
280  KOKKOS_IMPL_OMPT_SAFE_CALL(omp_target_memcpy(
281  dst, const_cast<void*>(src), n, 0, 0, omp_get_initial_device(),
282  omp_get_default_device()));
283  }
284  DeepCopy(const ExecutionSpace& exec, void* dst, const void* src, size_t n) {
285  exec.fence(
286  "Kokkos::Impl::DeepCopy<HostSpace, OpenMPTargetSpace>: fence before "
287  "copy");
288  if (n > 0)
289  KOKKOS_IMPL_OMPT_SAFE_CALL(omp_target_memcpy(
290  dst, const_cast<void*>(src), n, 0, 0, omp_get_initial_device(),
291  omp_get_default_device()));
292  }
293 };
294 
295 } // namespace Impl
296 } // namespace Kokkos
297 
298 #endif
299 #endif /* #define KOKKOS_OPENMPTARGETSPACE_HPP */
Memory management for host memory.