Skip to content

Commit 652c903

Browse files
authored
[SYCL] Split read/write lockings (#2292)
Signed-off-by: Sergey Kanaev <[email protected]>
1 parent 8e6344c commit 652c903

21 files changed

+485
-241
lines changed

sycl/source/detail/scheduler/commands.cpp

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ class DispatchHostTask {
235235
// Thus we employ read-lock of graph.
236236
{
237237
Scheduler &Sched = Scheduler::getInstance();
238-
std::shared_lock<std::shared_timed_mutex> Lock(Sched.MGraphLock);
238+
Scheduler::ReadLockT Lock(Sched.MGraphLock);
239239

240240
std::vector<DepDesc> Deps = MThisCmd->MDeps;
241241

@@ -481,7 +481,7 @@ void Command::makeTraceEventEpilog() {
481481
#endif
482482
}
483483

484-
void Command::processDepEvent(EventImplPtr DepEvent, const DepDesc &Dep) {
484+
Command *Command::processDepEvent(EventImplPtr DepEvent, const DepDesc &Dep) {
485485
const QueueImplPtr &WorkerQueue = getWorkerQueue();
486486
const ContextImplPtr &WorkerContext = WorkerQueue->getContextImplPtr();
487487

@@ -493,21 +493,25 @@ void Command::processDepEvent(EventImplPtr DepEvent, const DepDesc &Dep) {
493493
// call to waitInternal() is in waitForPreparedHostEvents() as it's called
494494
// from enqueue process functions
495495
MPreparedHostDepsEvents.push_back(DepEvent);
496-
return;
496+
return nullptr;
497497
}
498498

499+
Command *ConnectionCmd = nullptr;
500+
499501
// Do not add redundant event dependencies for in-order queues.
500502
if (Dep.MDepCommand && Dep.MDepCommand->getWorkerQueue() == WorkerQueue &&
501503
WorkerQueue->has_property<property::queue::in_order>())
502-
return;
504+
return nullptr;
503505

504506
ContextImplPtr DepEventContext = DepEvent->getContextImpl();
505507
// If contexts don't match we'll connect them using host task
506508
if (DepEventContext != WorkerContext && !WorkerContext->is_host()) {
507509
Scheduler::GraphBuilder &GB = Scheduler::getInstance().MGraphBuilder;
508-
GB.connectDepEvent(this, DepEvent, Dep);
510+
ConnectionCmd = GB.connectDepEvent(this, DepEvent, Dep);
509511
} else
510512
MPreparedDepsEvents.push_back(std::move(DepEvent));
513+
514+
return ConnectionCmd;
511515
}
512516

513517
const ContextImplPtr &Command::getWorkerContext() const {
@@ -516,19 +520,23 @@ const ContextImplPtr &Command::getWorkerContext() const {
516520

517521
const QueueImplPtr &Command::getWorkerQueue() const { return MQueue; }
518522

519-
void Command::addDep(DepDesc NewDep) {
523+
Command *Command::addDep(DepDesc NewDep) {
524+
Command *ConnectionCmd = nullptr;
525+
520526
if (NewDep.MDepCommand) {
521-
processDepEvent(NewDep.MDepCommand->getEvent(), NewDep);
527+
ConnectionCmd = processDepEvent(NewDep.MDepCommand->getEvent(), NewDep);
522528
}
523529
MDeps.push_back(NewDep);
524530
#ifdef XPTI_ENABLE_INSTRUMENTATION
525531
emitEdgeEventForCommandDependence(
526532
NewDep.MDepCommand, (void *)NewDep.MDepRequirement->MSYCLMemObj,
527533
accessModeToString(NewDep.MDepRequirement->MAccessMode), true);
528534
#endif
535+
536+
return ConnectionCmd;
529537
}
530538

531-
void Command::addDep(EventImplPtr Event) {
539+
Command *Command::addDep(EventImplPtr Event) {
532540
#ifdef XPTI_ENABLE_INSTRUMENTATION
533541
// We need this for just the instrumentation, so guarding it will prevent
534542
// unused variable warnings when instrumentation is turned off
@@ -538,7 +546,7 @@ void Command::addDep(EventImplPtr Event) {
538546
emitEdgeEventForEventDependence(Cmd, PiEventAddr);
539547
#endif
540548

541-
processDepEvent(std::move(Event), DepDesc{nullptr, nullptr, nullptr});
549+
return processDepEvent(std::move(Event), DepDesc{nullptr, nullptr, nullptr});
542550
}
543551

544552
void Command::emitEnqueuedEventSignal(RT::PiEvent &PiEventAddr) {
@@ -732,7 +740,10 @@ AllocaCommand::AllocaCommand(QueueImplPtr Queue, Requirement Req,
732740
// Node event must be created before the dependent edge is added to this node,
733741
// so this call must be before the addDep() call.
734742
emitInstrumentationDataProxy();
735-
addDep(DepDesc(nullptr, getRequirement(), this));
743+
// "Nothing to depend on"
744+
Command *ConnectionCmd = addDep(DepDesc(nullptr, getRequirement(), this));
745+
assert(ConnectionCmd == nullptr);
746+
(void)ConnectionCmd;
736747
}
737748

738749
void AllocaCommand::emitInstrumentationData() {
@@ -795,7 +806,8 @@ void AllocaCommand::printDot(std::ostream &Stream) const {
795806
}
796807

797808
AllocaSubBufCommand::AllocaSubBufCommand(QueueImplPtr Queue, Requirement Req,
798-
AllocaCommandBase *ParentAlloca)
809+
AllocaCommandBase *ParentAlloca,
810+
std::vector<Command *> &ToEnqueue)
799811
: AllocaCommandBase(CommandType::ALLOCA_SUB_BUF, std::move(Queue),
800812
std::move(Req),
801813
/*LinkedAllocaCmd*/ nullptr),
@@ -804,7 +816,10 @@ AllocaSubBufCommand::AllocaSubBufCommand(QueueImplPtr Queue, Requirement Req,
804816
// is added to this node, so this call must be before
805817
// the addDep() call.
806818
emitInstrumentationDataProxy();
807-
addDep(DepDesc(MParentAlloca, getRequirement(), MParentAlloca));
819+
Command *ConnectionCmd =
820+
addDep(DepDesc(MParentAlloca, getRequirement(), MParentAlloca));
821+
if (ConnectionCmd)
822+
ToEnqueue.push_back(ConnectionCmd);
808823
}
809824

810825
void AllocaSubBufCommand::emitInstrumentationData() {
@@ -1329,7 +1344,10 @@ void EmptyCommand::addRequirement(Command *DepCmd, AllocaCommandBase *AllocaCmd,
13291344
MRequirements.emplace_back(ReqRef);
13301345
const Requirement *const StoredReq = &MRequirements.back();
13311346

1332-
addDep(DepDesc{DepCmd, StoredReq, AllocaCmd});
1347+
// EmptyCommand is always host one, so we believe that result of addDep is nil
1348+
Command *Cmd = addDep(DepDesc{DepCmd, StoredReq, AllocaCmd});
1349+
assert(Cmd == nullptr && "Conection command should be null for EmptyCommand");
1350+
(void)Cmd;
13331351
}
13341352

13351353
void EmptyCommand::emitInstrumentationData() {

sycl/source/detail/scheduler/commands.hpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,11 @@ class Command {
107107

108108
Command(CommandType Type, QueueImplPtr Queue);
109109

110-
void addDep(DepDesc NewDep);
110+
/// \return an optional connection cmd to enqueue
111+
[[nodiscard]] Command *addDep(DepDesc NewDep);
111112

112-
void addDep(EventImplPtr Event);
113+
/// \return an optional connection cmd to enqueue
114+
[[nodiscard]] Command *addDep(EventImplPtr Event);
113115

114116
void addUser(Command *NewUser) { MUsers.insert(NewUser); }
115117

@@ -204,13 +206,15 @@ class Command {
204206
/// Perform glueing of events from different contexts
205207
/// \param DepEvent event this commands should depend on
206208
/// \param Dep optional DepDesc to perform connection of events properly
209+
/// \return returns an optional connection command to enqueue
207210
///
208211
/// Glueing (i.e. connecting) will be performed if and only if DepEvent is
209212
/// not from host context and its context doesn't match to context of this
210213
/// command. Context of this command is fetched via getWorkerContext().
211214
///
212215
/// Optionality of Dep is set by Dep.MDepCommand not equal to nullptr.
213-
void processDepEvent(EventImplPtr DepEvent, const DepDesc &Dep);
216+
[[nodiscard]] Command *processDepEvent(EventImplPtr DepEvent,
217+
const DepDesc &Dep);
214218

215219
/// Private interface. Derived classes should implement this method.
216220
virtual cl_int enqueueImp() = 0;
@@ -387,7 +391,8 @@ class AllocaCommand : public AllocaCommandBase {
387391
class AllocaSubBufCommand : public AllocaCommandBase {
388392
public:
389393
AllocaSubBufCommand(QueueImplPtr Queue, Requirement Req,
390-
AllocaCommandBase *ParentAlloca);
394+
AllocaCommandBase *ParentAlloca,
395+
std::vector<Command *> &ToEnqueue);
391396

392397
void *getMemAllocation() const final;
393398
void printDot(std::ostream &Stream) const final;

0 commit comments

Comments
 (0)