Skip to content

Commit 64546e7

Browse files
[SYCL] Extend scope of scheduler bypass to safe to bypass events (#16735)
1) Aling scheduler bypass conditions for CG and for memory ops. 2) Connect an event returned from scheduler bypass case with dependent events. --------- Co-authored-by: Sergey Semenov <[email protected]>
1 parent 55a0987 commit 64546e7

File tree

6 files changed

+29
-15
lines changed

6 files changed

+29
-15
lines changed

sycl/source/detail/queue_impl.cpp

+12-1
Original file line numberDiff line numberDiff line change
@@ -481,14 +481,25 @@ event queue_impl::submitMemOpHelper(const std::shared_ptr<queue_impl> &Self,
481481
}
482482

483483
event ResEvent = prepareSYCLEventAssociatedWithQueue(Self);
484-
auto EventImpl = detail::getSyclObjImpl(ResEvent);
484+
const auto &EventImpl = detail::getSyclObjImpl(ResEvent);
485485
{
486486
NestedCallsTracker tracker;
487487
ur_event_handle_t UREvent = nullptr;
488488
MemOpFunc(MemOpArgs..., getUrEvents(ExpandedDepEvents), &UREvent,
489489
EventImpl);
490490
EventImpl->setHandle(UREvent);
491491
EventImpl->setEnqueued();
492+
// connect returned event with dependent events
493+
if (!isInOrder()) {
494+
std::vector<EventImplPtr> &ExpandedDepEventImplPtrs =
495+
EventImpl->getPreparedDepsEvents();
496+
ExpandedDepEventImplPtrs.reserve(ExpandedDepEvents.size());
497+
for (const event &DepEvent : ExpandedDepEvents)
498+
ExpandedDepEventImplPtrs.push_back(
499+
detail::getSyclObjImpl(DepEvent));
500+
501+
EventImpl->cleanDepEventsThroughOneLevel();
502+
}
492503
}
493504

