Skip to content

Commit 195b265

Browse files
Add a test
Signed-off-by: Sergey Semenov <[email protected]>
1 parent 197353f commit 195b265

File tree

5 files changed

+176
-88
lines changed

5 files changed

+176
-88
lines changed

sycl/test/scheduler/FakeCommand.hpp

Lines changed: 0 additions & 23 deletions
This file was deleted.
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// RUN: %clangxx -fsycl %s -o %t.out
2+
// RUN: %t.out
3+
#include <CL/sycl.hpp>
4+
5+
#include <algorithm>
6+
#include <vector>
7+
8+
#include "SchedulerTestUtils.hpp"
9+
10+
using namespace cl::sycl;
11+
12+
// This test checks regular execution graph cleanup at host-device
13+
// synchronization points
14+
int main() {
15+
TestScheduler TS;
16+
queue Queue;
17+
buffer<int, 1> BufA(range<1>(1));
18+
buffer<int, 1> BufB(range<1>(1));
19+
buffer<int, 1> BufC(range<1>(1));
20+
detail::Requirement FakeReqA = getFakeRequirement(BufA);
21+
detail::Requirement FakeReqB = getFakeRequirement(BufB);
22+
detail::Requirement FakeReqC = getFakeRequirement(BufC);
23+
detail::MemObjRecord *RecC =
24+
TS.getOrInsertMemObjRecord(detail::getSyclObjImpl(Queue), &FakeReqC);
25+
26+
// Create a graph and check that all inner nodes have been deleted and
27+
// their users have had the corresponding dependency replaced with a
28+
// dependency on the alloca. The graph should undergo the following
29+
// transformation:
30+
// +---------+ +---------+ +---------++---------+
31+
// | LeafA | <-- | InnerA | | LeafA || LeafB |
32+
// +---------+ +---------+ +---------++---------+
33+
// | | | |
34+
// | | ===> | |
35+
// v v v v
36+
// +---------+ +---------+ +---------++---------+
37+
// | InnerC | | InnerB | | AllocaA || AllocaB |
38+
// +---------+ +---------+ +---------++---------+
39+
// | |
40+
// | |
41+
// v v
42+
// +---------+ +---------+
43+
// | AllocaA | | LeafB |
44+
// +---------+ +---------+
45+
// |
46+
// |
47+
// v
48+
// +---------+
49+
// | AllocaB |
50+
// +---------+
51+
detail::AllocaCommand AllocaA{detail::getSyclObjImpl(Queue), FakeReqA};
52+
detail::AllocaCommand AllocaB{detail::getSyclObjImpl(Queue), FakeReqB};
53+
54+
int NInnerCommandsAlive = 3;
55+
std::function<void()> Callback = [&]() { --NInnerCommandsAlive; };
56+
57+
FakeCommand *InnerC = new FakeCommandWithCallback(
58+
detail::getSyclObjImpl(Queue), FakeReqA, Callback);
59+
addEdge(InnerC, &AllocaA, &AllocaA);
60+
61+
FakeCommand LeafB{detail::getSyclObjImpl(Queue), FakeReqB};
62+
addEdge(&LeafB, &AllocaB, &AllocaB);
63+
TS.AddNodeToLeaves(RecC, &LeafB);
64+
65+
FakeCommand LeafA{detail::getSyclObjImpl(Queue), FakeReqA};
66+
addEdge(&LeafA, InnerC, &AllocaA);
67+
TS.AddNodeToLeaves(RecC, &LeafA);
68+
69+
FakeCommand *InnerB = new FakeCommandWithCallback(
70+
detail::getSyclObjImpl(Queue), FakeReqB, Callback);
71+
addEdge(InnerB, &LeafB, &AllocaB);
72+
73+
FakeCommand *InnerA = new FakeCommandWithCallback(
74+
detail::getSyclObjImpl(Queue), FakeReqA, Callback);
75+
addEdge(InnerA, &LeafA, &AllocaA);
76+
addEdge(InnerA, InnerB, &AllocaB);
77+
78+
TS.cleanupFinishedCommands(InnerA);
79+
TS.removeRecordForMemObj(detail::getSyclObjImpl(BufC).get());
80+
81+
assert(NInnerCommandsAlive == 0);
82+
83+
assert(LeafA.MDeps.size() == 1);
84+
assert(LeafA.MDeps[0].MDepCommand == &AllocaA);
85+
assert(AllocaA.MUsers.size() == 1);
86+
assert(*AllocaA.MUsers.begin() == &LeafA);
87+
88+
assert(LeafB.MDeps.size() == 1);
89+
assert(LeafB.MDeps[0].MDepCommand == &AllocaB);
90+
assert(AllocaB.MUsers.size() == 1);
91+
assert(*AllocaB.MUsers.begin() == &LeafB);
92+
}

