Imported Upstream version 1.25.0
[platform/core/ml/nnfw.git] / onert-micro / luci-interpreter / src / core / RuntimeGraph.cpp
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
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
17 #include "core/RuntimeGraph.h"
18 #include "kernels/KernelBuilder.h"
19
20 #include <algorithm>
21 #include <map>
22
23 namespace luci_interpreter
24 {
25
26 // IBaseRuntimeGraph
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)
34 {
35 }
36
37 RuntimeGraph::~RuntimeGraph()
38 {
39   for (auto &idx_to_tensor : _tensor_to_data)
40   {
41     auto *data = idx_to_tensor.second;
42
43     _memory_manager->release_memory(data);
44   }
45 }
46
47 // TODO: modify this
48 void RuntimeGraph::buildAllocDeallocPlan(bool dealloc_input)
49 {
50   assert(_reader->get_current_subgraph_index() == _subgraph_index);
51   invalidate();
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();
55
56   if (dealloc_input)
57   {
58     for (const auto input_ind : _reader->inputs())
59     {
60       const auto raw_tensor = _reader->tensors()[input_ind];
61
62       assert(lifetimes.count(raw_tensor) == 0);
63       lifetimes[raw_tensor] = Lifetime(-1, 0);
64     }
65   }
66
67   for (int32_t index = 0; index < num_kernels; ++index)
68   {
69     const auto kernel = _reader->operators().at(index);
70     assert(kernel != nullptr);
71
72     for (int32_t j = 0; j < kernel->inputs()->size(); ++j)
73     {
74       const auto input_index = kernel->inputs()->operator[](j);
75
76       if (input_index == -1)
77         continue;
78
79       const auto raw_tensor = _reader->tensors()[input_index];
80
81       // Pass constant tensors
82       if (Tensor::is_constant_tensor(_reader, raw_tensor))
83         continue;
84
85       if (lifetimes.count(raw_tensor) > 0)
86       {
87         if (_inplace_op_indexes.find(kernel) != _inplace_op_indexes.end())
88           lifetimes.at(raw_tensor).second = -1;
89         else
90           lifetimes.at(raw_tensor).second = index;
91       }
92     }
93
94     for (int32_t j = 0; j < kernel->outputs()->size(); ++j)
95     {
96       const auto output_index = kernel->outputs()->operator[](j);
97       const auto raw_tensor = _reader->tensors()[output_index];
98
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);
102       else
103         lifetimes[raw_tensor] = Lifetime(index, index);
104     }
105   }
106
107   for (const auto output_ind : _reader->outputs())
108   {
109     const auto raw_tensor = _reader->tensors()[output_ind];
110
111     if (lifetimes.count(raw_tensor) > 0)
112       lifetimes.at(raw_tensor).second = num_kernels;
113   }
114
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)
118   {
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);
123   }
124   _is_valid = true;
125 }
126
127 void RuntimeGraph::allocate(size_t kernel_index)
128 {
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])
132   {
133     if (_tensor_to_data.find(tensor) != _tensor_to_data.end())
134     {
135       auto *data = _tensor_to_data.at(tensor);
136       _memory_manager->release_memory(data);
137     }
138     auto *data = _memory_manager->allocate_memory(tensor);
139     _tensor_to_data[tensor] = data;
140   }
141 }
142
143 #ifndef DIS_DYN_SHAPES
144 void RuntimeGraph::addDynamicShapeTensor(const circle::Tensor *tensor,
145                                          luci_interpreter::RuntimeShape &&shapes)
146 {
147   assert(_reader->get_current_subgraph_index() == _subgraph_index);
148   _dynamic_tensor_shapes[tensor] = std::move(shapes);
149 }
150
151 luci_interpreter::RuntimeShape *RuntimeGraph::getDynamicShapeTensor(const circle::Tensor *tensor)
152 {
153   assert(_reader->get_current_subgraph_index() == _subgraph_index);
154   auto it = _dynamic_tensor_shapes.find(tensor);
155
156   return it == _dynamic_tensor_shapes.end() ? nullptr : &_dynamic_tensor_shapes[tensor];
157 }
158
159 void RuntimeGraph::removeDynamicShapeTensor(const circle::Tensor *tensor)
160 {
161   assert(_reader->get_current_subgraph_index() == _subgraph_index);
162   auto it = _dynamic_tensor_shapes.find(tensor);
163
164   assert(it != _dynamic_tensor_shapes.end());
165
166   _dynamic_tensor_shapes.erase(it);
167 }
168
169 #endif // DIS_DYN_SHAPES
170
171 void RuntimeGraph::deallocate(size_t kernel_index)
172 {
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])
176   {
177     const auto it = _tensor_to_data.find(tensor);
178     assert(it != _tensor_to_data.end());
179
180     auto *data = _tensor_to_data.at(tensor);
181     _memory_manager->release_memory(data);
182
183     _tensor_to_data.erase(it);
184   }
185 }
186
187 void RuntimeGraph::resetTensorData(uint8_t *new_data, const circle::Tensor *tensor)
188 {
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())
192   {
193     auto *data = _tensor_to_data.at(tensor);
194     _memory_manager->release_memory(data);
195   }
196
197   _tensor_to_data[tensor] = new_data;
198 }
199
200 void RuntimeGraph::resetOutputTensorsData()
201 {
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)
205   {
206     const auto tensor_index = _reader->outputs()[i];
207     assert(tensor_index != -1);
208
209     if (std::find(graph_inputs.begin(), graph_inputs.end(), tensor_index) != graph_inputs.end())
210       return;
211
212     const auto tensor = _reader->tensors()[tensor_index];
213     assert(tensor != nullptr);
214
215     auto tensor_it = _tensor_to_data.find(tensor);
216     if (tensor_it != _tensor_to_data.end())
217     {
218       auto *data = _tensor_to_data.at(tensor);
219       _memory_manager->release_memory(data);
220       _tensor_to_data.erase(tensor_it);
221     }
222   }
223 }
224
225 uint8_t *RuntimeGraph::configureGraphInput(int32_t input_index)
226 {
227   assert(_reader->get_current_subgraph_index() == _subgraph_index);
228
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);
233
234   auto *data = _memory_manager->allocate_memory(tensor);
235   configureGraphInput(input_index, data);
236
237   return data;
238 }
239
240 void RuntimeGraph::configureGraphInput(int32_t input_index, uint8_t *data)
241 {
242   assert(_reader->get_current_subgraph_index() == _subgraph_index);
243   resetOutputTensorsData();
244
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);
249
250   if (_tensor_to_data.find(tensor) != _tensor_to_data.end())
251   {
252     auto *data_prev = _tensor_to_data.at(tensor);
253     if (data_prev != data)
254       _memory_manager->release_memory(data_prev);
255   }
256   _tensor_to_data[tensor] = data;
257 }
258
259 int32_t RuntimeGraph::getInputDataSizeByIndex(int32_t input_index)
260 {
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);
266
267   return Tensor::num_elements(tensor) * size(Tensor::element_type(tensor));
268 }
269
270 int32_t RuntimeGraph::getNumOfInputTensors()
271 {
272   assert(_reader->get_current_subgraph_index() == _subgraph_index);
273   return _reader->inputs().size();
274 }
275
276 int32_t RuntimeGraph::getNumOfOutputTensors()
277 {
278   assert(_reader->get_current_subgraph_index() == _subgraph_index);
279   return _reader->outputs().size();
280 }
281
282 const circle::Tensor *RuntimeGraph::getInputTensorByIndex(int32_t input_index)
283 {
284   assert(_reader->get_current_subgraph_index() == _subgraph_index);
285
286   const auto tensor_index = _reader->inputs()[input_index];
287   const auto tensor = _reader->tensors()[tensor_index];
288   assert(tensor != nullptr);
289   return tensor;
290 }
291
292 const circle::Tensor *RuntimeGraph::getOutputTensorByIndex(int32_t input_index)
293 {
294   assert(_reader->get_current_subgraph_index() == _subgraph_index);
295
296   const auto tensor_index = _reader->outputs()[input_index];
297   const auto tensor = _reader->tensors()[tensor_index];
298   assert(tensor != nullptr);
299   return tensor;
300 }
301
302 int32_t RuntimeGraph::getOutputDataSizeByIndex(int32_t output_index)
303 {
304   assert(_reader->get_current_subgraph_index() == _subgraph_index);
305
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);
310
311   return Tensor::num_elements(tensor) * size(Tensor::element_type(tensor));
312 }
313
314 uint8_t *RuntimeGraph::getOutputDataByIndex(int32_t output_index)
315 {
316   assert(_reader->get_current_subgraph_index() == _subgraph_index);
317
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);
322
323   assert(_tensor_to_data.find(tensor) != _tensor_to_data.end());
324
325   return _tensor_to_data[tensor];
326 }
327
328 uint8_t *RuntimeGraph::getDataByTensor(const circle::Tensor *raw_tensor)
329 {
330   assert(_reader->get_current_subgraph_index() == _subgraph_index);
331
332   if (raw_tensor == nullptr)
333     return nullptr;
334
335   if (_tensor_to_data.find(raw_tensor) == _tensor_to_data.end())
336   {
337     return nullptr;
338   }
339
340   return _tensor_to_data.at(raw_tensor);
341 }
342
343 void RuntimeGraph::clearTensors() { _tensor_to_data.clear(); }
344
345 void RuntimeGraph::makeInplaceOperation(const circle::Tensor *removing_tensor,
346                                         const circle::Tensor *dst_tensor)
347 {
348   assert(_reader->get_current_subgraph_index() == _subgraph_index);
349   assert(removing_tensor != nullptr);
350
351   auto src_it = _tensor_to_data.find(removing_tensor);
352
353   if (src_it == _tensor_to_data.end())
354     return;
355
356   auto *data = _tensor_to_data[removing_tensor];
357
358   _tensor_to_data.erase(src_it);
359
360   if (dst_tensor == nullptr)
361   {
362     delete[] data;
363     return;
364   }
365
366   assert(_tensor_to_data.find(dst_tensor) == _tensor_to_data.end() &&
367          "Failed makeInplaceOperation");
368   _tensor_to_data[dst_tensor] = data;
369 }
370
371 uint8_t *RuntimeGraph::getConstDataByTensor(const circle::Tensor *raw_tensor)
372 {
373   assert(_reader->get_current_subgraph_index() == _subgraph_index);
374   if (raw_tensor == nullptr)
375     return nullptr;
376
377   auto const &buffer = wrap(_reader->buffers()[raw_tensor->buffer()]->data());
378
379   return const_cast<uint8_t *>(buffer.data());
380 }
381
382 const circle::Tensor *RuntimeGraph::getCircleTensorByIndex(int32_t index)
383 {
384   assert(_reader->get_current_subgraph_index() == _subgraph_index);
385   if (index < 0)
386     return nullptr;
387
388   const auto raw_tensor = _reader->tensors()[index];
389
390   return raw_tensor;
391 }
392
393 void RuntimeGraph::configure(bool dealloc_input)
394 {
395   selectOwnSubgraph();
396
397   for (uint32_t i = 0; i < _reader->operators().size(); ++i)
398   {
399     const auto op = _reader->operators().at(i);
400     assert(op != nullptr);
401
402     const auto opcode = _reader->builtin_code(op);
403
404     kernel_configure.configure_kernel(op, opcode, this);
405   }
406
407   if (not _is_valid)
408     buildAllocDeallocPlan(dealloc_input);
409
410   _is_valid = true;
411 }
412
413 void RuntimeGraph::setDataToTensor(const circle::Tensor *tensor, uint8_t *data)
414 {
415   _tensor_to_data[tensor] = data;
416 }
417
418 void RuntimeGraph::execute()
419 {
420   selectOwnSubgraph();
421
422   if (not _is_valid)
423     configure(true);
424
425   const auto operators_size = _reader->operators().size();
426   const auto operators = _reader->operators();
427
428   for (uint32_t i = 0; i < operators_size; ++i)
429   {
430     const auto op = operators.at(i);
431     assert(op != nullptr);
432
433     const auto opcode = _reader->builtin_code(op);
434
435     allocate(i);
436
437     kernel_executor.execute_kernel(op, opcode, this);
438
439     deallocate(i);
440   }
441 }
442
443 } // namespace luci_interpreter