Skip to content

Commit f6ecdbf

Browse files
romanovvladvladimirlaz
authored andcommitted
[SYCL] Introduction of new scheduler.
This patch introduces new scheduler which is enabled when SCHEDULER_20 macro is set(set by default). The new scheduler is based on accessor rather on buffer, so it will support images. Also now there are two commands that implements moving memory to other contexts instead of one - alloca memory and memcpy. There is new command - release memory which will be ran during the sycl::buffer or sycl::image object destruction and releases memory instances for the memory object. Signed-off-by: Vlad Romanov <[email protected]>
1 parent 2385839 commit f6ecdbf

28 files changed

+1465
-442
lines changed

sycl/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,12 @@ add_library("${SYCLLibrary}" SHARED
138138
"${sourceRootPath}/detail/os_util.cpp"
139139
"${sourceRootPath}/detail/sampler_impl.cpp"
140140
"${sourceRootPath}/detail/scheduler/commands.cpp"
141+
"${sourceRootPath}/detail/scheduler/commands2.cpp"
141142
"${sourceRootPath}/detail/scheduler/printers.cpp"
142143
"${sourceRootPath}/detail/scheduler/scheduler.cpp"
144+
"${sourceRootPath}/detail/scheduler/graph_processor.cpp"
145+
"${sourceRootPath}/detail/scheduler/graph_builder.cpp"
146+
"${sourceRootPath}/detail/scheduler/scheduler2.cpp"
143147
"${sourceRootPath}/detail/util.cpp"
144148
"${sourceRootPath}/context.cpp"
145149
"${sourceRootPath}/device.cpp"

sycl/include/CL/sycl.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88

99
#pragma once
1010

11+
#ifndef SCHEDULER_10
12+
#define SCHEDULER_20
13+
#endif
14+
1115
#include <CL/sycl/accessor.hpp>
1216
#include <CL/sycl/atomic.hpp>
1317
#include <CL/sycl/buffer.hpp>
@@ -37,6 +41,7 @@
3741
#include <CL/sycl/types.hpp>
3842
#include <CL/sycl/version.hpp>
3943

44+
#ifndef SCHEDULER_20
4045
// Do not include RT only function implementations for device code as it leads
4146
// to problem. Should be finally fixed when we introduce library.
4247
#ifndef __SYCL_DEVICE_ONLY__
@@ -46,3 +51,4 @@
4651
#include <CL/sycl/detail/scheduler/printers.cpp>
4752
#include <CL/sycl/detail/scheduler/scheduler.cpp>
4853
#endif //__SYCL_DEVICE_ONLY__
54+
#endif // !SCHEDULER_20

sycl/include/CL/sycl/detail/event_impl.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,16 @@ class event_impl {
5959
// with the cl_event object stored in this class
6060
void setContextImpl(const ContextImplPtr &Context);
6161

62+
void *getCommand() { return m_Command; }
63+
64+
void setCommand(void *Command) { m_Command = Command; }
65+
6266
private:
6367
cl_event m_Event = nullptr;
6468
ContextImplPtr m_Context;
6569
bool m_OpenCLInterop = false;
6670
bool m_HostEvent = true;
71+
void *m_Command = nullptr;
6772
};
6873

6974
} // namespace detail

sycl/include/CL/sycl/detail/kernel_impl.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ class kernel_impl {
112112
Device.get(), Value);
113113
}
114114