sycl/test/scheduler/LeafLimit.cpp

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,12 @@
77
#include <memory>
88
#include <vector>
99

10-
#include "FakeCommand.hpp"
10+
#include "SchedulerTestUtils.hpp"
1111

1212
// This test checks the leaf limit imposed on the execution graph
1313

1414
using namespace cl::sycl;
1515

16-
class TestScheduler : public detail::Scheduler {
17-
public:
18-
void AddNodeToLeaves(detail::MemObjRecord *Rec, detail::Command *Cmd,
19-
access::mode Mode) {
20-
return MGraphBuilder.AddNodeToLeaves(Rec, Cmd, Mode);
21-
}
22-
23-
detail::MemObjRecord *
24-
getOrInsertMemObjRecord(const detail::QueueImplPtr &Queue,
25-
detail::Requirement *Req) {
26-
return MGraphBuilder.getOrInsertMemObjRecord(Queue, Req);
27-
}
28-
};
29-
3016
int main() {
3117
TestScheduler TS;
3218
queue Queue;
@@ -57,7 +43,7 @@ int main() {
5743
}
5844
// Add edges as leaves and exceed the leaf limit
5945
for (auto LeafPtr : LeavesToAdd) {
60-
TS.AddNodeToLeaves(Rec, LeafPtr, access::mode::read_write);
46+
TS.AddNodeToLeaves(Rec, LeafPtr);
6147
}
6248
// Check that the oldest leaf has been removed from the leaf list
6349
// and added as a dependency of the newest one instead

sycl/test/scheduler/MemObjCommandCleanup.cpp

Lines changed: 1 addition & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2,65 +2,17 @@
22
// RUN: %t.out
33
#include <CL/sycl.hpp>
44

5-
#include <functional>
65
#include <memory>
76
#include <utility>
87

9-
#include "FakeCommand.hpp"
8+
#include "SchedulerTestUtils.hpp"
109

1110
// This test checks that the execution graph cleanup on memory object
1211
// destruction traverses the entire graph, rather than only the immediate users
1312
// of deleted commands.
1413

1514
using namespace cl::sycl;
1615

17-
class TestScheduler : public detail::Scheduler {
18-
public:
19-
void cleanupCommandsForRecord(detail::MemObjRecord *Rec) {
20-
MGraphBuilder.cleanupCommandsForRecord(Rec);
21-
}
22-
23-
void removeRecordForMemObj(detail::SYCLMemObjI *MemObj) {
24-
MGraphBuilder.removeRecordForMemObj(MemObj);
25-
}
26-
27-
detail::MemObjRecord *
28-
getOrInsertMemObjRecord(const detail::QueueImplPtr &Queue,
29-
detail::Requirement *Req) {
30-
return MGraphBuilder.getOrInsertMemObjRecord(Queue, Req);
31-
}
32-
};
33-
34-
class FakeCommandWithCallback : public FakeCommand {
35-
public:
36-
FakeCommandWithCallback(detail::QueueImplPtr Queue, detail::Requirement Req,
37-
std::function<void()> Callback)
38-
: FakeCommand(Queue, Req), MCallback(std::move(Callback)) {}
39-
40-
~FakeCommandWithCallback() override { MCallback(); }
41-
42-
protected:
43-
std::function<void()> MCallback;
44-
};
45-
46-
template <typename MemObjT>
47-
detail::Requirement getFakeRequirement(const MemObjT &MemObj) {
48-
return {{0, 0, 0},
49-
{0, 0, 0},
50-
{0, 0, 0},
51-
access::mode::read_write,
52-
detail::getSyclObjImpl(MemObj).get(),
53-
0,
54-
0,
55-
0};
56-
}
57-
58-
void addEdge(detail::Command *User, detail::Command *Dep,
59-
detail::AllocaCommandBase *Alloca) {
60-
User->addDep(detail::DepDesc{Dep, User->getRequirement(), Alloca});
61-
Dep->addUser(User);
62-
}
63-
6416
int main() {
6517
TestScheduler TS;
6618
queue Queue;
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#pragma once
2+
#include <CL/sycl.hpp>
3+
4+
#include <functional>
5+
// This header contains a few common classes/methods used in
6+
// execution graph testing.
7+
8+
class FakeCommand : public cl::sycl::detail::Command {
9+
public:
10+
FakeCommand(cl::sycl::detail::QueueImplPtr Queue,
11+
cl::sycl::detail::Requirement Req)
12+
: Command{cl::sycl::detail::Command::EMPTY_TASK, Queue},
13+
MRequirement{std::move(Req)} {}
14+
15+
void printDot(std::ostream &Stream) const override {}
16+
17+
const cl::sycl::detail::Requirement *getRequirement() const final {
18+
return &MRequirement;
19+
};
20+
21+
cl_int enqueueImp() override { return MRetVal; }
22+
23+
cl_int MRetVal = CL_SUCCESS;
24+
25+
protected:
26+
cl::sycl::detail::Requirement MRequirement;
27+
};
28+
29+
class FakeCommandWithCallback : public FakeCommand {
30+
public:
31+
FakeCommandWithCallback(cl::sycl::detail::QueueImplPtr Queue,
32+
cl::sycl::detail::Requirement Req,
33+
std::function<void()> Callback)
34+
: FakeCommand(Queue, Req), MCallback(std::move(Callback)) {}
35+
36+
~FakeCommandWithCallback() override { MCallback(); }
37+
38+
protected:
39+
std::function<void()> MCallback;
40+
};
41+
42+
class TestScheduler : public cl::sycl::detail::Scheduler {
43+
public:
44+
cl::sycl::detail::MemObjRecord *
45+
getOrInsertMemObjRecord(const cl::sycl::detail::QueueImplPtr &Queue,
46+
cl::sycl::detail::Requirement *Req) {
47+
return MGraphBuilder.getOrInsertMemObjRecord(Queue, Req);
48+
}
49+
50+
void removeRecordForMemObj(cl::sycl::detail::SYCLMemObjI *MemObj) {
51+
MGraphBuilder.removeRecordForMemObj(MemObj);
52+
}
53+
54+
void cleanupCommandsForRecord(cl::sycl::detail::MemObjRecord *Rec) {
55+
MGraphBuilder.cleanupCommandsForRecord(Rec);
56+
}
57+
58+
void AddNodeToLeaves(
59+
cl::sycl::detail::MemObjRecord *Rec, cl::sycl::detail::Command *Cmd,
60+
cl::sycl::access::mode Mode = cl::sycl::access::mode::read_write) {
61+
return MGraphBuilder.AddNodeToLeaves(Rec, Cmd, Mode);
62+
}
63+
};
64+
65+
void addEdge(cl::sycl::detail::Command *User, cl::sycl::detail::Command *Dep,
66+
cl::sycl::detail::AllocaCommandBase *Alloca) {
67+
User->addDep(cl::sycl::detail::DepDesc{Dep, User->getRequirement(), Alloca});
68+
Dep->addUser(User);
69+
}
70+
71+
template <typename MemObjT>
72+
cl::sycl::detail::Requirement getFakeRequirement(const MemObjT &MemObj) {
73+
return {{0, 0, 0},
74+
{0, 0, 0},
75+
{0, 0, 0},
76+
cl::sycl::access::mode::read_write,
77+
cl::sycl::detail::getSyclObjImpl(MemObj).get(),
78+
0,
79+
0,
80+
0};
81+
}

0 commit comments

Comments
 (0)