1 /**
2 * Copyright (c) Glow Contributors. See CONTRIBUTORS file.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #ifndef GLOW_BACKENDS_BACKENDUTILS_H
17 #define GLOW_BACKENDS_BACKENDUTILS_H
18
19 #include "glow/CodeGen/MemoryAllocator.h"
20 #include "glow/IR/IR.h"
21
22 #include <map>
23
24 namespace glow {
25 namespace runtime {
26
27 /// An enum to indicate what type each symbol in the bundle is.
28 enum class SymbolCategory {
29 Activation,
30 Placeholder,
31 Constant,
32 PlaceholderTensorView,
33 ConstantTensorView
34 };
35
36 /// Contains information for initialization and handling of symbol at runtime.
37 struct RuntimeSymbolInfo {
38 /// The size in bytes.
39 size_t size{0};
40 /// Offset in bytes from the base address.
41 size_t offset{0};
42 /// Type of symbol.
43 Type type;
44 /// Is the symbol an input for the function.
45 bool input{true};
46 /// Is the symbol an output for the function.
47 bool output{true};
48 /// Indicates what category the symbol is.
49 SymbolCategory symbolCategory;
50 };
51
52 using SymbolTableTy = std::map<std::string, RuntimeSymbolInfo>;
53
54 /// Contains the information needed to be passed forward from compile time to
55 /// runtime. In order to allocate and initialize memory.
56 class RuntimeBundle {
57 /// Map from symbol name to a RuntimeSymbolInfo.
58 SymbolTableTy symbolTable_;
59 /// Pointer to memory containing the weights for execution.
60 uint8_t *constants_{nullptr};
61 /// Amount of memory needed for weights.
62 size_t constantWeightVarsMemSize_{0};
63 /// Amount of memory needed for mutable vars.
64 size_t mutableWeightVarsMemSize_{0};
65 /// Amount of memory needed for activations.
66 size_t activationsMemSize_{0};
67 /// True if the RuntimeBundle is valid, false if not.
68 bool isValid_{false};
69
70 public:
71 /// Get Constant Weights memory size.
getConstantWeightSize()72 size_t getConstantWeightSize() const { return constantWeightVarsMemSize_; }
73 /// Get Mutable Weights memory size.
getMutableWeightSize()74 size_t getMutableWeightSize() const { return mutableWeightVarsMemSize_; }
75 /// Get Activations Weights memory size.
getActivationsSize()76 size_t getActivationsSize() const { return activationsMemSize_; }
77 /// Get pointer to memory block of constants.
getConstants()78 uint8_t *getConstants() const { return constants_; }
79 /// Set pointer to memory block of constants.
setConstants(uint8_t * constants)80 void setConstants(uint8_t *constants) { constants_ = constants; }
81 /// Helper function, gets offset of \p v.
82 size_t getValueOffset(const Named *v) const;
83 /// Helper function, gets symbol info for \p v.
84 const RuntimeSymbolInfo &getSymbolInfo(const Named *v) const;
85 /// Get a const reference to the symbol table.
getSymbolTable()86 const SymbolTableTy &getSymbolTable() const { return symbolTable_; }
87 /// At compile time condense constants to a single block of memory.
88 /// This allows the graph to go away after compile time.
89 /// Allocates a block of memory of size \p constantMaxSize then walks the
90 /// given function \p F and and copies weights to their address as specified
91 /// by offsets contained in symbolTable_.
92 void collectConstants(const IRFunction *F);
93 void collectConstants(const Module *M);
94 /// Free constants.
95 void freeConstants();
96
97 /// Sets the input and output flags for each symbol in the symbolBundle.
98 void setInputsandOutputs();
99
100 /// Computes offsets and total allocation for Constants, Placeholders, and
101 /// Activations to build runtime symbol table. Returns RuntimeBundle.
102 static runtime::RuntimeBundle create(const IRFunction &F,
103 MemoryAllocator &constantAllocator,
104 MemoryAllocator &placeholderAllocator,
105 MemoryAllocator &activationsAllocator);
106
107 /// Computes offsets and total allocation for Constants, Placeholders, and
108 /// Activations to build runtime symbol table. \returns RuntimeBundle.
109 /// Constants and Placeholders are taken from \p F, and all Activations
110 /// required by each function in \p funcs are placed into the same
111 /// RuntimeBundle.
112 static runtime::RuntimeBundle
113 create(const Function &F, const std::vector<const IRFunction *> &funcs);
114
115 /// Computes offsets and total allocations for Constants, Placeholders, and
116 /// Activations to build runtime symbol table. \returns RuntimeBundle. Uses a
117 /// single allocator \p allocator and allocates all buffers contiguously in
118 /// the same block.
119 static runtime::RuntimeBundle create(const IRFunction &F,
120 MemoryAllocator &allocator);
121
122 /// Build a runtime symbol table from a Function. Computes Constant and
123 /// Placeholder sizes, but not Activations, since Functions are unserialized.
124 /// Only use this method to generate bundles for backends that do not use
125 /// Glow's IR.
126 static runtime::RuntimeBundle create(const Function &F);
127
128 /// Deleted default constructor. A properly constructed RuntimeBundle is
129 /// necessary for correct execution using the HostManager.
130 RuntimeBundle() = delete;
131
132 // Constructor.
RuntimeBundle(SymbolTableTy & symbolTable,size_t constWeight,size_t mutableWeight,size_t activations)133 RuntimeBundle(SymbolTableTy &symbolTable, size_t constWeight,
134 size_t mutableWeight, size_t activations)
135 : symbolTable_(std::move(symbolTable)), constants_(nullptr),
136 constantWeightVarsMemSize_(constWeight),
137 mutableWeightVarsMemSize_(mutableWeight),
138 activationsMemSize_(activations), isValid_(true) {}
139
140 // Explicit copy constructor and deleted assignment operator. A RuntimeBundle
141 // should be moved. It should only be copied if absolutely necessary and never
142 // implicitly.
143 explicit RuntimeBundle(const RuntimeBundle &) = default;
144 RuntimeBundle &operator=(const RuntimeBundle &) = delete;
145
146 // Move constructor and assignment operator.
147 RuntimeBundle(RuntimeBundle &&rhs);
148 RuntimeBundle &operator=(RuntimeBundle &&rhs);
149 };
150 } // namespace runtime
151
152 /// Generates a struct named has_\p METHOD_NAME that looks for a method called
153 /// \p METHOD_NAME inside of ClassName with return type ReturnType.
154 #define CLASS_CONTAINS_METHOD(METHOD_NAME) \
155 template <typename ClassName, typename ReturnType> \
156 struct has_##METHOD_NAME { \
157 private: \
158 template <typename T> \
159 static constexpr auto check(T *) -> \
160 typename std::is_same<decltype(std::declval<T>().METHOD_NAME()), \
161 ReturnType>::type; \
162 template <typename> static constexpr std::false_type check(...); \
163 typedef decltype(check<ClassName>(0)) type; \
164 \
165 public: \
166 static constexpr bool value = type::value; \
167 };
168
169 /// Use template meta-programming to check if typename ClassName contains
170 /// getFusedActivation() method. Below generates a struct named
171 /// has_getFusedActivation that looks for said method.
172 CLASS_CONTAINS_METHOD(getFusedActivation)
173
174 /// If \p PH is an output placeholder in the IRFunction \p F,
175 /// \returns true.
176 /// This is determined by checking if the PH has weights which are referenced by
177 /// other Instructions as OperandKind::InOut or OperandKind::Out.
178 bool isOutput(const Placeholder *PH, const IRFunction &F);
179
180 /// If \p PH is an input placeholder in the IRFunction \p F,
181 /// \returns true.
182 /// This is determined by checking if the PH is always used as an @in parameter
183 /// by the current function.
184 bool isInput(const Placeholder *PH, const IRFunction &F);
185
186 /// If \p N does not have fused activation \returns true.
187 template <typename T,
188 std::enable_if_t<!has_getFusedActivation<T, FusedActivation>::value,
189 int> = 0>
checkNoFusion(const T & N)190 bool checkNoFusion(const T &N) {
191 (void)N;
192 return true;
193 }
194
195 /// If \p N does not have fused activation \returns true.
196 template <typename T,
197 std::enable_if_t<has_getFusedActivation<T, FusedActivation>::value,
198 int> = 0>
checkNoFusion(const T & N)199 bool checkNoFusion(const T &N) {
200 if (N.getFusedActivation() != FusedActivation::NONE) {
201 report("Glow backend does not support fused Activations for: " +
202 std::string(N.getKindName()));
203 return false;
204 }
205 return true;
206 }
207
208 /// If \p N does not have fused activation \returns true.
209 bool checkNoFusionForNode(const Node &N);
210
211 /// If \p I does not have fused activation \returns true.
212 bool checkNoFusionForInstr(const Instruction &I);
213
214 /// Contains information for placeholder during allocation.
215 struct PlaceholderInputOutputInfo {
216 /// The placeholder address.
217 const Placeholder *addr;
218 /// Is the placeholder an input for the function.
219 bool isInput;
220 /// Is the placeholder an onput for the function.
221 bool isOutput;
222 };
223
224 using ContiguousPlaceholders = std::vector<PlaceholderInputOutputInfo>;
225
226 /// Convert placeholders to be ordered as input|inputOutput|output|neither.
227 /// Packed into {Placeholder *, isInput, isOutput} as
228 /// PlaceholderInputOutputInfo. FUN could be Function or IRFunction. ARR could
229 /// be std::list<Placeholder *> or std::vector<const Placeholder *>
230 template <typename FUN, typename ARR>
231 ContiguousPlaceholders getContiguousPlaceHolder(const ARR &holders,
232 const FUN &F);
233
234 /// \returns true if \p V is capable of handling a partial tensor as input.
235 bool allowsPartialInput(const Placeholder *V, const Function *F);
236
237 /// \returns true if \p V requires last-element padding
238 bool requiresPadding(const Placeholder *V, const Function *F);
239
240 /// \returns true if \p V is used in \p F; false otherwise.
241 bool usedInFunction(const Placeholder *V, const Function *F);
242
243 } // end namespace glow
244 #endif // GLOW_BACKENDS_BACKENDUTILS_H
245