115+
cl_kernel &getHandleRef() { return ClKernel; }
116+
115117
private:
116118
cl_kernel ClKernel;
117119
context Context;
Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
//==-------------- commands.hpp - SYCL standard header file ----------------==//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#pragma once
10+
11+
#include <atomic>
12+
#include <memory>
13+
#include <vector>
14+
15+
#include <CL/sycl/detail/accessor_impl.hpp>
16+
#include <CL/sycl/detail/cg.hpp>
17+
18+
namespace cl {
19+
namespace sycl {
20+
namespace detail {
21+
22+
class queue_impl;
23+
class event_impl;
24+
class context_impl;
25+
26+
using QueueImplPtr = std::shared_ptr<detail::queue_impl>;
27+
using EventImplPtr = std::shared_ptr<detail::event_impl>;
28+
using ContextImplPtr = std::shared_ptr<detail::context_impl>;
29+
30+
class Command;
31+
class AllocaCommand;
32+
class ReleaseCommand;
33+
34+
// DepDesc represents dependency between two commands
35+
struct DepDesc {
36+
DepDesc(Command *DepCommand, Requirement *Req, AllocaCommand *AllocaCmd)
37+
: MDepCommand(DepCommand), MReq(Req), MAllocaCmd(AllocaCmd) {}
38+
39+
friend bool operator<(const DepDesc &Lhs, const DepDesc &Rhs) {
40+
return std::tie(Lhs.MReq, Lhs.MDepCommand) <
41+
std::tie(Rhs.MReq, Rhs.MDepCommand);
42+
}
43+
44+
// The actual dependency command.
45+
Command *MDepCommand = nullptr;
46+
// Requirement for the dependency.
47+
Requirement *MReq = nullptr;
48+
// Allocation command for the memory object we have requirement for.
49+
// Used to simplify searching for memory handle.
50+
AllocaCommand *MAllocaCmd = nullptr;
51+
};
52+
53+
// The Command represents some action that needs to be performed on one or more
54+
// memory objects. The command has vector of Depdesc objects that represent
55+
// dependencies of the command. It has vector of pointer to commands that depend
56+
// on the command. It has pointer to sycl::queue object. And has event that is
57+
// associated with the command.
58+
class Command {
59+
public:
60+
enum CommandType {
61+
RUN_CG,
62+
COPY_MEMORY,
63+
ALLOCA,
64+
RELEASE,
65+
MAP_MEM_OBJ,
66+
UNMAP_MEM_OBJ
67+
};
68+
69+
Command(CommandType Type, QueueImplPtr Queue);
70+
71+
void addDep(DepDesc NewDep) {
72+
if (NewDep.MDepCommand)
73+
MDepsEvents.push_back(NewDep.MDepCommand->getEvent());
74+
MDeps.push_back(NewDep);
75+
}
76+
77+
void addDep(EventImplPtr Event) { MDepsEvents.push_back(std::move(Event)); }
78+
79+
void addUser(Command *NewUser) { MUsers.push_back(NewUser); }
80+
81+
// Return type of the command, e.g. Allocate, MemoryCopy.
82+
CommandType getType() const { return MType; }
83+
84+
// The method checks if the command is enqueued, call enqueueImp if not and
85+
// returns CL_SUCCESS on success.
86+
cl_int enqueue();
87+
88+
bool isFinished();
89+
90+
bool isEnqueued() const { return MEnqueued; }
91+
92+
std::shared_ptr<queue_impl> getQueue() const { return MQueue; }
93+
94+
std::shared_ptr<event_impl> getEvent() const { return MEvent; }
95+
96+
protected:
97+
EventImplPtr MEvent;
98+
QueueImplPtr MQueue;
99+
std::vector<EventImplPtr> MDepsEvents;
100+
101+
std::vector<cl_event> prepareEvents(ContextImplPtr Context);
102+
103+
// Private interface. Derived classes should implement this method.
104+
virtual cl_int enqueueImp() = 0;
105+
106+
public:
107+
std::vector<DepDesc> MDeps;
108+
std::vector<Command *> MUsers;
109+
110+
private:
111+
CommandType MType;
112+
std::atomic<bool> MEnqueued;
113+
};
114+
115+
// The command enqueues release instance of memory allocated on Host or
116+
// underlying framework.
117+
class ReleaseCommand : public Command {
118+
public:
119+
ReleaseCommand(QueueImplPtr Queue, AllocaCommand *AllocaCmd)
120+
: Command(CommandType::RELEASE, std::move(Queue)), MAllocaCmd(AllocaCmd) {
121+
}
122+
private:
123+
cl_int enqueueImp() override;
124+
125+
AllocaCommand *MAllocaCmd = nullptr;
126+
};
127+
128+
// The command enqueues allocation of instance of memory object on Host or
129+
// underlying framework.
130+
class AllocaCommand : public Command {
131+
public:
132+
AllocaCommand(QueueImplPtr Queue, Requirement Req,
133+
bool InitFromUserData = true)
134+
: Command(CommandType::ALLOCA, Queue), MReleaseCmd(Queue, this),
135+
MInitFromUserData(InitFromUserData), MReq(std::move(Req)) {
136+
addDep(DepDesc(nullptr, &MReq, this));
137+
}
138+
ReleaseCommand *getReleaseCmd() { return &MReleaseCmd; }
139+
140+
SYCLMemObjT *getSYCLMemObj() const { return MReq.MSYCLMemObj; }
141+
142+
void *getMemAllocation() const { return MMemAllocation; }
143+
144+
Requirement *getAllocationReq() { return &MReq; }
145+
146+
private:
147+
cl_int enqueueImp() override;
148+
149+
ReleaseCommand MReleaseCmd;
150+
void *MMemAllocation = nullptr;
151+
bool MInitFromUserData = false;
152+
Requirement MReq;
153+
};
154+
155+
class MapMemObject : public Command {
156+
public:
157+
MapMemObject(Requirement SrcReq, AllocaCommand *SrcAlloca,
158+
Requirement *DstAcc, QueueImplPtr Queue);
159+
160+
Requirement MSrcReq;
161+
AllocaCommand *MSrcAlloca = nullptr;
162+
Requirement *MDstAcc = nullptr;
163+
Requirement MDstReq;
164+
165+
private:
166+
cl_int enqueueImp() override;
167+
};
168+
169+
class UnMapMemObject : public Command {
170+
public:
171+
UnMapMemObject(Requirement SrcReq, AllocaCommand *SrcAlloca,
172+
Requirement *DstAcc, QueueImplPtr Queue);
173+
174+
private:
175+
cl_int enqueueImp() override;
176+
177+
Requirement MSrcReq;
178+
AllocaCommand *MSrcAlloca = nullptr;
179+
Requirement *MDstAcc = nullptr;
180+
};
181+
182+
// The command enqueues memory copy between two instances of memory object.
183+
class MemCpyCommand : public Command {
184+
public:
185+
MemCpyCommand(Requirement SrcReq, AllocaCommand *SrcAlloca,
186+
Requirement DstReq, AllocaCommand *DstAlloca,
187+
QueueImplPtr SrcQueue, QueueImplPtr DstQueue);
188+
189+
QueueImplPtr MSrcQueue;
190+
Requirement MSrcReq;
191+
AllocaCommand *MSrcAlloca = nullptr;
192+
Requirement MDstReq;
193+
AllocaCommand *MDstAlloca = nullptr;
194+
Requirement *MAccToUpdate = nullptr;
195+
196+
void setAccessorToUpdate(Requirement *AccToUpdate) {
197+
MAccToUpdate = AccToUpdate;
198+
}
199+
200+
private:
201+
cl_int enqueueImp() override;
202+
};
203+
204+
// The command enqueues memory copy between two instances of memory object.
205+
class MemCpyCommandHost : public Command {
206+
public:
207+
MemCpyCommandHost(Requirement SrcReq, AllocaCommand *SrcAlloca,
208+
Requirement *DstAcc, QueueImplPtr SrcQueue,
209+
QueueImplPtr DstQueue);
210+
211+
QueueImplPtr MSrcQueue;
212+
Requirement MSrcReq;
213+
AllocaCommand *MSrcAlloca = nullptr;
214+
Requirement MDstReq;
215+
Requirement *MDstAcc = nullptr;
216+
217+
private:
218+
cl_int enqueueImp() override;
219+
};
220+
221+
// The command enqueues execution of kernel or explicit memory operation.
222+
class ExecCGCommand : public Command {
223+
public:
224+
ExecCGCommand(std::unique_ptr<detail::CG> CommandGroup, QueueImplPtr Queue)
225+
: Command(CommandType::RUN_CG, std::move(Queue)),
226+
MCommandGroup(std::move(CommandGroup)) {}
227+
228+
private:
229+
// Implementation of enqueueing of ExecCGCommand.
230+
cl_int enqueueImp() override;
231+
232+
AllocaCommand *getAllocaForReq(Requirement *Req);
233+
234+
std::unique_ptr<detail::CG> MCommandGroup;
235+
};
236+
237+
} // namespace detail
238+
} // namespace sycl
239+
} // namespace cl

sycl/include/CL/sycl/detail/scheduler/scheduler.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#ifdef SCHEDULER_20
10+
11+
#include <CL/sycl/detail/scheduler/scheduler.hpp>
12+
13+
#else
14+
915
#pragma once
1016

1117
#include <CL/sycl/context.hpp>
@@ -240,3 +246,4 @@ class Scheduler {
240246
} // namespace simple_scheduler
241247
} // namespace sycl
242248
} // namespace cl
249+
#endif // SCHEDULER_20

0 commit comments

Comments
 (0)