494505
if (isInOrder()) {

sycl/source/detail/scheduler/scheduler.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,7 @@ bool CheckEventReadiness(const ContextImplPtr &Context,
670670
}
671671

672672
bool Scheduler::areEventsSafeForSchedulerBypass(
673-
const std::vector<sycl::event> &DepEvents, ContextImplPtr Context) {
673+
const std::vector<sycl::event> &DepEvents, const ContextImplPtr &Context) {
674674

675675
return std::all_of(
676676
DepEvents.begin(), DepEvents.end(), [&Context](const sycl::event &Event) {
@@ -680,7 +680,7 @@ bool Scheduler::areEventsSafeForSchedulerBypass(
680680
}
681681

682682
bool Scheduler::areEventsSafeForSchedulerBypass(
683-
const std::vector<EventImplPtr> &DepEvents, ContextImplPtr Context) {
683+
const std::vector<EventImplPtr> &DepEvents, const ContextImplPtr &Context) {
684684

685685
return std::all_of(DepEvents.begin(), DepEvents.end(),
686686
[&Context](const EventImplPtr &SyclEventImplPtr) {

sycl/source/detail/scheduler/scheduler.hpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -479,10 +479,10 @@ class Scheduler {
479479

480480
static bool
481481
areEventsSafeForSchedulerBypass(const std::vector<sycl::event> &DepEvents,
482-
ContextImplPtr Context);
482+
const ContextImplPtr &Context);
483483
static bool
484484
areEventsSafeForSchedulerBypass(const std::vector<EventImplPtr> &DepEvents,
485-
ContextImplPtr Context);
485+
const ContextImplPtr &Context);
486486

487487
protected:
488488
using RWLockT = std::shared_timed_mutex;

sycl/source/handler.cpp

+7-4
Original file line numberDiff line numberDiff line change
@@ -468,10 +468,8 @@ event handler::finalize() {
468468
if (MQueue && !impl->MGraph && !impl->MSubgraphNode &&
469469
!MQueue->hasCommandGraph() && !impl->CGData.MRequirements.size() &&
470470
!MStreamStorage.size() &&
471-
(!impl->CGData.MEvents.size() ||
472-
(MQueue->isInOrder() &&
473-
detail::Scheduler::areEventsSafeForSchedulerBypass(
474-
impl->CGData.MEvents, MQueue->getContextImplPtr())))) {
471+
detail::Scheduler::areEventsSafeForSchedulerBypass(
472+
impl->CGData.MEvents, MQueue->getContextImplPtr())) {
475473
// if user does not add a new dependency to the dependency graph, i.e.
476474
// the graph is not changed, then this faster path is used to submit
477475
// kernel bypassing scheduler and avoiding CommandGroup, Command objects
@@ -544,6 +542,11 @@ event handler::finalize() {
544542

545543
EnqueueKernel();
546544
NewEvent->setEnqueued();
545+
// connect returned event with dependent events
546+
if (!MQueue->isInOrder()) {
547+
NewEvent->getPreparedDepsEvents() = impl->CGData.MEvents;
548+
NewEvent->cleanDepEventsThroughOneLevel();
549+
}
547550

548551
MLastEvent = detail::createSyclObjFromImpl<event>(std::move(NewEvent));
549552
}

sycl/test-e2e/XPTI/basic_event_collection_linux.cpp

-6
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,6 @@
3232
// CHECK-DAG: from_source : false
3333
// CHECK-DAG: kernel_name : typeinfo name for main::{lambda(sycl::_V1::handler&)#1}::operator()(sycl::_V1::handler&) const::{lambda()#1}
3434
// CHECK-DAG: sycl_device : {{.*}}
35-
// CHECK: Node create
36-
// CHECK-DAG: queue_id : {{.*}}
37-
// CHECK-DAG: kernel_name : virtual_node[{{.*}}]
38-
// CHECK-NEXT: Edge create
39-
// CHECK-DAG: queue_id : {{.*}}
40-
// CHECK-DAG: event : {{.*}}
4135
// CHECK: Task begin
4236
// CHECK-DAG: queue_id : {{.*}}
4337
// CHECK-DAG: sym_line_no : {{.*}}

sycl/unittests/scheduler/EnqueueWithDependsOnDeps.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ TEST_F(DependsOnTests, ShortcutFunctionWithWaitList) {
323323
&redefinedextUSMEnqueueMemcpy);
324324
sycl::queue Queue = detail::createSyclObjFromImpl<queue>(QueueDevImpl);
325325

326+
// Mock up an incomplete host task
326327
auto HostTaskEvent =
327328
Queue.submit([&](sycl::handler &cgh) { cgh.host_task([=]() {}); });
328329
std::shared_ptr<detail::event_impl> HostTaskEventImpl =
@@ -332,6 +333,7 @@ TEST_F(DependsOnTests, ShortcutFunctionWithWaitList) {
332333
ASSERT_NE(Cmd, nullptr);
333334
Cmd->MIsBlockable = true;
334335
Cmd->MEnqueueStatus = detail::EnqueueResultT::SyclEnqueueBlocked;
336+
HostTaskEventImpl->setStateIncomplete();
335337

336338
auto SingleTaskEvent = Queue.submit([&](sycl::handler &cgh) {
337339
cgh.depends_on(HostTaskEvent);
@@ -341,6 +343,8 @@ TEST_F(DependsOnTests, ShortcutFunctionWithWaitList) {
341343
detail::getSyclObjImpl(SingleTaskEvent);
342344
EXPECT_EQ(SingleTaskEventImpl->getHandle(), nullptr);
343345

346+
// make HostTaskEvent completed, so SingleTaskEvent can be enqueued
347+
HostTaskEventImpl->setComplete();
344348
Cmd->MEnqueueStatus = detail::EnqueueResultT::SyclEnqueueSuccess;
345349
EventsInWaitList.clear();
346350

@@ -375,6 +379,7 @@ TEST_F(DependsOnTests, BarrierWithWaitList) {
375379
ASSERT_NE(Cmd, nullptr);
376380
Cmd->MIsBlockable = true;
377381
Cmd->MEnqueueStatus = detail::EnqueueResultT::SyclEnqueueBlocked;
382+
HostTaskEventImpl->setStateIncomplete();
378383

379384
auto SingleTaskEvent = Queue.submit([&](sycl::handler &cgh) {
380385
cgh.depends_on(HostTaskEvent);
@@ -384,6 +389,7 @@ TEST_F(DependsOnTests, BarrierWithWaitList) {
384389
detail::getSyclObjImpl(SingleTaskEvent);
385390
EXPECT_EQ(SingleTaskEventImpl->getHandle(), nullptr);
386391

392+
HostTaskEventImpl->setComplete();
387393
Cmd->MEnqueueStatus = detail::EnqueueResultT::SyclEnqueueSuccess;
388394
EventsInWaitList.clear();
389395

0 commit comments

Comments
 (0)