DPC++ Runtime
Runtime libraries for oneAPI DPC++
event_impl.cpp
Go to the documentation of this file.
1 //==---------------- event_impl.cpp - SYCL event ---------------------------==//
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 
9 #include <detail/event_impl.hpp>
10 #include <detail/event_info.hpp>
11 #include <detail/plugin.hpp>
12 #include <detail/queue_impl.hpp>
14 #include <sycl/context.hpp>
15 #include <sycl/device_selector.hpp>
16 
17 #include "detail/config.hpp"
18 
19 #include <chrono>
20 
21 #ifdef XPTI_ENABLE_INSTRUMENTATION
22 #include "xpti/xpti_trace_framework.hpp"
23 #include <atomic>
24 #include <detail/xpti_registry.hpp>
25 #include <sstream>
26 #endif
27 
28 namespace sycl {
29 inline namespace _V1 {
30 namespace detail {
31 #ifdef XPTI_ENABLE_INSTRUMENTATION
32 extern xpti::trace_event_data_t *GSYCLGraphEvent;
33 #endif
34 
35 // If we do not yet have a context, use the default one.
38  return;
39 
40  const device SyclDevice;
41  this->setContextImpl(
43 }
44 
46  try {
47  if (MEvent)
49  } catch (std::exception &e) {
50  __SYCL_REPORT_EXCEPTION_TO_STREAM("exception in ~event_impl", e);
51  }
52 }
53 
54 void event_impl::waitInternal(bool *Success) {
55  if (!MIsHostEvent && MEvent) {
56  // Wait for the native event
58  getPlugin()->call_nocheck<PiApiKind::piEventsWait>(1, &MEvent);
59  // TODO drop the PI_ERROR_UKNOWN from here once the UR counterpart to
60  // PI_ERROR_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST is added:
61  // https://github.com/oneapi-src/unified-runtime/issues/1459
62  if (Success != nullptr &&
63  (Err == PI_ERROR_UNKNOWN ||
64  Err == PI_ERROR_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST))
65  *Success = false;
66  else {
67  getPlugin()->checkPiResult(Err);
68  if (Success != nullptr)
69  *Success = true;
70  }
71  } else if (MState == HES_Discarded) {
72  // Waiting for the discarded event is invalid
73  throw sycl::exception(
75  "waitInternal method cannot be used for a discarded event.");
76  } else if (MState != HES_Complete) {
77  // Wait for the host event
78  std::unique_lock<std::mutex> lock(MMutex);
79  cv.wait(lock, [this] { return MState == HES_Complete; });
80  }
81 
82  // Wait for connected events(e.g. streams prints)
83  for (const EventImplPtr &Event : MPostCompleteEvents)
84  Event->wait(Event);
85 }
86 
88  if (MIsHostEvent || !MEvent) {
89  {
90  std::unique_lock<std::mutex> lock(MMutex);
91 #ifndef NDEBUG
92  int Expected = HES_NotComplete;
93  int Desired = HES_Complete;
94 
95  bool Succeeded = MState.compare_exchange_strong(Expected, Desired);
96 
97  assert(Succeeded && "Unexpected state of event");
98 #else
99  MState.store(static_cast<int>(HES_Complete));
100 #endif
101  }
102  cv.notify_all();
103  return;
104  }
105 
106  assert(false && "setComplete is not supported for non-host event");
107 }
108 
109 static uint64_t inline getTimestamp() {
110  auto Timestamp = std::chrono::high_resolution_clock::now().time_since_epoch();
111  return std::chrono::duration_cast<std::chrono::nanoseconds>(Timestamp)
112  .count();
113 }
114 
116  return MEvent;
117 }
119 
122  return MContext;
123 }
124 
127  return MContext->getPlugin();
128 }
129 
131 
133  MIsHostEvent = Context == nullptr;
134  MContext = Context;
135 }
136 
138  const context &SyclContext)
139  : MEvent(Event), MContext(detail::getSyclObjImpl(SyclContext)),
140  MIsFlushed(true), MState(HES_Complete) {
141 
142  sycl::detail::pi::PiContext TempContext;
145  &TempContext, nullptr);
146  if (MContext->getHandleRef() != TempContext) {
147  throw sycl::exception(sycl::make_error_code(sycl::errc::invalid),
148  "The syclContext must match the OpenCL context "
149  "associated with the clEvent. " +
150  codeToString(PI_ERROR_INVALID_CONTEXT));
151  }
152 }
153 
155  : MQueue{Queue}, MIsProfilingEnabled{!Queue || Queue->MIsProfilingEnabled},
156  MFallbackProfiling{MIsProfilingEnabled && Queue &&
157  Queue->isProfilingFallback()} {
158  if (Queue)
159  this->setContextImpl(Queue->getContextImplPtr());
160  else {
161  MState.store(HES_NotComplete);
163  if (!MHostProfilingInfo)
164  throw sycl::exception(sycl::make_error_code(sycl::errc::runtime),
165  "Out of host memory " +
166  codeToString(PI_ERROR_OUT_OF_HOST_MEMORY));
167  return;
168  }
169  MState.store(HES_Complete);
170 }
171 
172 void *event_impl::instrumentationProlog(std::string &Name, int32_t StreamID,
173  uint64_t &IId) const {
174  void *TraceEvent = nullptr;
175 #ifdef XPTI_ENABLE_INSTRUMENTATION
176  constexpr uint16_t NotificationTraceType = xpti::trace_wait_begin;
177  if (!xptiCheckTraceEnabled(StreamID, NotificationTraceType))
178  return TraceEvent;
179  // Use a thread-safe counter to get a unique instance ID for the wait() on the
180  // event
181  static std::atomic<uint64_t> InstanceID = {1};
182  xpti::trace_event_data_t *WaitEvent = nullptr;
183 
184  // Create a string with the event address so it
185  // can be associated with other debug data
186  xpti::utils::StringHelper SH;
187  Name = SH.nameWithAddress<sycl::detail::pi::PiEvent>("event.wait", MEvent);
188 
189  // We can emit the wait associated with the graph if the
190  // event does not have a command object or associated with
191  // the command object, if it exists
192  if (MCommand) {
193  Command *Cmd = (Command *)MCommand;
194  WaitEvent = Cmd->MTraceEvent ? static_cast<xpti_td *>(Cmd->MTraceEvent)
195  : GSYCLGraphEvent;
196  } else
197  WaitEvent = GSYCLGraphEvent;
198 
199  // Record the current instance ID for use by Epilog
200  IId = InstanceID++;
201  xptiNotifySubscribers(StreamID, NotificationTraceType, nullptr, WaitEvent,
202  IId, static_cast<const void *>(Name.c_str()));
203  TraceEvent = (void *)WaitEvent;
204 #endif
205  return TraceEvent;
206 }
207 
208 void event_impl::instrumentationEpilog(void *TelemetryEvent,
209  const std::string &Name,
210  int32_t StreamID, uint64_t IId) const {
211 #ifdef XPTI_ENABLE_INSTRUMENTATION
212  constexpr uint16_t NotificationTraceType = xpti::trace_wait_end;
213  if (!(xptiCheckTraceEnabled(StreamID, NotificationTraceType) &&
214  TelemetryEvent))
215  return;
216  // Close the wait() scope
217  xpti::trace_event_data_t *TraceEvent =
218  (xpti::trace_event_data_t *)TelemetryEvent;
219  xptiNotifySubscribers(StreamID, NotificationTraceType, nullptr, TraceEvent,
220  IId, static_cast<const void *>(Name.c_str()));
221 #endif
222 }
223 
224 void event_impl::wait(std::shared_ptr<sycl::detail::event_impl> Self,
225  bool *Success) {
226  if (MState == HES_Discarded)
228  "wait method cannot be used for a discarded event.");
229 
230  if (!MGraph.expired()) {
232  "wait method cannot be used for an event associated "
233  "with a command graph.");
234  }
235 
236 #ifdef XPTI_ENABLE_INSTRUMENTATION
237  void *TelemetryEvent = nullptr;
238  uint64_t IId = 0;
239  std::string Name;
240  int32_t StreamID = xptiRegisterStream(SYCL_STREAM_NAME);
241  TelemetryEvent = instrumentationProlog(Name, StreamID, IId);
242 #endif
243 
244  if (MEvent)
245  // presence of MEvent means the command has been enqueued, so no need to
246  // go via the slow path event waiting in the scheduler
247  waitInternal(Success);
248  else if (MCommand)
250 
251 #ifdef XPTI_ENABLE_INSTRUMENTATION
252  instrumentationEpilog(TelemetryEvent, Name, StreamID, IId);
253 #endif
254 }
255 
257  std::shared_ptr<sycl::detail::event_impl> Self) {
258  wait(Self);
259 
260  if (QueueImplPtr SubmittedQueue = MSubmittedQueue.lock())
261  SubmittedQueue->throw_asynchronous();
262 }
263 
265  std::weak_ptr<queue_impl> EmptyPtr;
266 
267  if (!MIsHostEvent && !EmptyPtr.owner_before(MQueue) &&
268  !MQueue.owner_before(EmptyPtr)) {
269  throw sycl::exception(make_error_code(sycl::errc::invalid),
270  "Profiling information is unavailable as the event "
271  "has no associated queue.");
272  }
274  throw sycl::exception(
275  make_error_code(sycl::errc::invalid),
276  "Profiling information is unavailable as the queue associated with "
277  "the event does not have the 'enable_profiling' property.");
278  }
279 }
280 
281 template <>
282 uint64_t
283 event_impl::get_profiling_info<info::event_profiling::command_submit>() {
284  checkProfilingPreconditions();
285  if (isProfilingTagEvent()) {
286  // For profiling tag events we rely on the submission time reported as
287  // the start time has undefined behavior.
288  return get_event_profiling_info<info::event_profiling::command_submit>(
289  this->getHandleRef(), this->getPlugin());
290  }
291 
292  // The delay between the submission and the actual start of a CommandBuffer
293  // can be short. Consequently, the submission time, which is based on
294  // an estimated clock and not on the real device clock, may be ahead of the
295  // start time, which is based on the actual device clock.
296  // MSubmitTime is set in a critical performance path.
297  // Force reading the device clock when setting MSubmitTime may deteriorate
298  // the performance.
299  // Since submit time is an estimated time, we implement this little hack
300  // that allows all profiled time to be meaningful.
301  // (Note that the observed time deviation between the estimated clock and
302  // the real device clock is typically less than 0.5ms. The approximation we
303  // made by forcing the re-sync of submit time to start time is less than
304  // 0.5ms. These timing values were obtained empirically using an integrated
305  // Intel GPU).
306  if (MEventFromSubmittedExecCommandBuffer && !MIsHostEvent && MEvent) {
307  uint64_t StartTime =
308  get_event_profiling_info<info::event_profiling::command_start>(
309  this->getHandleRef(), this->getPlugin());
310  if (StartTime < MSubmitTime)
311  MSubmitTime = StartTime;
312  }
313  return MSubmitTime;
314 }
315 
316 template <>
317 uint64_t
318 event_impl::get_profiling_info<info::event_profiling::command_start>() {
319  checkProfilingPreconditions();
320  if (!MIsHostEvent) {
321  if (MEvent) {
322  auto StartTime =
323  get_event_profiling_info<info::event_profiling::command_start>(
324  this->getHandleRef(), this->getPlugin());
325  if (!MFallbackProfiling) {
326  return StartTime;
327  } else {
328  auto DeviceBaseTime =
329  get_event_profiling_info<info::event_profiling::command_submit>(
330  this->getHandleRef(), this->getPlugin());
331  return MHostBaseTime - DeviceBaseTime + StartTime;
332  }
333  }
334  return 0;
335  }
336  if (!MHostProfilingInfo)
337  throw sycl::exception(
338  sycl::make_error_code(sycl::errc::invalid),
339  "Profiling info is not available. " +
340  codeToString(PI_ERROR_PROFILING_INFO_NOT_AVAILABLE));
341  return MHostProfilingInfo->getStartTime();
342 }
343 
344 template <>
345 uint64_t event_impl::get_profiling_info<info::event_profiling::command_end>() {
346  checkProfilingPreconditions();
347  if (!MIsHostEvent) {
348  if (MEvent) {
349  auto EndTime =
350  get_event_profiling_info<info::event_profiling::command_end>(
351  this->getHandleRef(), this->getPlugin());
352  if (!MFallbackProfiling) {
353  return EndTime;
354  } else {
355  auto DeviceBaseTime =
356  get_event_profiling_info<info::event_profiling::command_submit>(
357  this->getHandleRef(), this->getPlugin());
358  return MHostBaseTime - DeviceBaseTime + EndTime;
359  }
360  }
361  return 0;
362  }
363  if (!MHostProfilingInfo)
364  throw sycl::exception(
365  sycl::make_error_code(sycl::errc::invalid),
366  "Profiling info is not available. " +
367  codeToString(PI_ERROR_PROFILING_INFO_NOT_AVAILABLE));
368  return MHostProfilingInfo->getEndTime();
369 }
370 
371 template <> uint32_t event_impl::get_info<info::event::reference_count>() {
372  if (!MIsHostEvent && MEvent) {
373  return get_event_info<info::event::reference_count>(this->getHandleRef(),
374  this->getPlugin());
375  }
376  return 0;
377 }
378 
379 template <>
381 event_impl::get_info<info::event::command_execution_status>() {
382  if (MState == HES_Discarded)
384 
385  if (!MIsHostEvent) {
386  // Command is enqueued and PiEvent is ready
387  if (MEvent)
388  return get_event_info<info::event::command_execution_status>(
389  this->getHandleRef(), this->getPlugin());
390  // Command is blocked and not enqueued, PiEvent is not assigned yet
391  else if (MCommand)
392  return sycl::info::event_command_status::submitted;
393  }
394 
395  return MIsHostEvent && MState.load() != HES_Complete
396  ? sycl::info::event_command_status::submitted
398 }
399 
400 template <>
401 typename info::platform::version::return_type
402 event_impl::get_backend_info<info::platform::version>() const {
403  if (!MContext) {
404  return "Context not initialized, no backend info available";
405  }
406  if (MContext->getBackend() != backend::opencl) {
408  "the info::platform::version info descriptor can "
409  "only be queried with an OpenCL backend");
410  }
411  if (QueueImplPtr Queue = MQueue.lock()) {
412  return Queue->getDeviceImplPtr()
413  ->get_platform()
414  .get_info<info::platform::version>();
415  }
416  // If the queue has been released, no platform will be associated
417  // so return empty string.
418  return "";
419 }
420 
421 template <>
422 typename info::device::version::return_type
423 event_impl::get_backend_info<info::device::version>() const {
424  if (!MContext) {
425  return "Context not initialized, no backend info available";
426  }
427  if (MContext->getBackend() != backend::opencl) {
429  "the info::device::version info descriptor can only "
430  "be queried with an OpenCL backend");
431  }
432  if (QueueImplPtr Queue = MQueue.lock()) {
433  return Queue->getDeviceImplPtr()->get_info<info::device::version>();
434  }
435  return ""; // If the queue has been released, no device will be associated so
436  // return empty string
437 }
438 
439 template <>
440 typename info::device::backend_version::return_type
441 event_impl::get_backend_info<info::device::backend_version>() const {
442  if (!MContext) {
443  return "Context not initialized, no backend info available";
444  }
445  if (MContext->getBackend() != backend::ext_oneapi_level_zero) {
447  "the info::device::backend_version info descriptor "
448  "can only be queried with a Level Zero backend");
449  }
450  return "";
451  // Currently The Level Zero backend does not define the value of this
452  // information descriptor and implementations are encouraged to return the
453  // empty string as per specification.
454 }
455 
456 void HostProfilingInfo::start() { StartTime = getTimestamp(); }
457 
458 void HostProfilingInfo::end() { EndTime = getTimestamp(); }
459 
461  if (isHost())
462  return {};
464 
465  auto Plugin = getPlugin();
466  if (MIsDefaultConstructed && !MEvent) {
467  auto TempContext = MContext.get()->getHandleRef();
468  Plugin->call<PiApiKind::piEventCreate>(TempContext, &MEvent);
469  }
470  if (MContext->getBackend() == backend::opencl)
471  Plugin->call<PiApiKind::piEventRetain>(getHandleRef());
472  pi_native_handle Handle;
473  Plugin->call<PiApiKind::piextEventGetNativeHandle>(getHandleRef(), &Handle);
474  return Handle;
475 }
476 
477 std::vector<EventImplPtr> event_impl::getWaitList() {
478  if (MState == HES_Discarded)
479  throw sycl::exception(
481  "get_wait_list() cannot be used for a discarded event.");
482 
483  std::lock_guard<std::mutex> Lock(MMutex);
484 
485  std::vector<EventImplPtr> Result;
486  Result.reserve(MPreparedDepsEvents.size() + MPreparedHostDepsEvents.size());
487  Result.insert(Result.end(), MPreparedDepsEvents.begin(),
488  MPreparedDepsEvents.end());
489  Result.insert(Result.end(), MPreparedHostDepsEvents.begin(),
491 
492  return Result;
493 }
494 
495 void event_impl::flushIfNeeded(const QueueImplPtr &UserQueue) {
496  // Some events might not have a native handle underneath even at this point,
497  // e.g. those produced by memset with 0 size (no PI call is made).
498  if (MIsFlushed || !MEvent)
499  return;
500 
501  QueueImplPtr Queue = MQueue.lock();
502  // If the queue has been released, all of the commands have already been
503  // implicitly flushed by piQueueRelease.
504  if (!Queue) {
505  MIsFlushed = true;
506  return;
507  }
508  if (Queue == UserQueue)
509  return;
510 
511  // Check if the task for this event has already been submitted.
515  nullptr);
516  if (Status == PI_EVENT_QUEUED) {
517  getPlugin()->call<PiApiKind::piQueueFlush>(Queue->getHandleRef());
518  }
519  MIsFlushed = true;
520 }
521 
523  std::lock_guard<std::mutex> Lock(MMutex);
524  MPreparedDepsEvents.clear();
525  MPreparedHostDepsEvents.clear();
526 }
527 
529  std::lock_guard<std::mutex> Lock(MMutex);
530  for (auto &Event : MPreparedDepsEvents) {
531  Event->cleanupDependencyEvents();
532  }
533  for (auto &Event : MPreparedHostDepsEvents) {
534  Event->cleanupDependencyEvents();
535  }
536 }
537 
540  return;
541  if (!MFallbackProfiling) {
542  if (QueueImplPtr Queue = MQueue.lock()) {
543  try {
544  MSubmitTime = Queue->getDeviceImplPtr()->getCurrentDeviceTime();
545  } catch (sycl::exception &e) {
546  if (e.code() == sycl::errc::feature_not_supported)
547  throw sycl::exception(
549  std::string("Unable to get command group submission time: ") +
550  e.what());
551  std::rethrow_exception(std::current_exception());
552  }
553  } else {
554  // Returning host time
555  using namespace std::chrono;
556  MSubmitTime =
557  duration_cast<nanoseconds>(steady_clock::now().time_since_epoch())
558  .count();
559  }
560  } else {
561  // Capture the host timestamp for a return value of function call
562  // <info::event_profiling::command_submit>. See MFallbackProfiling
564  }
565 }
566 
569  return;
570  // Capture a host timestamp to use normalize profiling time in
571  // <command_start> and <command_end>. See MFallbackProfiling
573 }
574 
576 
578  return get_info<info::event::command_execution_status>() ==
580 }
581 
582 void event_impl::setCommand(void *Cmd) {
583  MCommand = Cmd;
584  auto TypedCommand = static_cast<Command *>(Cmd);
585  if (TypedCommand)
586  MIsHostEvent = TypedCommand->getWorkerContext() == nullptr;
587 }
588 
589 } // namespace detail
590 } // namespace _V1
591 } // namespace sycl
The context class represents a SYCL context on which kernel functions may be executed.
Definition: context.hpp:50
The Command class represents some action that needs to be performed on one or more memory objects.
Definition: commands.hpp:106
void * MTraceEvent
The event for node_create and task_begin.
Definition: commands.hpp:346
Profiling info for the host execution.
void end()
Measures event's end time.
Definition: event_impl.cpp:458
void start()
Measures event's start time.
Definition: event_impl.cpp:456
void waitForEvent(const EventImplPtr &Event, bool *Success=nullptr)
Waits for the event.
Definition: scheduler.cpp:252
static Scheduler & getInstance()
Definition: scheduler.cpp:244
void checkProfilingPreconditions() const
Definition: event_impl.cpp:264
std::vector< EventImplPtr > getWaitList()
Returns vector of event_impl that this event_impl depends on.
Definition: event_impl.cpp:477
void * instrumentationProlog(std::string &Name, int32_t StreamID, uint64_t &instance_id) const
Definition: event_impl.cpp:172
std::vector< EventImplPtr > MPostCompleteEvents
Definition: event_impl.hpp:361
void cleanDepEventsThroughOneLevel()
Cleans dependencies of this event's dependencies.
Definition: event_impl.cpp:528
void waitInternal(bool *Success=nullptr)
Waits for the event with respect to device type.
Definition: event_impl.cpp:54
void setComplete()
Marks this event as completed.
Definition: event_impl.cpp:87
pi_native_handle getNative()
Gets the native handle of the SYCL event.
Definition: event_impl.cpp:460
std::unique_ptr< HostProfilingInfo > MHostProfilingInfo
Definition: event_impl.hpp:348
void setContextImpl(const ContextImplPtr &Context)
Associate event with the context.
Definition: event_impl.cpp:132
void setHostEnqueueTime()
Calling this function to capture the host timestamp to use profiling base time.
Definition: event_impl.cpp:567
std::weak_ptr< ext::oneapi::experimental::detail::graph_impl > MGraph
Store the command graph associated with this event, if any.
Definition: event_impl.hpp:377
const ContextImplPtr & getContextImpl()
Returns context that is associated with this event.
Definition: event_impl.cpp:120
void flushIfNeeded(const QueueImplPtr &UserQueue)
Performs a flush on the queue associated with this event if the user queue is different and the task ...
Definition: event_impl.cpp:495
std::weak_ptr< queue_impl > MSubmittedQueue
Definition: event_impl.hpp:355
std::atomic< int > MState
Definition: event_impl.hpp:370
sycl::detail::pi::PiEvent MEvent
Definition: event_impl.hpp:343
void instrumentationEpilog(void *TelementryEvent, const std::string &Name, int32_t StreamID, uint64_t IId) const
Definition: event_impl.cpp:208
event_impl(std::optional< HostEventState > State=HES_Complete)
Constructs a ready SYCL event.
Definition: event_impl.hpp:51
bool isCompleted()
Checks if this event is complete.
Definition: event_impl.cpp:577
std::vector< EventImplPtr > MPreparedHostDepsEvents
Definition: event_impl.hpp:359
void wait(std::shared_ptr< sycl::detail::event_impl > Self, bool *Success=nullptr)
Waits for the event.
Definition: event_impl.cpp:224
void setStateIncomplete()
Clear the event state.
Definition: event_impl.cpp:130
std::condition_variable cv
Definition: event_impl.hpp:373
std::vector< EventImplPtr > MPreparedDepsEvents
Dependency events prepared for waiting by backend.
Definition: event_impl.hpp:358
void setSubmissionTime()
Calling this function queries the current device timestamp and sets it as submission time for the com...
Definition: event_impl.cpp:538
void cleanupDependencyEvents()
Cleans dependencies of this event_impl.
Definition: event_impl.cpp:522
void wait_and_throw(std::shared_ptr< sycl::detail::event_impl > Self)
Waits for the event.
Definition: event_impl.cpp:256
void setCommand(void *Command)
Associates this event with the command.
Definition: event_impl.cpp:582
const PluginPtr & getPlugin()
Definition: event_impl.cpp:125
sycl::detail::pi::PiEvent & getHandleRef()
Returns raw interoperability event handle.
Definition: event_impl.cpp:118
std::atomic< bool > MIsFlushed
Indicates that the task associated with this event has been submitted by the queue to the device.
Definition: event_impl.hpp:365
std::weak_ptr< queue_impl > MQueue
Definition: event_impl.hpp:350
static ContextImplPtr getDefaultOrNew(const DeviceImplPtr &Device)
Definition: queue_impl.hpp:75
The SYCL device class encapsulates a single SYCL device on which kernels may be executed.
Definition: device.hpp:64
const char * what() const noexcept final
Definition: exception.cpp:48
const std::error_code & code() const noexcept
Definition: exception.cpp:42
#define __SYCL_REPORT_EXCEPTION_TO_STREAM(str, e)
Definition: common.hpp:365
::pi_context PiContext
Definition: pi.hpp:109
decltype(Obj::impl) const & getSyclObjImpl(const Obj &SyclObject)
Definition: impl_utils.hpp:31
constexpr const char * SYCL_STREAM_NAME
std::string codeToString(pi_int32 code)
Definition: exception.hpp:58
static uint64_t getTimestamp()
Definition: event_impl.cpp:109
std::shared_ptr< sycl::detail::context_impl > ContextImplPtr
Definition: event_impl.hpp:32
static const PluginPtr & getPlugin(backend Backend)
Definition: backend.cpp:32
std::shared_ptr< event_impl > EventImplPtr
Definition: handler.hpp:184
std::shared_ptr< plugin > PluginPtr
Definition: pi.hpp:47
std::shared_ptr< sycl::detail::queue_impl > QueueImplPtr
Definition: event_impl.hpp:34
std::error_code make_error_code(sycl::errc E) noexcept
Constructs an error code using e and sycl_category()
Definition: exception.cpp:64
Definition: access.hpp:18
int32_t pi_int32
Definition: pi.h:253
uintptr_t pi_native_handle
Definition: pi.h:258
_pi_result
Definition: pi.h:265
pi_result piextEventGetNativeHandle(pi_event event, pi_native_handle *nativeHandle)
Gets the native handle of a PI event object.
Definition: pi_cuda.cpp:637
pi_result piEventGetInfo(pi_event event, pi_event_info param_name, size_t param_value_size, void *param_value, size_t *param_value_size_ret)
Definition: pi_cuda.cpp:599
@ PI_EVENT_INFO_COMMAND_EXECUTION_STATUS
Definition: pi.h:616
@ PI_EVENT_INFO_CONTEXT
Definition: pi.h:614
pi_result piEventsWait(pi_uint32 num_events, const pi_event *event_list)
Definition: pi_cuda.cpp:614
pi_result piQueueFlush(pi_queue command_queue)
Definition: pi_cuda.cpp:188
pi_result piEventRelease(pi_event event)
Definition: pi_cuda.cpp:633
_pi_event_status
Definition: pi.h:273
@ PI_EVENT_QUEUED
Definition: pi.h:277
pi_result piEventRetain(pi_event event)
Definition: pi_cuda.cpp:631
decltype(piEventCreate) piEventCreate