Kokkos Core Kernels Package  Version of the Day
Kokkos_HostSpace.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_HOSTSPACE_HPP
23 #define KOKKOS_HOSTSPACE_HPP
24 
25 #include <cstring>
26 #include <string>
27 #include <iosfwd>
28 #include <typeinfo>
29 
30 #include <Kokkos_Core_fwd.hpp>
31 #include <Kokkos_Concepts.hpp>
32 #include <Kokkos_MemoryTraits.hpp>
33 
34 #include <impl/Kokkos_Traits.hpp>
35 #include <impl/Kokkos_Error.hpp>
36 #include <impl/Kokkos_SharedAlloc.hpp>
37 #include <impl/Kokkos_Tools.hpp>
38 
39 #include "impl/Kokkos_HostSpace_deepcopy.hpp"
40 #include <impl/Kokkos_MemorySpace.hpp>
41 
42 /*--------------------------------------------------------------------------*/
43 
44 namespace Kokkos {
45 
46 namespace Impl {
47 
55 
61 bool lock_address_host_space(void* ptr);
62 
69 void unlock_address_host_space(void* ptr);
70 
71 } // namespace Impl
72 
73 } // namespace Kokkos
74 
75 namespace Kokkos {
81 class HostSpace {
82  public:
85  using size_type = size_t;
86 
93  using execution_space = DefaultHostExecutionSpace;
94 
96  using device_type = Kokkos::Device<execution_space, memory_space>;
97 
99  HostSpace();
100  HostSpace(HostSpace&& rhs) = default;
101  HostSpace(const HostSpace& rhs) = default;
102  HostSpace& operator=(HostSpace&&) = default;
103  HostSpace& operator=(const HostSpace&) = default;
104  ~HostSpace() = default;
105 
110  STD_MALLOC,
111  POSIX_MEMALIGN,
112  POSIX_MMAP,
113  INTEL_MM_ALLOC
114  };
115 
116  explicit HostSpace(const AllocationMechanism&);
117 
119  void* allocate(const size_t arg_alloc_size) const;
120  void* allocate(const char* arg_label, const size_t arg_alloc_size,
121  const size_t arg_logical_size = 0) const;
122 
124  void deallocate(void* const arg_alloc_ptr, const size_t arg_alloc_size) const;
125  void deallocate(const char* arg_label, void* const arg_alloc_ptr,
126  const size_t arg_alloc_size,
127  const size_t arg_logical_size = 0) const;
128 
129  private:
130  template <class, class, class, class>
132 
133  void* impl_allocate(const char* arg_label, const size_t arg_alloc_size,
134  const size_t arg_logical_size = 0,
135  const Kokkos::Tools::SpaceHandle =
136  Kokkos::Tools::make_space_handle(name())) const;
137  void impl_deallocate(const char* arg_label, void* const arg_alloc_ptr,
138  const size_t arg_alloc_size,
139  const size_t arg_logical_size = 0,
140  const Kokkos::Tools::SpaceHandle =
141  Kokkos::Tools::make_space_handle(name())) const;
142 
143  public:
145  static constexpr const char* name() { return m_name; }
146 
147  private:
148  AllocationMechanism m_alloc_mech;
149  static constexpr const char* m_name = "Host";
150  friend class Kokkos::Impl::SharedAllocationRecord<Kokkos::HostSpace, void>;
151 };
152 
153 } // namespace Kokkos
154 
155 //----------------------------------------------------------------------------
156 
157 namespace Kokkos {
158 
159 namespace Impl {
160 
162  Kokkos::HostSpace>::assignable,
163  "");
164 
165 template <typename S>
166 struct HostMirror {
167  private:
168  // If input execution space can access HostSpace then keep it.
169  // Example: Kokkos::OpenMP can access, Kokkos::Cuda cannot
170  enum {
172  typename S::execution_space::memory_space,
173  Kokkos::HostSpace>::accessible
174  };
175 
176  // If HostSpace can access memory space then keep it.
177  // Example: Cannot access Kokkos::CudaSpace, can access Kokkos::CudaUVMSpace
178  enum {
179  keep_mem =
181  typename S::memory_space>::accessible
182  };
183 
184  public:
185  using Space = std::conditional_t<
186  keep_exe && keep_mem, S,
187  std::conditional_t<keep_mem,
188  Kokkos::Device<Kokkos::HostSpace::execution_space,
189  typename S::memory_space>,
191 };
192 
193 } // namespace Impl
194 
195 } // namespace Kokkos
196 
197 //----------------------------------------------------------------------------
198 
199 namespace Kokkos {
200 
201 namespace Impl {
202 
203 template <>
204 class SharedAllocationRecord<Kokkos::HostSpace, void>
205  : public SharedAllocationRecordCommon<Kokkos::HostSpace> {
206  private:
207  friend Kokkos::HostSpace;
208  friend class SharedAllocationRecordCommon<Kokkos::HostSpace>;
209 
210  using base_t = SharedAllocationRecordCommon<Kokkos::HostSpace>;
211  using RecordBase = SharedAllocationRecord<void, void>;
212 
213  SharedAllocationRecord(const SharedAllocationRecord&) = delete;
214  SharedAllocationRecord& operator=(const SharedAllocationRecord&) = delete;
215 
216 #ifdef KOKKOS_ENABLE_DEBUG
217 
218  static RecordBase s_root_record;
219 #endif
220 
221  const Kokkos::HostSpace m_space;
222 
223  protected:
224  ~SharedAllocationRecord();
225  SharedAllocationRecord() = default;
226 
227  // This constructor does not forward to the one without exec_space arg
228  // in order to work around https://github.com/kokkos/kokkos/issues/5258
229  // This constructor is templated so I can't just put it into the cpp file
230  // like the other constructor.
231  template <typename ExecutionSpace>
232  SharedAllocationRecord(
233  const ExecutionSpace& /* exec_space*/, const Kokkos::HostSpace& arg_space,
234  const std::string& arg_label, const size_t arg_alloc_size,
235  const RecordBase::function_type arg_dealloc = &deallocate)
236  : base_t(
237 #ifdef KOKKOS_ENABLE_DEBUG
238  &SharedAllocationRecord<Kokkos::HostSpace, void>::s_root_record,
239 #endif
240  Impl::checked_allocation_with_header(arg_space, arg_label,
241  arg_alloc_size),
242  sizeof(SharedAllocationHeader) + arg_alloc_size, arg_dealloc,
243  arg_label),
244  m_space(arg_space) {
245  this->base_t::_fill_host_accessible_header_info(*RecordBase::m_alloc_ptr,
246  arg_label);
247  }
248 
249  SharedAllocationRecord(
250  const Kokkos::HostSpace& arg_space, const std::string& arg_label,
251  const size_t arg_alloc_size,
252  const RecordBase::function_type arg_dealloc = &deallocate);
253 
254  public:
255  KOKKOS_INLINE_FUNCTION static SharedAllocationRecord* allocate(
256  const Kokkos::HostSpace& arg_space, const std::string& arg_label,
257  const size_t arg_alloc_size) {
258  KOKKOS_IF_ON_HOST((return new SharedAllocationRecord(arg_space, arg_label,
259  arg_alloc_size);))
260  KOKKOS_IF_ON_DEVICE(((void)arg_space; (void)arg_label; (void)arg_alloc_size;
261  return nullptr;))
262  }
263 };
264 
265 } // namespace Impl
266 
267 } // namespace Kokkos
268 
269 //----------------------------------------------------------------------------
270 
271 namespace Kokkos {
272 
273 namespace Impl {
274 
275 template <class DT, class... DP>
276 struct ZeroMemset<typename HostSpace::execution_space, DT, DP...> {
277  ZeroMemset(const typename HostSpace::execution_space& exec,
278  const View<DT, DP...>& dst,
279  typename View<DT, DP...>::const_value_type&) {
280  // Host spaces, except for HPX, are synchronous and we need to fence for HPX
281  // since we can't properly enqueue a std::memset otherwise.
282  // We can't use exec.fence() directly since we don't have a full definition
283  // of HostSpace here.
284  hostspace_fence(exec);
285  using ValueType = typename View<DT, DP...>::value_type;
286  std::memset(dst.data(), 0, sizeof(ValueType) * dst.size());
287  }
288 
289  ZeroMemset(const View<DT, DP...>& dst,
290  typename View<DT, DP...>::const_value_type&) {
291  using ValueType = typename View<DT, DP...>::value_type;
292  std::memset(dst.data(), 0, sizeof(ValueType) * dst.size());
293  }
294 };
295 
296 template <>
297 struct DeepCopy<HostSpace, HostSpace, DefaultHostExecutionSpace> {
298  DeepCopy(void* dst, const void* src, size_t n) {
299  hostspace_parallel_deepcopy(dst, src, n);
300  }
301 
302  DeepCopy(const DefaultHostExecutionSpace& exec, void* dst, const void* src,
303  size_t n) {
304  hostspace_parallel_deepcopy_async(exec, dst, src, n);
305  }
306 };
307 
308 template <class ExecutionSpace>
309 struct DeepCopy<HostSpace, HostSpace, ExecutionSpace> {
310  DeepCopy(void* dst, const void* src, size_t n) {
311  hostspace_parallel_deepcopy(dst, src, n);
312  }
313 
314  DeepCopy(const ExecutionSpace& exec, void* dst, const void* src, size_t n) {
315  exec.fence(
316  "Kokkos::Impl::DeepCopy<HostSpace, HostSpace, "
317  "ExecutionSpace>::DeepCopy: fence before copy");
318  hostspace_parallel_deepcopy_async(dst, src, n);
319  }
320 };
321 
322 } // namespace Impl
323 
324 } // namespace Kokkos
325 
326 #endif // #define KOKKOS_HOSTSPACE_HPP
View
void unlock_address_host_space(void *ptr)
Release lock for the address.
AllocationMechanism
Non-default memory space instance to choose allocation mechansim, if available.
void * allocate(const size_t arg_alloc_size) const
Allocate untracked memory in the space.
Memory management for host memory.
static constexpr const char * name()
Return Name of the MemorySpace.
void init_lock_array_host_space()
Initialize lock array for arbitrary size atomics.
Kokkos::Device< execution_space, memory_space > device_type
This memory space preferred device_type.
HostSpace()
Default memory space instance.
void deallocate(void *const arg_alloc_ptr, const size_t arg_alloc_size) const
Deallocate untracked memory in the space.
DefaultHostExecutionSpace execution_space
Default execution space for this memory space.
LogicalMemorySpace is a space that is identical to another space, but differentiable by name and temp...
Definition: dummy.cpp:17
bool lock_address_host_space(void *ptr)
Acquire a lock for the address.
Access relationship between DstMemorySpace and SrcMemorySpace.