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<UrApiKind::urEventRelease>(*MInitEvent);
35  MInitEvent = {};
36  return OwnedUrEvent(Plugin);
37  } else {
38  return OwnedUrEvent(*MInitEvent, Plugin);
39  }
40  }
41  return OwnedUrEvent(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  ur_event_handle_t 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 
80  MemoryManager::copy_usm(reinterpret_cast<const void *>(
81  reinterpret_cast<uintptr_t>(MDeviceGlobalPtr) +
82  sizeof(MDeviceGlobalPtr)),
83  QueueImpl, MDeviceGlobalTSize, NewAlloc.MPtr,
84  std::vector<ur_event_handle_t>{}, &InitEvent,
85  nullptr);
86  NewAlloc.MInitEvent = InitEvent;
87  }
88 
89  CtxImpl->addAssociatedDeviceGlobal(MDeviceGlobalPtr);
90  return NewAlloc;
91 }
92 
94  const context_impl *CtxImpl) {
95  std::lock_guard<std::mutex> Lock{MDeviceToUSMPtrMapMutex};
96  for (device Device : CtxImpl->getDevices()) {
97  auto USMPtrIt =
98  MDeviceToUSMPtrMap.find({getSyclObjImpl(Device).get(), CtxImpl});
99  if (USMPtrIt != MDeviceToUSMPtrMap.end()) {
100  DeviceGlobalUSMMem &USMMem = USMPtrIt->second;
101  detail::usm::freeInternal(USMMem.MPtr, CtxImpl);
102  if (USMMem.MInitEvent.has_value())
103  CtxImpl->getPlugin()->call<UrApiKind::urEventRelease>(
104  *USMMem.MInitEvent);
105 #ifndef NDEBUG
106  // For debugging we set the event and memory to some recognizable values
107  // to allow us to check that this cleanup happens before erasure.
108  USMMem.MPtr = nullptr;
109  USMMem.MInitEvent = {};
110 #endif
111  MDeviceToUSMPtrMap.erase(USMPtrIt);
112  }
113  }
114 }
115 
116 } // namespace detail
117 } // namespace _V1
118 } // namespace sycl
static void copy_usm(const void *SrcMem, QueueImplPtr Queue, size_t Len, void *DstMem, std::vector< ur_event_handle_t > DepEvents, ur_event_handle_t *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:251
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:116
decltype(Obj::impl) const & getSyclObjImpl(const Obj &SyclObject)
Definition: impl_utils.hpp:31
std::shared_ptr< plugin > PluginPtr
Definition: ur.hpp:107
Definition: access.hpp:18
DeviceGlobalUSMMem & getOrAllocateDeviceGlobalUSM(const std::shared_ptr< queue_impl > &QueueImpl)
void removeAssociatedResources(const context_impl *CtxImpl)
OwnedUrEvent getInitEvent(const PluginPtr &Plugin)