2 * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "core/RuntimeGraph.h"
18 #include "kernels/KernelBuilder.h"
23 namespace luci_interpreter
27 RuntimeGraph::RuntimeGraph(SimpleMemoryManager *memory_manager, CircleReader *circle_reader,
28 RuntimeModule *runtime_module, uint32_t subgraph_index)
29 : _memory_manager(memory_manager),
30 _tensor_to_data(std::unordered_map<const circle::Tensor *, uint8_t *>{}),
31 _runtime_module(runtime_module), _reader(circle_reader),
32 _inplace_op_indexes(std::unordered_set<const circle::Operator *>{}),
33 _subgraph_index(subgraph_index)
37 RuntimeGraph::~RuntimeGraph()
39 for (auto &idx_to_tensor : _tensor_to_data)
41 auto *data = idx_to_tensor.second;
43 _memory_manager->release_memory(data);
48 void RuntimeGraph::buildAllocDeallocPlan(bool dealloc_input)
50 assert(_reader->get_current_subgraph_index() == _subgraph_index);
52 using Lifetime = std::pair<int32_t, int32_t>;
53 std::map<const circle::Tensor *, Lifetime> lifetimes;
54 const size_t num_kernels = _reader->operators().size();
58 for (const auto input_ind : _reader->inputs())
60 const auto raw_tensor = _reader->tensors()[input_ind];
62 assert(lifetimes.count(raw_tensor) == 0);
63 lifetimes[raw_tensor] = Lifetime(-1, 0);
67 for (int32_t index = 0; index < num_kernels; ++index)
69 const auto kernel = _reader->operators().at(index);
70 assert(kernel != nullptr);
72 for (int32_t j = 0; j < kernel->inputs()->size(); ++j)
74 const auto input_index = kernel->inputs()->operator[](j);
76 if (input_index == -1)
79 const auto raw_tensor = _reader->tensors()[input_index];
81 // Pass constant tensors
82 if (Tensor::is_constant_tensor(_reader, raw_tensor))
85 if (lifetimes.count(raw_tensor) > 0)
87 if (_inplace_op_indexes.find(kernel) != _inplace_op_indexes.end())
88 lifetimes.at(raw_tensor).second = -1;
90 lifetimes.at(raw_tensor).second = index;
94 for (int32_t j = 0; j < kernel->outputs()->size(); ++j)
96 const auto output_index = kernel->outputs()->operator[](j);
97 const auto raw_tensor = _reader->tensors()[output_index];
99 assert(lifetimes.count(raw_tensor) == 0);
100 if (_inplace_op_indexes.find(kernel) != _inplace_op_indexes.end())
101 lifetimes[raw_tensor] = Lifetime(-1, index);
103 lifetimes[raw_tensor] = Lifetime(index, index);
107 for (const auto output_ind : _reader->outputs())
109 const auto raw_tensor = _reader->tensors()[output_ind];
111 if (lifetimes.count(raw_tensor) > 0)
112 lifetimes.at(raw_tensor).second = num_kernels;
115 _alloc_plan.assign(num_kernels, std::vector<const circle::Tensor *>());
116 _dealloc_plan.assign(num_kernels + 1, std::vector<const circle::Tensor *>());
117 for (const auto &item : lifetimes)
119 if (item.second.first != -1)
120 _alloc_plan[item.second.first].push_back(item.first);
121 if (item.second.second != -1)
122 _dealloc_plan[item.second.second].push_back(item.first);
127 void RuntimeGraph::allocate(size_t kernel_index)
129 assert(_reader->get_current_subgraph_index() == _subgraph_index);
130 assert(_is_valid && kernel_index < _alloc_plan.size());
131 for (const circle::Tensor *tensor : _alloc_plan[kernel_index])
133 if (_tensor_to_data.find(tensor) != _tensor_to_data.end())
135 auto *data = _tensor_to_data.at(tensor);
136 _memory_manager->release_memory(data);
138 auto *data = _memory_manager->allocate_memory(tensor);
139 _tensor_to_data[tensor] = data;
143 #ifndef DIS_DYN_SHAPES
144 void RuntimeGraph::addDynamicShapeTensor(const circle::Tensor *tensor,
145 luci_interpreter::RuntimeShape &&shapes)
147 assert(_reader->get_current_subgraph_index() == _subgraph_index);
148 _dynamic_tensor_shapes[tensor] = std::move(shapes);
151 luci_interpreter::RuntimeShape *RuntimeGraph::getDynamicShapeTensor(const circle::Tensor *tensor)
153 assert(_reader->get_current_subgraph_index() == _subgraph_index);
154 auto it = _dynamic_tensor_shapes.find(tensor);
156 return it == _dynamic_tensor_shapes.end() ? nullptr : &_dynamic_tensor_shapes[tensor];
159 void RuntimeGraph::removeDynamicShapeTensor(const circle::Tensor *tensor)
161 assert(_reader->get_current_subgraph_index() == _subgraph_index);
162 auto it = _dynamic_tensor_shapes.find(tensor);
164 assert(it != _dynamic_tensor_shapes.end());
166 _dynamic_tensor_shapes.erase(it);
169 #endif // DIS_DYN_SHAPES
171 void RuntimeGraph::deallocate(size_t kernel_index)
173 assert(_reader->get_current_subgraph_index() == _subgraph_index);
174 assert(_is_valid && kernel_index < _dealloc_plan.size());
175 for (const circle::Tensor *tensor : _dealloc_plan[kernel_index])
177 const auto it = _tensor_to_data.find(tensor);
178 assert(it != _tensor_to_data.end());
180 auto *data = _tensor_to_data.at(tensor);
181 _memory_manager->release_memory(data);
183 _tensor_to_data.erase(it);
187 void RuntimeGraph::resetTensorData(uint8_t *new_data, const circle::Tensor *tensor)
189 assert(_reader->get_current_subgraph_index() == _subgraph_index);
190 auto tensor_it = _tensor_to_data.find(tensor);
191 if (tensor_it != _tensor_to_data.end())
193 auto *data = _tensor_to_data.at(tensor);
194 _memory_manager->release_memory(data);
197 _tensor_to_data[tensor] = new_data;
200 void RuntimeGraph::resetOutputTensorsData()
202 assert(_reader->get_current_subgraph_index() == _subgraph_index);
203 const auto graph_inputs = _reader->inputs();
204 for (int i = 0; i < _reader->outputs().size(); ++i)
206 const auto tensor_index = _reader->outputs()[i];
207 assert(tensor_index != -1);
209 if (std::find(graph_inputs.begin(), graph_inputs.end(), tensor_index) != graph_inputs.end())
212 const auto tensor = _reader->tensors()[tensor_index];
213 assert(tensor != nullptr);
215 auto tensor_it = _tensor_to_data.find(tensor);
216 if (tensor_it != _tensor_to_data.end())
218 auto *data = _tensor_to_data.at(tensor);
219 _memory_manager->release_memory(data);
220 _tensor_to_data.erase(tensor_it);
225 uint8_t *RuntimeGraph::configureGraphInput(int32_t input_index)
227 assert(_reader->get_current_subgraph_index() == _subgraph_index);
229 const auto tensor_index = _reader->inputs()[input_index];
230 assert(tensor_index != -1);
231 const auto tensor = _reader->tensors()[tensor_index];
232 assert(tensor != nullptr);
234 auto *data = _memory_manager->allocate_memory(tensor);
235 configureGraphInput(input_index, data);
240 void RuntimeGraph::configureGraphInput(int32_t input_index, uint8_t *data)
242 assert(_reader->get_current_subgraph_index() == _subgraph_index);
243 resetOutputTensorsData();
245 const auto tensor_index = _reader->inputs()[input_index];
246 assert(tensor_index != -1);
247 const auto tensor = _reader->tensors()[tensor_index];
248 assert(tensor != nullptr);
250 if (_tensor_to_data.find(tensor) != _tensor_to_data.end())
252 auto *data_prev = _tensor_to_data.at(tensor);
253 if (data_prev != data)
254 _memory_manager->release_memory(data_prev);
256 _tensor_to_data[tensor] = data;
259 int32_t RuntimeGraph::getInputDataSizeByIndex(int32_t input_index)
261 assert(_reader->get_current_subgraph_index() == _subgraph_index);
262 const auto tensor_index = _reader->inputs()[input_index];
263 assert(tensor_index != -1);
264 const auto tensor = _reader->tensors()[tensor_index];
265 assert(tensor != nullptr);
267 return Tensor::num_elements(tensor) * size(Tensor::element_type(tensor));
270 int32_t RuntimeGraph::getNumOfInputTensors()
272 assert(_reader->get_current_subgraph_index() == _subgraph_index);
273 return _reader->inputs().size();
276 int32_t RuntimeGraph::getNumOfOutputTensors()
278 assert(_reader->get_current_subgraph_index() == _subgraph_index);
279 return _reader->outputs().size();
282 const circle::Tensor *RuntimeGraph::getInputTensorByIndex(int32_t input_index)
284 assert(_reader->get_current_subgraph_index() == _subgraph_index);
286 const auto tensor_index = _reader->inputs()[input_index];
287 const auto tensor = _reader->tensors()[tensor_index];
288 assert(tensor != nullptr);
292 const circle::Tensor *RuntimeGraph::getOutputTensorByIndex(int32_t input_index)
294 assert(_reader->get_current_subgraph_index() == _subgraph_index);
296 const auto tensor_index = _reader->outputs()[input_index];
297 const auto tensor = _reader->tensors()[tensor_index];
298 assert(tensor != nullptr);
302 int32_t RuntimeGraph::getOutputDataSizeByIndex(int32_t output_index)
304 assert(_reader->get_current_subgraph_index() == _subgraph_index);
306 const auto tensor_index = _reader->outputs()[output_index];
307 assert(tensor_index != -1);
308 const auto tensor = _reader->tensors()[tensor_index];
309 assert(tensor != nullptr);
311 return Tensor::num_elements(tensor) * size(Tensor::element_type(tensor));
314 uint8_t *RuntimeGraph::getOutputDataByIndex(int32_t output_index)
316 assert(_reader->get_current_subgraph_index() == _subgraph_index);
318 const auto tensor_index = _reader->outputs()[output_index];
319 assert(tensor_index != -1);
320 const auto tensor = _reader->tensors()[tensor_index];
321 assert(tensor != nullptr);
323 assert(_tensor_to_data.find(tensor) != _tensor_to_data.end());
325 return _tensor_to_data[tensor];
328 uint8_t *RuntimeGraph::getDataByTensor(const circle::Tensor *raw_tensor)
330 assert(_reader->get_current_subgraph_index() == _subgraph_index);
332 if (raw_tensor == nullptr)
335 if (_tensor_to_data.find(raw_tensor) == _tensor_to_data.end())
340 return _tensor_to_data.at(raw_tensor);
343 void RuntimeGraph::clearTensors() { _tensor_to_data.clear(); }
345 void RuntimeGraph::makeInplaceOperation(const circle::Tensor *removing_tensor,
346 const circle::Tensor *dst_tensor)
348 assert(_reader->get_current_subgraph_index() == _subgraph_index);
349 assert(removing_tensor != nullptr);
351 auto src_it = _tensor_to_data.find(removing_tensor);
353 if (src_it == _tensor_to_data.end())
356 auto *data = _tensor_to_data[removing_tensor];
358 _tensor_to_data.erase(src_it);
360 if (dst_tensor == nullptr)
366 assert(_tensor_to_data.find(dst_tensor) == _tensor_to_data.end() &&
367 "Failed makeInplaceOperation");
368 _tensor_to_data[dst_tensor] = data;
371 uint8_t *RuntimeGraph::getConstDataByTensor(const circle::Tensor *raw_tensor)
373 assert(_reader->get_current_subgraph_index() == _subgraph_index);
374 if (raw_tensor == nullptr)
377 auto const &buffer = wrap(_reader->buffers()[raw_tensor->buffer()]->data());
379 return const_cast<uint8_t *>(buffer.data());
382 const circle::Tensor *RuntimeGraph::getCircleTensorByIndex(int32_t index)
384 assert(_reader->get_current_subgraph_index() == _subgraph_index);
388 const auto raw_tensor = _reader->tensors()[index];
393 void RuntimeGraph::configure(bool dealloc_input)
397 for (uint32_t i = 0; i < _reader->operators().size(); ++i)
399 const auto op = _reader->operators().at(i);
400 assert(op != nullptr);
402 const auto opcode = _reader->builtin_code(op);
404 kernel_configure.configure_kernel(op, opcode, this);
408 buildAllocDeallocPlan(dealloc_input);
413 void RuntimeGraph::setDataToTensor(const circle::Tensor *tensor, uint8_t *data)
415 _tensor_to_data[tensor] = data;
418 void RuntimeGraph::execute()
425 const auto operators_size = _reader->operators().size();
426 const auto operators = _reader->operators();
428 for (uint32_t i = 0; i < operators_size; ++i)
430 const auto op = operators.at(i);
431 assert(op != nullptr);
433 const auto opcode = _reader->builtin_code(op);
437 kernel_executor.execute_kernel(op, opcode, this);
443 } // namespace luci_interpreter