DPC++ Runtime
Runtime libraries for oneAPI DPC++
leaves_collection.cpp
Go to the documentation of this file.
1 //==---- leaves_collection.hpp - Container for leaves of execution graph ---==//
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 
11 
12 #include <algorithm>
13 
15 namespace sycl {
16 namespace detail {
17 
18 // TODO merge with GraphBuilder's version of doOverlap (see graph_builder.cpp).
19 static inline bool doOverlap(const Requirement *LHS, const Requirement *RHS) {
20  size_t LHSStart = LHS->MOffsetInBytes;
21  size_t LHSEnd = LHSStart + LHS->MAccessRange.size() * LHS->MElemSize;
22 
23  size_t RHSStart = RHS->MOffsetInBytes;
24  size_t RHSEnd = RHSStart + RHS->MAccessRange.size() * RHS->MElemSize;
25 
26  if (LHSStart < RHSStart) {
27  return (RHSStart < LHSEnd) && (LHSEnd <= RHSEnd);
28  } else {
29  return (LHSStart < RHSEnd) && (RHSEnd <= LHSEnd);
30  }
31 }
32 
33 static inline bool isHostAccessorCmd(Command *Cmd) {
34  return Cmd->getType() == Command::EMPTY_TASK &&
35  Cmd->MBlockReason == Command::BlockReason::HostAccessor;
36 }
37 
38 size_t LeavesCollection::remove(value_type Cmd) {
39  if (!isHostAccessorCmd(Cmd)) {
40  auto NewEnd =
41  std::remove(MGenericCommands.begin(), MGenericCommands.end(), Cmd);
42  size_t RemovedCount = std::distance(NewEnd, MGenericCommands.end());
43  MGenericCommands.erase(NewEnd, MGenericCommands.end());
44 
45  return RemovedCount;
46  }
47 
48  // host accessor commands part
49  return eraseHostAccessorCommand(static_cast<EmptyCommand *>(Cmd));
50 }
51 
52 bool LeavesCollection::push_back(value_type Cmd, EnqueueListT &ToEnqueue) {
53  bool Result = false;
54 
55  if (isHostAccessorCmd(Cmd))
56  Result =
57  addHostAccessorCommand(static_cast<EmptyCommand *>(Cmd), ToEnqueue);
58  else
59  Result = addGenericCommand(Cmd, ToEnqueue);
60 
61  return Result;
62 }
63 
64 std::vector<LeavesCollection::value_type> LeavesCollection::toVector() const {
65  std::vector<value_type> Result;
66  Result.reserve(MGenericCommands.size() + MHostAccessorCommands.size());
67 
68  Result.insert(Result.end(), MGenericCommands.begin(), MGenericCommands.end());
69 
70  for (EmptyCommand *Cmd : MHostAccessorCommands)
71  Result.push_back(Cmd);
72 
73  return Result;
74 }
75 
76 bool LeavesCollection::addHostAccessorCommand(EmptyCommand *Cmd,
77  EnqueueListT &ToEnqueue) {
78  // 1. find the oldest command with doOverlap() = true amongst the List
79  // => OldCmd
80  HostAccessorCommandSingleXRefT OldCmdIt;
81 
82  // HACK we believe here that read accessors never overlap as it doesn't add
83  // any real dependency (e.g. data copy to device) except for blocking.
85  OldCmdIt = MHostAccessorCommands.end();
86  else
87  OldCmdIt = std::find_if(
88  MHostAccessorCommands.begin(), MHostAccessorCommands.end(),
89  [&](const EmptyCommand *Test) -> bool {
90  return doOverlap(Test->getRequirement(), Cmd->getRequirement());
91  });
92 
93  // FIXME this 'if' is a workaround for duplicate leaves, remove once fixed
94  if (OldCmdIt != MHostAccessorCommands.end() && *OldCmdIt == Cmd)
95  return false;
96 
97  // 2.1 If OldCmd != null:
98  // Put a dependency in the same way as we would for generic commands
99  // when circular buffer is full.
100  if (OldCmdIt != MHostAccessorCommands.end()) {
101  // allocate dependency
102  MAllocateDependency(Cmd, *OldCmdIt, MRecord, ToEnqueue);
103 
104  // erase the old cmd as it's tracked via dependency now
105  eraseHostAccessorCommand(static_cast<EmptyCommand *>(*OldCmdIt));
106  }
107 
108  // 2.2 If OldCmd == null:
109  // Put cmd to the List
110  insertHostAccessorCommand(Cmd);
111  return true;
112 }
113 
114 bool LeavesCollection::addGenericCommand(Command *Cmd,
115  EnqueueListT &ToEnqueue) {
116  if (MGenericCommands.full()) {
117  Command *OldLeaf = MGenericCommands.front();
118 
119  // FIXME this 'if' is a workaround for duplicate leaves, remove once fixed
120  if (OldLeaf == Cmd)
121  return false;
122 
123  MAllocateDependency(Cmd, OldLeaf, MRecord, ToEnqueue);
124  }
125 
126  MGenericCommands.push_back(Cmd);
127 
128  return true;
129 }
130 
131 void LeavesCollection::insertHostAccessorCommand(EmptyCommand *Cmd) {
132  MHostAccessorCommandsXRef[Cmd] =
133  MHostAccessorCommands.insert(MHostAccessorCommands.end(), Cmd);
134 }
135 
136 size_t LeavesCollection::eraseHostAccessorCommand(EmptyCommand *Cmd) {
137  auto XRefIt = MHostAccessorCommandsXRef.find(Cmd);
138 
139  if (XRefIt == MHostAccessorCommandsXRef.end())
140  return 0;
141 
142  MHostAccessorCommands.erase(XRefIt->second);
143  MHostAccessorCommandsXRef.erase(XRefIt);
144  return 1;
145 }
146 
147 } // namespace detail
148 } // namespace sycl
149 } // __SYCL_INLINE_NAMESPACE(cl)
cl::sycl::detail::isHostAccessorCmd
static bool isHostAccessorCmd(Command *Cmd)
Definition: leaves_collection.cpp:33
cl::sycl::distance
float distance(T p0, T p1) __NOEXC
Definition: builtins.hpp:1011
cl::sycl::access::mode::read
@ read
leaves_collection.hpp
sycl
Definition: invoke_simd.hpp:68
scheduler.hpp
cl::sycl::range::size
size_t size() const
Definition: range.hpp:50
cl::sycl::detail::AccessorImplHost::MElemSize
unsigned int MElemSize
Definition: accessor_impl.hpp:115
cl::sycl::detail::LeavesCollection::EnqueueListT
std::vector< Command * > EnqueueListT
Definition: leaves_collection.hpp:42
cl::sycl::detail::AccessorImplHost
Definition: accessor_impl.hpp:74
cl::sycl::detail::AccessorImplHost::MOffsetInBytes
unsigned int MOffsetInBytes
Definition: accessor_impl.hpp:116
cl::sycl::detail::Command::getType
CommandType getType() const
Definition: commands.hpp:127
cl::sycl::detail::doOverlap
static bool doOverlap(const Requirement *LHS, const Requirement *RHS)
Definition: leaves_collection.cpp:19
cl::sycl::detail::Command
The Command class represents some action that needs to be performed on one or more memory objects.
Definition: commands.hpp:95
cl
We provide new interfaces for matrix muliply in this patch:
Definition: access.hpp:13
cl::sycl::detail::AccessorImplHost::MAccessMode
access::mode MAccessMode
Definition: accessor_impl.hpp:110
cl::sycl::detail::Command::MBlockReason
BlockReason MBlockReason
Definition: commands.hpp:276
cl::sycl::detail::EmptyCommand::getRequirement
const Requirement * getRequirement() const final
Definition: commands.hpp:328
cl::sycl::detail::AccessorImplHost::MAccessRange
range< 3 > MAccessRange
Definition: accessor_impl.hpp:107
cl::sycl::detail::EmptyCommand
The empty command does nothing during enqueue.
Definition: commands.hpp:323
__SYCL_INLINE_NAMESPACE
#define __SYCL_INLINE_NAMESPACE(X)
Definition: defines_elementary.hpp:12