@@ -194,6 +194,8 @@ MemObjRecord *Scheduler::GraphBuilder::getOrInsertMemObjRecord(
194
194
ToEnqueue.push_back (ConnectionCmd);
195
195
Dependency->addUser (Dependant);
196
196
--(Dependency->MLeafCounter );
197
+ if (Dependency->MLeafCounter == 0 && Dependency->isSuccessfullyEnqueued ())
198
+ cleanupCommand (Dependency);
197
199
};
198
200
199
201
const ContextImplPtr &InteropCtxPtr = Req->MSYCLMemObj ->getInteropContext ();
@@ -225,17 +227,25 @@ MemObjRecord *Scheduler::GraphBuilder::getOrInsertMemObjRecord(
225
227
return MemObject->MRecord .get ();
226
228
}
227
229
228
- void Scheduler::GraphBuilder::updateLeaves (const std::set<Command *> &Cmds,
229
- MemObjRecord *Record,
230
- access::mode AccessMode) {
230
+ void Scheduler::GraphBuilder::updateLeaves (
231
+ const std::set<Command *> &Cmds, MemObjRecord *Record,
232
+ access::mode AccessMode, std::vector<Command *> *CommandsToCleanUp ) {
231
233
232
234
const bool ReadOnlyReq = AccessMode == access::mode::read;
233
235
if (ReadOnlyReq)
234
236
return ;
235
237
236
238
for (Command *Cmd : Cmds) {
239
+ bool WasLeaf = Cmd->MLeafCounter > 0 ;
237
240
Cmd->MLeafCounter -= Record->MReadLeaves .remove (Cmd);
238
241
Cmd->MLeafCounter -= Record->MWriteLeaves .remove (Cmd);
242
+ if (Cmd->MLeafCounter == 0 && Cmd->isSuccessfullyEnqueued ()) {
243
+ if (CommandsToCleanUp) {
244
+ if (WasLeaf)
245
+ CommandsToCleanUp->push_back (Cmd);
246
+ } else
247
+ cleanupCommand (Cmd);
248
+ }
239
249
}
240
250
}
241
251
@@ -963,14 +973,23 @@ Scheduler::GraphBuilder::addCG(std::unique_ptr<detail::CG> CommandGroup,
963
973
// Node dependencies can be modified further when adding the node to leaves,
964
974
// iterate over their copy.
965
975
// FIXME employ a reference here to eliminate copying of a vector
976
+ // Updating leaves might also clean up some of the dep commands, so update
977
+ // their users first.
978
+ // FIXME there's probably a better way of handling cleanup & leaf/dep update
979
+ // here considering that some of the updated might be destroyed by cleanup
980
+ // immediately after.
966
981
std::vector<DepDesc> Deps = NewCmd->MDeps ;
982
+ std::vector<Command *> CommandsToCleanUp;
967
983
for (DepDesc &Dep : Deps) {
968
984
Dep.MDepCommand ->addUser (NewCmd.get ());
969
985
const Requirement *Req = Dep.MDepRequirement ;
970
986
MemObjRecord *Record = getMemObjRecord (Req->MSYCLMemObj );
971
- updateLeaves ({Dep.MDepCommand }, Record, Req->MAccessMode );
987
+ updateLeaves ({Dep.MDepCommand }, Record, Req->MAccessMode ,
988
+ &CommandsToCleanUp);
972
989
addNodeToLeaves (Record, NewCmd.get (), Req->MAccessMode , ToEnqueue);
973
990
}
991
+ for (Command *Cmd : CommandsToCleanUp)
992
+ cleanupCommand (Cmd);
974
993
975
994
// Register all the events as dependencies
976
995
for (detail::EventImplPtr e : Events) {
@@ -993,9 +1012,13 @@ void Scheduler::GraphBuilder::decrementLeafCountersForRecord(
993
1012
MemObjRecord *Record) {
994
1013
for (Command *Cmd : Record->MReadLeaves ) {
995
1014
--(Cmd->MLeafCounter );
1015
+ if (Cmd->MLeafCounter == 0 && Cmd->isSuccessfullyEnqueued ())
1016
+ cleanupCommand (Cmd);
996
1017
}
997
1018
for (Command *Cmd : Record->MWriteLeaves ) {
998
1019
--(Cmd->MLeafCounter );
1020
+ if (Cmd->MLeafCounter == 0 && Cmd->isSuccessfullyEnqueued ())
1021
+ cleanupCommand (Cmd);
999
1022
}
1000
1023
}
1001
1024
@@ -1096,6 +1119,52 @@ void Scheduler::GraphBuilder::cleanupCommandsForRecord(
1096
1119
handleVisitedNodes (MVisitedCmds);
1097
1120
}
1098
1121
1122
+
1123
+ void Scheduler::GraphBuilder::cleanupCommand (Command *Cmd) {
1124
+ if (SYCLConfig<SYCL_DISABLE_EXECUTION_GRAPH_CLEANUP>::get ())
1125
+ return ;
1126
+ assert (Cmd->MLeafCounter == 0 && Cmd->isSuccessfullyEnqueued ());
1127
+ // Isolated command nodes are cleaned up by scheduler instead.
1128
+ assert (Cmd->MDeps .size () != 0 || Cmd->MUsers .size () != 0 );
1129
+ Command::CommandType CmdT = Cmd->getType ();
1130
+ // Allocas have to be kept alive until memory objects are released.
1131
+ if (CmdT == Command::ALLOCA || CmdT == Command::ALLOCA_SUB_BUF)
1132
+ return ;
1133
+
1134
+ // FIXME handle host tasks
1135
+ if (CmdT == Command::RUN_CG) {
1136
+ auto *ExecCGCmd = static_cast <ExecCGCommand *>(Cmd);
1137
+ if (ExecCGCmd->getCG ().getType () == CG::CGTYPE::CodeplayHostTask) {
1138
+ return ;
1139
+ }
1140
+ }
1141
+ assert (CmdT != Command::ALLOCA && CmdT != Command::ALLOCA_SUB_BUF);
1142
+
1143
+ for (Command *UserCmd : Cmd->MUsers ) {
1144
+ for (DepDesc &Dep : UserCmd->MDeps ) {
1145
+ // Link the users of the command to the alloca command(s) instead
1146
+ if (Dep.MDepCommand == Cmd) {
1147
+ // ... unless the user is the alloca itself.
1148
+ if (Dep.MAllocaCmd == UserCmd) {
1149
+ Dep.MDepCommand = nullptr ;
1150
+ }
1151
+ else {
1152
+ Dep.MDepCommand = Dep.MAllocaCmd ;
1153
+ Dep.MDepCommand ->MUsers .insert (UserCmd);
1154
+ }
1155
+ }
1156
+ }
1157
+ }
1158
+ // Update dependency users
1159
+ for (DepDesc &Dep : Cmd->MDeps ) {
1160
+ Command *DepCmd = Dep.MDepCommand ;
1161
+ DepCmd->MUsers .erase (Cmd);
1162
+ }
1163
+ Cmd->getEvent ()->setCommand (nullptr );
1164
+ Cmd->getEvent ()->cleanupDependencyEvents ();
1165
+ delete Cmd;
1166
+ }
1167
+
1099
1168
void Scheduler::GraphBuilder::cleanupFinishedCommands (
1100
1169
Command *FinishedCmd,
1101
1170
std::vector<std::shared_ptr<stream_impl>> &StreamsToDeallocate) {
0 commit comments