Skip to content

[SYCL] Refactored scheduler unit tests #1598

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 4 additions & 31 deletions sycl/unittests/scheduler/BlockedCommands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,37 +7,10 @@
//===----------------------------------------------------------------------===//

#include "SchedulerTest.hpp"

#include <CL/cl.h>
#include <CL/sycl.hpp>
#include <detail/scheduler/scheduler.hpp>

#include <gtest/gtest.h>
#include "SchedulerTestUtils.hpp"

using namespace cl::sycl;

class MockCommand : public detail::Command {
public:
MockCommand(detail::QueueImplPtr Queue)
: Command(detail::Command::ALLOCA, Queue) {}
void printDot(std::ostream &Stream) const override {}

void emitInstrumentationData() override {}

cl_int enqueueImp() override { return MRetVal; }

cl_int MRetVal = CL_SUCCESS;
};

class TestScheduler : public detail::Scheduler {
public:
static bool enqueueCommand(detail::Command *Cmd,
detail::EnqueueResultT &EnqueueResult,
detail::BlockingT Blocking) {
return GraphProcessor::enqueueCommand(Cmd, EnqueueResult, Blocking);
}
};

TEST_F(SchedulerTest, BlockedCommands) {
MockCommand MockCmd(detail::getSyclObjImpl(MQueue));

Expand All @@ -47,7 +20,7 @@ TEST_F(SchedulerTest, BlockedCommands) {

detail::EnqueueResultT Res;
bool Enqueued =
TestScheduler::enqueueCommand(&MockCmd, Res, detail::NON_BLOCKING);
MockScheduler::enqueueCommand(&MockCmd, Res, detail::NON_BLOCKING);
ASSERT_FALSE(Enqueued) << "Blocked command should not be enqueued\n";
ASSERT_EQ(detail::EnqueueResultT::SyclEnqueueBlocked, Res.MResult)
<< "Result of enqueueing blocked command should be BLOCKED\n";
Expand All @@ -56,7 +29,7 @@ TEST_F(SchedulerTest, BlockedCommands) {
Res.MResult = detail::EnqueueResultT::SyclEnqueueSuccess;
MockCmd.MRetVal = CL_DEVICE_PARTITION_EQUALLY;

Enqueued = TestScheduler::enqueueCommand(&MockCmd, Res, detail::BLOCKING);
Enqueued = MockScheduler::enqueueCommand(&MockCmd, Res, detail::BLOCKING);
ASSERT_FALSE(Enqueued) << "Blocked command should not be enqueued\n";
ASSERT_EQ(detail::EnqueueResultT::SyclEnqueueFailed, Res.MResult)
<< "The command is expected to fail to enqueue.\n";
Expand All @@ -67,7 +40,7 @@ TEST_F(SchedulerTest, BlockedCommands) {
Res = detail::EnqueueResultT{};
MockCmd.MEnqueueStatus = detail::EnqueueResultT::SyclEnqueueReady;
MockCmd.MRetVal = CL_SUCCESS;
Enqueued = TestScheduler::enqueueCommand(&MockCmd, Res, detail::BLOCKING);
Enqueued = MockScheduler::enqueueCommand(&MockCmd, Res, detail::BLOCKING);
ASSERT_TRUE(Enqueued &&
Res.MResult == detail::EnqueueResultT::SyclEnqueueSuccess)
<< "The command is expected to be successfully enqueued.\n";
Expand Down
30 changes: 2 additions & 28 deletions sycl/unittests/scheduler/FailedCommands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,38 +7,12 @@
//===----------------------------------------------------------------------===//

#include "SchedulerTest.hpp"

#include <CL/cl.h>
#include <CL/sycl.hpp>
#include <detail/scheduler/scheduler.hpp>

#include <gtest/gtest.h>
#include "SchedulerTestUtils.hpp"

using namespace cl::sycl;

class MockCommand : public detail::Command {
public:
MockCommand(detail::QueueImplPtr Queue)
: Command(detail::Command::ALLOCA, Queue) {}
void printDot(std::ostream &Stream) const override {}
void emitInstrumentationData() override {}
cl_int enqueueImp() override { return CL_SUCCESS; }
};

class MockScheduler : public detail::Scheduler {
public:
static bool enqueueCommand(detail::Command *Cmd,
detail::EnqueueResultT &EnqueueResult,
detail::BlockingT Blocking) {
return GraphProcessor::enqueueCommand(Cmd, EnqueueResult, Blocking);
}
};

TEST_F(SchedulerTest, FailedDependency) {
detail::Requirement MockReq(/*Offset*/ {0, 0, 0}, /*AccessRange*/ {1, 1, 1},
/*MemoryRange*/ {1, 1, 1},
access::mode::read_write, /*SYCLMemObjT*/ nullptr,
/*Dims*/ 1, /*ElementSize*/ 1);
detail::Requirement MockReq = getMockRequirement();
MockCommand MDep(detail::getSyclObjImpl(MQueue));
MockCommand MUser(detail::getSyclObjImpl(MQueue));
MDep.addUser(&MUser);
Expand Down
42 changes: 19 additions & 23 deletions sycl/unittests/scheduler/FinishedCmdCleanup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,20 @@
#include "SchedulerTest.hpp"
#include "SchedulerTestUtils.hpp"

#include <CL/sycl.hpp>
#include <detail/event_impl.hpp>
#include <detail/scheduler/scheduler.hpp>

#include <gtest/gtest.h>

using namespace cl::sycl;

TEST_F(SchedulerTest, FinishedCmdCleanup) {
TestScheduler TS;
MockScheduler MS;
buffer<int, 1> BufA(range<1>(1));
buffer<int, 1> BufB(range<1>(1));
buffer<int, 1> BufC(range<1>(1));
detail::Requirement FakeReqA = getFakeRequirement(BufA);
detail::Requirement FakeReqB = getFakeRequirement(BufB);
detail::Requirement FakeReqC = getFakeRequirement(BufC);
detail::Requirement MockReqA = getMockRequirement(BufA);
detail::Requirement MockReqB = getMockRequirement(BufB);
detail::Requirement MockReqC = getMockRequirement(BufC);
detail::MemObjRecord *RecC =
TS.getOrInsertMemObjRecord(detail::getSyclObjImpl(MQueue), &FakeReqC);
MS.getOrInsertMemObjRecord(detail::getSyclObjImpl(MQueue), &MockReqC);

// Create a graph and check that all inner nodes have been deleted and
// their users have had the corresponding dependency replaced with a
Expand All @@ -53,37 +49,37 @@ TEST_F(SchedulerTest, FinishedCmdCleanup) {
// +---------+
// | AllocaB |
// +---------+
detail::AllocaCommand AllocaA{detail::getSyclObjImpl(MQueue), FakeReqA};
detail::AllocaCommand AllocaB{detail::getSyclObjImpl(MQueue), FakeReqB};
detail::AllocaCommand AllocaA{detail::getSyclObjImpl(MQueue), MockReqA};
detail::AllocaCommand AllocaB{detail::getSyclObjImpl(MQueue), MockReqB};

int NInnerCommandsAlive = 3;
std::function<void()> Callback = [&]() { --NInnerCommandsAlive; };

FakeCommand *InnerC = new FakeCommandWithCallback(
detail::getSyclObjImpl(MQueue), FakeReqA, Callback);
MockCommand *InnerC = new MockCommandWithCallback(
detail::getSyclObjImpl(MQueue), MockReqA, Callback);
addEdge(InnerC, &AllocaA, &AllocaA);

FakeCommand LeafB{detail::getSyclObjImpl(MQueue), FakeReqB};
MockCommand LeafB{detail::getSyclObjImpl(MQueue), MockReqB};
addEdge(&LeafB, &AllocaB, &AllocaB);
TS.addNodeToLeaves(RecC, &LeafB);
MS.addNodeToLeaves(RecC, &LeafB);

FakeCommand LeafA{detail::getSyclObjImpl(MQueue), FakeReqA};
MockCommand LeafA{detail::getSyclObjImpl(MQueue), MockReqA};
addEdge(&LeafA, InnerC, &AllocaA);
TS.addNodeToLeaves(RecC, &LeafA);
MS.addNodeToLeaves(RecC, &LeafA);

FakeCommand *InnerB = new FakeCommandWithCallback(
detail::getSyclObjImpl(MQueue), FakeReqB, Callback);
MockCommand *InnerB = new MockCommandWithCallback(
detail::getSyclObjImpl(MQueue), MockReqB, Callback);
addEdge(InnerB, &LeafB, &AllocaB);

FakeCommand *InnerA = new FakeCommandWithCallback(
detail::getSyclObjImpl(MQueue), FakeReqA, Callback);
MockCommand *InnerA = new MockCommandWithCallback(
detail::getSyclObjImpl(MQueue), MockReqA, Callback);
addEdge(InnerA, &LeafA, &AllocaA);
addEdge(InnerA, InnerB, &AllocaB);

std::shared_ptr<detail::event_impl> Event{new detail::event_impl{}};
Event->setCommand(InnerA);
TS.cleanupFinishedCommands(Event);
TS.removeRecordForMemObj(detail::getSyclObjImpl(BufC).get());
MS.cleanupFinishedCommands(Event);
MS.removeRecordForMemObj(detail::getSyclObjImpl(BufC).get());

EXPECT_EQ(NInnerCommandsAlive, 0);

Expand Down
35 changes: 13 additions & 22 deletions sycl/unittests/scheduler/LeafLimit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
#include "SchedulerTest.hpp"
#include "SchedulerTestUtils.hpp"

#include <CL/sycl.hpp>

#include <algorithm>
#include <cstddef>
#include <memory>
Expand All @@ -19,36 +17,29 @@
using namespace cl::sycl;

TEST_F(SchedulerTest, LeafLimit) {
TestScheduler TS;
MockScheduler MS;

buffer<int, 1> Buf(range<1>(1));
detail::Requirement FakeReq{{0, 0, 0},
{0, 0, 0},
{0, 0, 0},
access::mode::read_write,
detail::getSyclObjImpl(Buf).get(),
0,
0,
0};
FakeCommand *FakeDepCmd =
new FakeCommand(detail::getSyclObjImpl(MQueue), FakeReq);
detail::Requirement MockReq = getMockRequirement(Buf);
MockCommand *MockDepCmd =
new MockCommand(detail::getSyclObjImpl(MQueue), MockReq);
detail::MemObjRecord *Rec =
TS.getOrInsertMemObjRecord(detail::getSyclObjImpl(MQueue), &FakeReq);
MS.getOrInsertMemObjRecord(detail::getSyclObjImpl(MQueue), &MockReq);

// Create commands that will be added as leaves exceeding the limit by 1
std::vector<FakeCommand *> LeavesToAdd;
std::vector<MockCommand *> LeavesToAdd;
for (std::size_t i = 0; i < Rec->MWriteLeaves.capacity() + 1; ++i) {
LeavesToAdd.push_back(
new FakeCommand(detail::getSyclObjImpl(MQueue), FakeReq));
new MockCommand(detail::getSyclObjImpl(MQueue), MockReq));
}
// Create edges: all soon-to-be leaves are direct users of FakeDep
// Create edges: all soon-to-be leaves are direct users of MockDep
for (auto Leaf : LeavesToAdd) {
FakeDepCmd->addUser(Leaf);
Leaf->addDep(detail::DepDesc{FakeDepCmd, Leaf->getRequirement(), nullptr});
MockDepCmd->addUser(Leaf);
Leaf->addDep(detail::DepDesc{MockDepCmd, Leaf->getRequirement(), nullptr});
}
// Add edges as leaves and exceed the leaf limit
for (auto LeafPtr : LeavesToAdd) {
TS.addNodeToLeaves(Rec, LeafPtr);
MS.addNodeToLeaves(Rec, LeafPtr);
}
// Check that the oldest leaf has been removed from the leaf list
// and added as a dependency of the newest one instead
Expand All @@ -59,8 +50,8 @@ TEST_F(SchedulerTest, LeafLimit) {
assert(std::find(Leaves.begin(), Leaves.end(), LeavesToAdd[i]) !=
Leaves.end());
}
FakeCommand *OldestLeaf = LeavesToAdd.front();
FakeCommand *NewestLeaf = LeavesToAdd.back();
MockCommand *OldestLeaf = LeavesToAdd.front();
MockCommand *NewestLeaf = LeavesToAdd.back();
ASSERT_EQ(OldestLeaf->MUsers.size(), 1U);
EXPECT_GT(OldestLeaf->MUsers.count(NewestLeaf), 0U);
ASSERT_EQ(NewestLeaf->MDeps.size(), 2U);
Expand Down
47 changes: 21 additions & 26 deletions sycl/unittests/scheduler/MemObjCommandCleanup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,49 +9,44 @@
#include "SchedulerTest.hpp"
#include "SchedulerTestUtils.hpp"

#include <CL/sycl.hpp>
#include <detail/scheduler/scheduler.hpp>

#include <gtest/gtest.h>

using namespace cl::sycl;

TEST_F(SchedulerTest, MemObjCommandCleanup) {
TestScheduler TS;
MockScheduler MS;
buffer<int, 1> BufA(range<1>(1));
buffer<int, 1> BufB(range<1>(1));
detail::Requirement FakeReqA = getFakeRequirement(BufA);
detail::Requirement FakeReqB = getFakeRequirement(BufB);
detail::Requirement MockReqA = getMockRequirement(BufA);
detail::Requirement MockReqB = getMockRequirement(BufB);
detail::MemObjRecord *RecA =
TS.getOrInsertMemObjRecord(detail::getSyclObjImpl(MQueue), &FakeReqA);
MS.getOrInsertMemObjRecord(detail::getSyclObjImpl(MQueue), &MockReqA);

// Create 2 fake allocas, one of which will be cleaned up
detail::AllocaCommand *FakeAllocaA =
new detail::AllocaCommand(detail::getSyclObjImpl(MQueue), FakeReqA);
std::unique_ptr<detail::AllocaCommand> FakeAllocaB{
new detail::AllocaCommand(detail::getSyclObjImpl(MQueue), FakeReqB)};
RecA->MAllocaCommands.push_back(FakeAllocaA);
detail::AllocaCommand *MockAllocaA =
new detail::AllocaCommand(detail::getSyclObjImpl(MQueue), MockReqA);
std::unique_ptr<detail::AllocaCommand> MockAllocaB{
new detail::AllocaCommand(detail::getSyclObjImpl(MQueue), MockReqB)};
RecA->MAllocaCommands.push_back(MockAllocaA);

// Create a direct user of both allocas
std::unique_ptr<FakeCommand> FakeDirectUser{
new FakeCommand(detail::getSyclObjImpl(MQueue), FakeReqA)};
addEdge(FakeDirectUser.get(), FakeAllocaA, FakeAllocaA);
addEdge(FakeDirectUser.get(), FakeAllocaB.get(), FakeAllocaB.get());
std::unique_ptr<MockCommand> MockDirectUser{
new MockCommand(detail::getSyclObjImpl(MQueue), MockReqA)};
addEdge(MockDirectUser.get(), MockAllocaA, MockAllocaA);
addEdge(MockDirectUser.get(), MockAllocaB.get(), MockAllocaB.get());

// Create an indirect user of the soon-to-be deleted alloca
bool IndirectUserDeleted = false;
std::function<void()> Callback = [&]() { IndirectUserDeleted = true; };
FakeCommand *FakeIndirectUser = new FakeCommandWithCallback(
detail::getSyclObjImpl(MQueue), FakeReqA, Callback);
addEdge(FakeIndirectUser, FakeDirectUser.get(), FakeAllocaA);
MockCommand *MockIndirectUser = new MockCommandWithCallback(
detail::getSyclObjImpl(MQueue), MockReqA, Callback);
addEdge(MockIndirectUser, MockDirectUser.get(), MockAllocaA);

TS.cleanupCommandsForRecord(RecA);
TS.removeRecordForMemObj(detail::getSyclObjImpl(BufA).get());
MS.cleanupCommandsForRecord(RecA);
MS.removeRecordForMemObj(detail::getSyclObjImpl(BufA).get());

// Check that the direct user has been left with the second alloca
// as the only dependency, while the indirect user has been cleaned up.
ASSERT_EQ(FakeDirectUser->MUsers.size(), 0U);
ASSERT_EQ(FakeDirectUser->MDeps.size(), 1U);
EXPECT_EQ(FakeDirectUser->MDeps[0].MDepCommand, FakeAllocaB.get());
ASSERT_EQ(MockDirectUser->MUsers.size(), 0U);
ASSERT_EQ(MockDirectUser->MDeps.size(), 1U);
EXPECT_EQ(MockDirectUser->MDeps[0].MDepCommand, MockAllocaB.get());
EXPECT_TRUE(IndirectUserDeleted);
}
Loading