@@ -282,19 +282,26 @@ event queue_impl::memcpyFromDeviceGlobal(
282
282
DeviceGlobalPtr, IsDeviceImageScope, Self, NumBytes, Offset, Dest);
283
283
}
284
284
285
- sycl::detail::optional<event> queue_impl::getLastEvent () {
285
+ sycl::detail::optional<event>
286
+ queue_impl::getLastEvent (const std::shared_ptr<queue_impl> &Self) {
286
287
// The external event is required to finish last if set, so it is considered
287
288
// the last event if present.
288
289
if (std::optional<event> ExternalEvent = MInOrderExternalEvent.read ())
289
290
return ExternalEvent;
290
291
291
292
std::lock_guard<std::mutex> Lock{MMutex};
292
- if (MGraph. expired () && !MDefaultGraphDeps. LastEventPtr )
293
+ if (MEmpty )
293
294
return std::nullopt;
294
- if (MDiscardEvents)
295
- return createDiscardedEvent ();
295
+ if (MNoEventMode) {
296
+ assert (MGraph.expired ());
297
+ assert (!MDefaultGraphDeps.LastEventPtr );
298
+
299
+ // We insert a marker to represent an event at end.
300
+ return detail::createSyclObjFromImpl<event>(insertMarkerEvent (Self));
301
+ }
296
302
if (!MGraph.expired () && MExtGraphDeps.LastEventPtr )
297
303
return detail::createSyclObjFromImpl<event>(MExtGraphDeps.LastEventPtr );
304
+ assert (MDefaultGraphDeps.LastEventPtr );
298
305
return detail::createSyclObjFromImpl<event>(MDefaultGraphDeps.LastEventPtr );
299
306
}
300
307
@@ -339,10 +346,27 @@ event queue_impl::submit_impl(const detail::type_erased_cgfo_ty &CGF,
339
346
340
347
HandlerImpl->MEventMode = SubmitInfo.EventMode ();
341
348
342
- auto Event = finalizeHandler (Handler, SubmitInfo.PostProcessorFunc ());
349
+ auto isInNoEventsMode =
350
+ isInOrder () && MNoEventMode.load (std::memory_order_relaxed);
351
+ auto needToStoreEvent = Type == CGType::CodeplayHostTask ||
352
+ Streams.size () > 0 || SubmitInfo.PostProcessorFunc ();
353
+
354
+ if (isInNoEventsMode && !needToStoreEvent) {
355
+ std::unique_lock<std::mutex> Lock (MMutex);
356
+
357
+ // Check the condition again, under the lock to ensure that the
358
+ // there was no concurrent submit that changed the state.
359
+ if (MNoEventMode.load (std::memory_order_relaxed))
360
+ return finalizeHandlerInOrderNoEventsUnlocked (Handler);
361
+ }
343
362
363
+ auto Event = finalizeHandler (Handler, SubmitInfo.PostProcessorFunc ());
344
364
addEvent (Event);
345
365
366
+ // If we taken this path, it's because we need to store the last event.
367
+ if (isInOrder ())
368
+ assert (!MNoEventMode);
369
+
346
370
const auto &EventImpl = detail::getSyclObjImpl (Event);
347
371
for (auto &Stream : Streams) {
348
372
// We don't want stream flushing to be blocking operation that is why submit
@@ -460,21 +484,12 @@ event queue_impl::submitMemOpHelper(const std::shared_ptr<queue_impl> &Self,
460
484
// handler rather than by-passing the scheduler.
461
485
if (MGraph.expired () && Scheduler::areEventsSafeForSchedulerBypass (
462
486
ExpandedDepEvents, MContext)) {
463
- if ((MDiscardEvents || !CallerNeedsEvent) &&
464
- supportsDiscardingPiEvents ()) {
487
+ if (!CallerNeedsEvent && MNoEventMode) {
465
488
NestedCallsTracker tracker;
466
489
MemOpFunc (MemOpArgs..., getUrEvents (ExpandedDepEvents),
467
490
/* PiEvent*/ nullptr , /* EventImplPtr*/ nullptr );
468
491
469
- event DiscardedEvent = createDiscardedEvent ();
470
- if (isInOrder ()) {
471
- // Store the discarded event for proper in-order dependency tracking.
472
- auto &EventToStoreIn = MGraph.expired ()
473
- ? MDefaultGraphDeps.LastEventPtr
474
- : MExtGraphDeps.LastEventPtr ;
475
- EventToStoreIn = detail::getSyclObjImpl (DiscardedEvent);
476
- }
477
- return DiscardedEvent;
492
+ return createDiscardedEvent ();
478
493
}
479
494
480
495
event ResEvent = prepareSYCLEventAssociatedWithQueue (Self);
@@ -500,7 +515,7 @@ event queue_impl::submitMemOpHelper(const std::shared_ptr<queue_impl> &Self,
500
515
}
501
516
}
502
517
503
- if (isInOrder () ) {
518
+ if (!MNoEventMode ) {
504
519
auto &EventToStoreIn = MGraph.expired () ? MDefaultGraphDeps.LastEventPtr
505
520
: MExtGraphDeps.LastEventPtr ;
506
521
EventToStoreIn = EventImpl;
@@ -745,14 +760,11 @@ bool queue_impl::ext_oneapi_empty() const {
745
760
// the status of the last event.
746
761
if (isInOrder () && !MDiscardEvents) {
747
762
std::lock_guard<std::mutex> Lock (MMutex);
748
- // If there is no last event we know that no work has been submitted, so it
749
- // must be trivially empty.
750
- if (!MDefaultGraphDeps.LastEventPtr )
751
- return true ;
752
- // Otherwise, check if the last event is finished.
763
+ assert ((MDefaultGraphDeps.LastEventPtr == nullptr ) == MNoEventMode);
753
764
// Note that we fall back to the backend query if the event was discarded,
754
765
// which may happend despite the queue not being a discard event queue.
755
- if (!MDefaultGraphDeps.LastEventPtr ->isDiscarded ())
766
+ if (MDefaultGraphDeps.LastEventPtr &&
767
+ !MDefaultGraphDeps.LastEventPtr ->isDiscarded ())
756
768
return MDefaultGraphDeps.LastEventPtr
757
769
->get_info <info::event::command_execution_status>() ==
758
770
info::event_command_status::complete;
@@ -765,6 +777,11 @@ bool queue_impl::ext_oneapi_empty() const {
765
777
if (!IsReady)
766
778
return false ;
767
779
780
+ // If got here, it means that LastEventPtr is nullptr (so no possible Host
781
+ // Tasks) and there is nothing executing on the device.
782
+ if (isInOrder ())
783
+ return true ;
784
+
768
785
// We may have events like host tasks which are not submitted to the backend
769
786
// queue so we need to get their status separately.
770
787
std::lock_guard<std::mutex> Lock (MMutex);
0 commit comments