DPC++ Runtime
Runtime libraries for oneAPI DPC++
queue.cpp
Go to the documentation of this file.
1 //==-------------- queue.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 
10 #include <detail/event_impl.hpp>
11 #include <detail/queue_impl.hpp>
12 #include <sycl/detail/common.hpp>
13 #include <sycl/event.hpp>
14 #include <sycl/exception_list.hpp>
16 #include <sycl/handler.hpp>
17 #include <sycl/queue.hpp>
18 
19 #include <algorithm>
20 
21 namespace sycl {
22 inline namespace _V1 {
23 
24 queue::queue(const context &SyclContext, const device_selector &DeviceSelector,
25  const async_handler &AsyncHandler, const property_list &PropList) {
26  const std::vector<device> Devs = SyclContext.get_devices();
27 
28  auto Comp = [&DeviceSelector](const device &d1, const device &d2) {
29  return DeviceSelector(d1) < DeviceSelector(d2);
30  };
31 
32  const device &SyclDevice = *std::max_element(Devs.begin(), Devs.end(), Comp);
33 
34  impl = std::make_shared<detail::queue_impl>(
35  detail::getSyclObjImpl(SyclDevice), detail::getSyclObjImpl(SyclContext),
37 }
38 
39 queue::queue(const context &SyclContext, const device &SyclDevice,
40  const async_handler &AsyncHandler, const property_list &PropList) {
41  impl = std::make_shared<detail::queue_impl>(
42  detail::getSyclObjImpl(SyclDevice), detail::getSyclObjImpl(SyclContext),
44 }
45 
46 queue::queue(const device &SyclDevice, const async_handler &AsyncHandler,
47  const property_list &PropList) {
48  impl = std::make_shared<detail::queue_impl>(
50 }
51 
52 queue::queue(const context &SyclContext, const device_selector &deviceSelector,
53  const property_list &PropList)
54  : queue(SyclContext, deviceSelector,
55  detail::getSyclObjImpl(SyclContext)->get_async_handler(),
56  PropList) {}
57 
58 queue::queue(const context &SyclContext, const device &SyclDevice,
59  const property_list &PropList)
60  : queue(SyclContext, SyclDevice,
61  detail::getSyclObjImpl(SyclContext)->get_async_handler(),
62  PropList) {}
63 
64 queue::queue(cl_command_queue clQueue, const context &SyclContext,
65  const async_handler &AsyncHandler) {
66  const property_list PropList{};
67  impl = std::make_shared<detail::queue_impl>(
68  reinterpret_cast<sycl::detail::pi::PiQueue>(clQueue),
70 }
71 
72 cl_command_queue queue::get() const { return impl->get(); }
73 
74 context queue::get_context() const { return impl->get_context(); }
75 
76 device queue::get_device() const { return impl->get_device(); }
77 
79  return impl->getCommandGraph()
82 }
83 
87  auto Graph = impl->getCommandGraph();
88  if (!Graph)
89  throw sycl::exception(
91  "ext_oneapi_get_graph() can only be called on recording queues.");
92 
96 }
97 
98 bool queue::is_host() const {
99  bool IsHost = impl->is_host();
100  assert(!IsHost && "queue::is_host should not be called in implementation.");
101  return IsHost;
102 }
103 
104 void queue::throw_asynchronous() { impl->throw_asynchronous(); }
105 
106 event queue::memset(void *Ptr, int Value, size_t Count,
107  const detail::code_location &CodeLoc) {
108  detail::tls_code_loc_t TlsCodeLocCapture(CodeLoc);
109  return impl->memset(impl, Ptr, Value, Count, {});
110 }
111 
112 event queue::memset(void *Ptr, int Value, size_t Count, event DepEvent,
113  const detail::code_location &CodeLoc) {
114  detail::tls_code_loc_t TlsCodeLocCapture(CodeLoc);
115  return impl->memset(impl, Ptr, Value, Count, {DepEvent});
116 }
117 
118 event queue::memset(void *Ptr, int Value, size_t Count,
119  const std::vector<event> &DepEvents,
120  const detail::code_location &CodeLoc) {
121  detail::tls_code_loc_t TlsCodeLocCapture(CodeLoc);
122  return impl->memset(impl, Ptr, Value, Count, DepEvents);
123 }
124 
125 event queue::memcpy(void *Dest, const void *Src, size_t Count,
126  const detail::code_location &CodeLoc) {
127  detail::tls_code_loc_t TlsCodeLocCapture(CodeLoc);
128  return impl->memcpy(impl, Dest, Src, Count, {}, CodeLoc);
129 }
130 
131 event queue::memcpy(void *Dest, const void *Src, size_t Count, event DepEvent,
132  const detail::code_location &CodeLoc) {
133  detail::tls_code_loc_t TlsCodeLocCapture(CodeLoc);
134  return impl->memcpy(impl, Dest, Src, Count, {DepEvent}, CodeLoc);
135 }
136 
137 event queue::memcpy(void *Dest, const void *Src, size_t Count,
138  const std::vector<event> &DepEvents,
139  const detail::code_location &CodeLoc) {
140  detail::tls_code_loc_t TlsCodeLocCapture(CodeLoc);
141  return impl->memcpy(impl, Dest, Src, Count, DepEvents, CodeLoc);
142 }
143 
144 event queue::mem_advise(const void *Ptr, size_t Length, pi_mem_advice Advice,
145  const detail::code_location &CodeLoc) {
146  detail::tls_code_loc_t TlsCodeLocCapture(CodeLoc);
147  return mem_advise(Ptr, Length, int(Advice));
148 }
149 
150 event queue::mem_advise(const void *Ptr, size_t Length, int Advice,
151  const detail::code_location &CodeLoc) {
152  detail::tls_code_loc_t TlsCodeLocCapture(CodeLoc);
153  return impl->mem_advise(impl, Ptr, Length, pi_mem_advice(Advice), {});
154 }
155 
156 event queue::mem_advise(const void *Ptr, size_t Length, int Advice,
157  event DepEvent, const detail::code_location &CodeLoc) {
158  detail::tls_code_loc_t TlsCodeLocCapture(CodeLoc);
159  return impl->mem_advise(impl, Ptr, Length, pi_mem_advice(Advice), {DepEvent});
160 }
161 
162 event queue::mem_advise(const void *Ptr, size_t Length, int Advice,
163  const std::vector<event> &DepEvents,
164  const detail::code_location &CodeLoc) {
165  detail::tls_code_loc_t TlsCodeLocCapture(CodeLoc);
166  return impl->mem_advise(impl, Ptr, Length, pi_mem_advice(Advice), DepEvents);
167 }
168 
169 event queue::discard_or_return(const event &Event) {
170  if (!(impl->MDiscardEvents))
171  return Event;
172  using detail::event_impl;
173  auto Impl = std::make_shared<event_impl>(event_impl::HES_Discarded);
174  return detail::createSyclObjFromImpl<event>(Impl);
175 }
176 
177 event queue::submit_impl(std::function<void(handler &)> CGH,
178  const detail::code_location &CodeLoc) {
179  return impl->submit(CGH, impl, CodeLoc);
180 }
181 
182 event queue::submit_impl(std::function<void(handler &)> CGH, queue SecondQueue,
183  const detail::code_location &CodeLoc) {
184  return impl->submit(CGH, impl, SecondQueue.impl, CodeLoc);
185 }
186 
187 event queue::submit_impl_and_postprocess(
188  std::function<void(handler &)> CGH, const detail::code_location &CodeLoc,
189  const SubmitPostProcessF &PostProcess) {
190  return impl->submit(CGH, impl, CodeLoc, &PostProcess);
191 }
192 
193 event queue::submit_impl_and_postprocess(
194  std::function<void(handler &)> CGH, queue SecondQueue,
195  const detail::code_location &CodeLoc,
196  const SubmitPostProcessF &PostProcess) {
197  return impl->submit(CGH, impl, SecondQueue.impl, CodeLoc, &PostProcess);
198 }
199 
201  impl->wait(CodeLoc);
202 }
203 
205  impl->wait_and_throw(CodeLoc);
206 }
207 
208 static event
210  // This function should not be called when a queue is recording to a graph,
211  // as a graph can record from multiple queues and we cannot guarantee the
212  // last node added by an in-order queue will be the last node added to the
213  // graph.
214  assert(!QueueImpl->getCommandGraph() &&
215  "Should not be called in on graph recording.");
216 
217  auto LastEvent = QueueImpl->getLastEvent();
218  if (QueueImpl->MDiscardEvents) {
219  std::cout << "Discard event enabled" << std::endl;
220  return LastEvent;
221  }
222 
223  auto LastEventImpl = detail::getSyclObjImpl(LastEvent);
224  // If last event is default constructed event then we want to associate it
225  // with the queue and record submission time if profiling is enabled. Such
226  // event corresponds to NOP and its submit time is same as start time and
227  // end time.
228  if (!LastEventImpl->isContextInitialized()) {
229  LastEventImpl->associateWithQueue(QueueImpl);
230  LastEventImpl->setSubmissionTime();
231  }
232  return detail::createSyclObjFromImpl<event>(LastEventImpl);
233 }
234 
243  if (is_in_order() && !impl->getCommandGraph())
245 
246  return submit([=](handler &CGH) { CGH.ext_oneapi_barrier(); }, CodeLoc);
247 }
248 
258 event queue::ext_oneapi_submit_barrier(const std::vector<event> &WaitList,
259  const detail::code_location &CodeLoc) {
260  bool AllEventsEmptyOrNop = std::all_of(
261  begin(WaitList), end(WaitList), [&](const event &Event) -> bool {
262  auto EventImpl = detail::getSyclObjImpl(Event);
263  return !EventImpl->isContextInitialized() || EventImpl->isNOP();
264  });
265  if (is_in_order() && !impl->getCommandGraph() && AllEventsEmptyOrNop)
267 
268  return submit([=](handler &CGH) { CGH.ext_oneapi_barrier(WaitList); },
269  CodeLoc);
270 }
271 
272 template <typename Param>
275  return impl->get_info<Param>();
276 }
277 
278 #define __SYCL_PARAM_TRAITS_SPEC(DescType, Desc, ReturnT, Picode) \
279  template __SYCL_EXPORT ReturnT queue::get_info<info::queue::Desc>() const;
280 
281 #include <sycl/info/queue_traits.def>
282 
283 #undef __SYCL_PARAM_TRAITS_SPEC
284 
285 template <typename Param>
288  return impl->get_backend_info<Param>();
289 }
290 
291 #define __SYCL_PARAM_TRAITS_SPEC(DescType, Desc, ReturnT, Picode) \
292  template __SYCL_EXPORT ReturnT \
293  queue::get_backend_info<info::DescType::Desc>() const;
294 
295 #include <sycl/info/sycl_backend_traits.def>
296 
297 #undef __SYCL_PARAM_TRAITS_SPEC
298 
299 template <typename PropertyT> bool queue::has_property() const noexcept {
300  return impl->has_property<PropertyT>();
301 }
302 
303 template <typename PropertyT> PropertyT queue::get_property() const {
304  return impl->get_property<PropertyT>();
305 }
306 
307 #define __SYCL_MANUALLY_DEFINED_PROP(NS_QUALIFIER, PROP_NAME) \
308  template __SYCL_EXPORT bool queue::has_property<NS_QUALIFIER::PROP_NAME>() \
309  const noexcept; \
310  template __SYCL_EXPORT NS_QUALIFIER::PROP_NAME \
311  queue::get_property<NS_QUALIFIER::PROP_NAME>() const;
312 
313 #define __SYCL_DATA_LESS_PROP(NS_QUALIFIER, PROP_NAME, ENUM_VAL) \
314  __SYCL_MANUALLY_DEFINED_PROP(NS_QUALIFIER, PROP_NAME)
315 
316 #include <sycl/properties/queue_properties.def>
317 
318 bool queue::is_in_order() const {
319  return impl->has_property<property::queue::in_order>();
320 }
321 
323 
324 bool queue::ext_oneapi_empty() const { return impl->ext_oneapi_empty(); }
325 
326 pi_native_handle queue::getNative(int32_t &NativeHandleDesc) const {
327  return impl->getNative(NativeHandleDesc);
328 }
329 
330 event queue::memcpyToDeviceGlobal(void *DeviceGlobalPtr, const void *Src,
331  bool IsDeviceImageScope, size_t NumBytes,
332  size_t Offset,
333  const std::vector<event> &DepEvents) {
334  return impl->memcpyToDeviceGlobal(impl, DeviceGlobalPtr, Src,
335  IsDeviceImageScope, NumBytes, Offset,
336  DepEvents);
337 }
338 
339 event queue::memcpyFromDeviceGlobal(void *Dest, const void *DeviceGlobalPtr,
340  bool IsDeviceImageScope, size_t NumBytes,
341  size_t Offset,
342  const std::vector<event> &DepEvents) {
343  return impl->memcpyFromDeviceGlobal(impl, Dest, DeviceGlobalPtr,
344  IsDeviceImageScope, NumBytes, Offset,
345  DepEvents);
346 }
347 
348 bool queue::device_has(aspect Aspect) const {
349  // avoid creating sycl object from impl
350  return impl->getDeviceImplPtr()->has(Aspect);
351 }
352 
354  return impl->has_property<
356 }
357 
359  if (!is_in_order())
360  throw sycl::exception(
362  "ext_oneapi_get_last_event() can only be called on in-order queues.");
363  if (impl->MDiscardEvents)
364  throw sycl::exception(
366  "ext_oneapi_get_last_event() cannot be called on queues with the "
367  "ext::oneapi::property::queue::discard_events property.");
368  return impl->getLastEvent();
369 }
370 
371 void queue::ext_oneapi_set_external_event(const event &external_event) {
372  if (!is_in_order())
374  "ext_oneapi_set_external_event() can only be called "
375  "on in-order queues.");
376  if (impl->MDiscardEvents)
377  throw sycl::exception(
379  "ext_oneapi_set_external_event() cannot be called on queues with the "
380  "ext::oneapi::property::queue::discard_events property.");
381  return impl->setExternalEvent(external_event);
382 }
383 
384 } // namespace _V1
385 } // namespace sycl
386 
388  // Compared to using the impl pointer, the unique ID helps avoid hash
389  // collisions with previously destroyed queues.
390  return std::hash<unsigned long long>()(
391  sycl::detail::getSyclObjImpl(Q)->getQueueID());
392 }
The context class represents a SYCL context on which kernel functions may be executed.
Definition: context.hpp:51
Data type that manages the code_location information in TLS.
Definition: common.hpp:129
The SYCL device class encapsulates a single SYCL device on which kernels may be executed.
Definition: device.hpp:64
An event object can be used to synchronize memory transfers, enqueues of kernels and signaling barrie...
Definition: event.hpp:44
Command group handler class.
Definition: handler.hpp:458
void ext_oneapi_barrier()
Prevents any commands submitted afterward to this queue from executing until all commands previously ...
Definition: handler.hpp:2883
Objects of the property_list class are containers for the SYCL properties.
Encapsulates a single SYCL queue which schedules kernels on a SYCL device.
Definition: queue.hpp:111
bool ext_oneapi_empty() const
Allows to check status of the queue (completed vs noncompleted).
Definition: queue.cpp:324
const property_list & PropList
Definition: queue.hpp:195
event memcpy(void *Dest, const void *Src, size_t Count, const detail::code_location &CodeLoc=detail::code_location::current())
Copies data from one memory region to another, each is either a host pointer or a pointer within USM ...
Definition: queue.cpp:125
queue(const property_list &PropList={})
Constructs a SYCL queue instance using the device returned by an instance of default_selector.
Definition: queue.hpp:117
bool is_in_order() const
Returns whether the queue is in order or OoO.
Definition: queue.cpp:318
event memset(void *Ptr, int Value, size_t Count, const detail::code_location &CodeLoc=detail::code_location::current())
Fills the memory pointed by a USM pointer with the value specified.
Definition: queue.cpp:106
pi_native_handle getNative(int32_t &NativeHandleDesc) const
Definition: queue.cpp:326
const device_selector const async_handler & AsyncHandler
Definition: queue.hpp:249
device get_device() const
Definition: queue.cpp:76
backend get_backend() const noexcept
Returns the backend associated with this queue.
Definition: queue.cpp:322
void ext_oneapi_set_external_event(const event &external_event)
Definition: queue.cpp:371
bool ext_codeplay_supports_fusion() const
Returns true if the queue was created with the ext::codeplay::experimental::property::queue::enable_f...
Definition: queue.cpp:353
void wait_and_throw_proxy(const detail::code_location &CodeLoc)
Proxy method for wait_and_throw to forward the code location information to the implementation.
Definition: queue.cpp:204
event ext_oneapi_get_last_event() const
Definition: queue.cpp:358
event ext_oneapi_submit_barrier(const detail::code_location &CodeLoc=detail::code_location::current())
Prevents any commands submitted afterward to this queue from executing until all commands previously ...
Definition: queue.cpp:242
ext::oneapi::experimental::queue_state ext_oneapi_get_state() const
Definition: queue.cpp:78
context get_context() const
Definition: queue.cpp:74
bool has_property() const noexcept
Definition: queue.cpp:299
detail::is_queue_info_desc< Param >::return_type get_info() const
Queries SYCL queue for information.
Definition: queue.cpp:274
event mem_advise(const void *Ptr, size_t Length, pi_mem_advice Advice, const detail::code_location &CodeLoc=detail::code_location::current())
Provides additional information to the underlying runtime about how different allocations are used.
Definition: queue.cpp:144
detail::is_backend_info_desc< Param >::return_type get_backend_info() const
Queries SYCL queue for SYCL backend-specific information.
Definition: queue.cpp:287
const device_selector & DeviceSelector
Definition: queue.hpp:235
ext::oneapi::experimental::command_graph< ext::oneapi::experimental::graph_state::modifiable > ext_oneapi_get_graph() const
Definition: queue.cpp:86
std::enable_if_t< std::is_invocable_r_v< void, T, handler & >, event > submit(T CGF, const detail::code_location &CodeLoc=detail::code_location::current())
Submits a command group function object to the queue, in order to be scheduled for execution on the d...
Definition: queue.hpp:346
PropertyT get_property() const
Definition: queue.cpp:303
void wait_proxy(const detail::code_location &CodeLoc)
Proxy method for wait to forward the code location information to the implementation.
Definition: queue.cpp:200
void throw_asynchronous()
Checks if any asynchronous errors have been produced by the queue and if so reports them to the async...
Definition: queue.cpp:104
__SYCL_EXTERN_STREAM_ATTRS ostream cout
Linked to standard output.
constexpr tuple_element< I, tuple< Types... > >::type & get(sycl::detail::tuple< Types... > &Arg) noexcept
Definition: tuple.hpp:198
backend getImplBackend(const T &Impl)
decltype(Obj::impl) getSyclObjImpl(const Obj &SyclObject)
Definition: impl_utils.hpp:30
T createSyclObjFromImpl(decltype(T::impl) ImplObj)
Definition: impl_utils.hpp:48
std::shared_ptr< sycl::detail::queue_impl > QueueImplPtr
Definition: event_impl.hpp:34
@ modifiable
In modifiable state, commands can be added to graph.
static event getBarrierEventForInorderQueueHelper(const detail::QueueImplPtr QueueImpl)
Definition: queue.cpp:209
std::function< void(sycl::exception_list)> async_handler
std::error_code make_error_code(sycl::errc E) noexcept
Constructs an error code using e and sycl_category()
Definition: exception.cpp:87
Definition: access.hpp:18
uintptr_t pi_native_handle
Definition: pi.h:217
_pi_mem_advice
Definition: pi.h:599
_pi_mem_advice pi_mem_advice
Definition: pi.h:834
bool all_of(const simd_mask< _Tp, _Abi > &) noexcept
_Abi const simd< _Tp, _Abi > & noexcept
Definition: simd.hpp:1324
size_t operator()(const sycl::queue &Q) const
Definition: queue.cpp:387