DPC++ Runtime
Runtime libraries for oneAPI DPC++
device_global_map_entry.cpp
Go to the documentation of this file.
1 //==------------------ device_global_map_entry.cpp -------------------------==//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
11 #include <detail/event_info.hpp>
13 #include <detail/queue_impl.hpp>
14 #include <detail/usm/usm_impl.hpp>
15 
16 namespace sycl {
17 inline namespace _V1 {
18 namespace detail {
19 
21  // removeAssociatedResources is expected to have cleaned up both the pointer
22  // and the event. When asserts are enabled the values are set, so we check
23  // these here.
24  assert(MPtr == nullptr && "MPtr has not been cleaned up.");
25  assert(!MInitEvent.has_value() && "MInitEvent has not been cleaned up.");
26 }
27 
29  std::lock_guard<std::mutex> Lock(MInitEventMutex);
30  // If there is a init event we can remove it if it is done.
31  if (MInitEvent.has_value()) {
32  if (get_event_info<info::event::command_execution_status>(
33  *MInitEvent, Plugin) == info::event_command_status::complete) {
34  Plugin->call<PiApiKind::piEventRelease>(*MInitEvent);
35  MInitEvent = {};
36  return OwnedPiEvent(Plugin);
37  } else {
38  return OwnedPiEvent(*MInitEvent, Plugin);
39  }
40  }
41  return OwnedPiEvent(Plugin);
42 }
43 
45  const std::shared_ptr<queue_impl> &QueueImpl) {
47  "USM allocations should not be acquired for device_global with "
48  "device_image_scope property.");
49  const std::shared_ptr<context_impl> &CtxImpl = QueueImpl->getContextImplPtr();
50  const std::shared_ptr<device_impl> &DevImpl = QueueImpl->getDeviceImplPtr();
51  std::lock_guard<std::mutex> Lock(MDeviceToUSMPtrMapMutex);
52 
53  auto DGUSMPtr = MDeviceToUSMPtrMap.find({DevImpl.get(), CtxImpl.get()});
54  if (DGUSMPtr != MDeviceToUSMPtrMap.end())
55  return DGUSMPtr->second;
56 
57  void *NewDGUSMPtr = detail::usm::alignedAllocInternal(
58  0, MDeviceGlobalTSize, CtxImpl.get(), DevImpl.get(),
59  sycl::usm::alloc::device);
60 
61  auto NewAllocIt = MDeviceToUSMPtrMap.emplace(
62  std::piecewise_construct,
63  std::forward_as_tuple(DevImpl.get(), CtxImpl.get()),
64  std::forward_as_tuple(NewDGUSMPtr));
65  assert(NewAllocIt.second &&
66  "USM allocation for device and context already happened.");
67  DeviceGlobalUSMMem &NewAlloc = NewAllocIt.first->second;
68 
69  // Initialize here and save the event.
70  {
71  std::lock_guard<std::mutex> Lock(NewAlloc.MInitEventMutex);
72  sycl::detail::pi::PiEvent InitEvent;
73  // C++ guarantees members appear in memory in the order they are declared,
74  // so since the member variable that contains the initial contents of the
75  // device_global is right after the usm_ptr member variable we can do
76  // some pointer arithmetic to memcopy over this value to the usm_ptr. This
77  // value inside of the device_global will be zero-initialized if it was not
78  // given a value on construction.
79  MemoryManager::copy_usm(reinterpret_cast<const void *>(
80  reinterpret_cast<uintptr_t>(MDeviceGlobalPtr) +
81  sizeof(MDeviceGlobalPtr)),
82  QueueImpl, MDeviceGlobalTSize, NewAlloc.MPtr,
83  std::vector<sycl::detail::pi::PiEvent>{},
84  &InitEvent);
85  NewAlloc.MInitEvent = InitEvent;
86  }
87 
88  CtxImpl->addAssociatedDeviceGlobal(MDeviceGlobalPtr);
89  return NewAlloc;
90 }
91 
93  const context_impl *CtxImpl) {
94  std::lock_guard<std::mutex> Lock{MDeviceToUSMPtrMapMutex};
95  for (device Device : CtxImpl->getDevices()) {
96  auto USMPtrIt =
97  MDeviceToUSMPtrMap.find({getSyclObjImpl(Device).get(), CtxImpl});
98  if (USMPtrIt != MDeviceToUSMPtrMap.end()) {
99  DeviceGlobalUSMMem &USMMem = USMPtrIt->second;
100  detail::usm::freeInternal(USMMem.MPtr, CtxImpl);
101  if (USMMem.MInitEvent.has_value())
102  CtxImpl->getPlugin()->call<PiApiKind::piEventRelease>(
103  *USMMem.MInitEvent);
104 #ifndef NDEBUG
105  // For debugging we set the event and memory to some recognizable values
106  // to allow us to check that this cleanup happens before erasure.
107  USMMem.MPtr = nullptr;
108  USMMem.MInitEvent = {};
109 #endif
110  MDeviceToUSMPtrMap.erase(USMPtrIt);
111  }
112  }
113 }
114 
115 } // namespace detail
116 } // namespace _V1
117 } // namespace sycl
static void copy_usm(const void *SrcMem, QueueImplPtr Queue, size_t Len, void *DstMem, std::vector< sycl::detail::pi::PiEvent > DepEvents, sycl::detail::pi::PiEvent *OutEvent, const detail::EventImplPtr &OutEventImpl)
const std::vector< device > & getDevices() const
Unlike ‘get_info<info::context::devices>’, this function returns a reference.
const PluginPtr & getPlugin() const
The SYCL device class encapsulates a single SYCL device on which kernels may be executed.
Definition: device.hpp:64
void freeInternal(void *Ptr, const context_impl *CtxImpl)
Definition: usm_impl.cpp:284
void * alignedAllocInternal(size_t Alignment, size_t Size, const context_impl *CtxImpl, const device_impl *DevImpl, alloc Kind, const property_list &PropList)
Definition: usm_impl.cpp:139
decltype(Obj::impl) getSyclObjImpl(const Obj &SyclObject)
Definition: impl_utils.hpp:30
std::shared_ptr< plugin > PluginPtr
Definition: pi.hpp:48
Definition: access.hpp:18
pi_result piEventRelease(pi_event event)
Definition: pi_cuda.cpp:617
DeviceGlobalUSMMem & getOrAllocateDeviceGlobalUSM(const std::shared_ptr< queue_impl > &QueueImpl)
void removeAssociatedResources(const context_impl *CtxImpl)
OwnedPiEvent getInitEvent(const PluginPtr &Plugin)