17#include "core/RuntimeGraph.h"
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)
39 for (
auto &idx_to_tensor : _tensor_to_data)
41 auto *
data = idx_to_tensor.second;
48void 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;
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)
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)
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);
127void 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);
143#ifndef DIS_DYN_SHAPES
147 assert(_reader->get_current_subgraph_index() == _subgraph_index);
148 _dynamic_tensor_shapes[tensor] = std::move(shapes);
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];
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);
171void RuntimeGraph::deallocate(
size_t kernel_index)
173 assert(_reader->get_current_subgraph_index() == _subgraph_index);
174 assert(_is_valid && kernel_index < _dealloc_plan.size());
176#ifdef ENABLE_TRAINING
178 const uint32_t last_layer = _number_of_last_trainable_layers > 0
179 ? _reader->
operators().
size() - _number_of_last_trainable_layers
183 for (
const circle::Tensor *tensor : _dealloc_plan[kernel_index])
185 const auto it = _tensor_to_data.find(tensor);
186 assert(it != _tensor_to_data.end());
188 auto *
data = _tensor_to_data.at(tensor);
190#ifdef ENABLE_TRAINING
191 if (_number_of_last_trainable_layers > 0 and kernel_index >= last_layer)
193 _gradient_calc_storage->saveDataToTensor(tensor,
data);
203 _tensor_to_data.erase(it);
209 assert(_reader->get_current_subgraph_index() == _subgraph_index);
210 auto tensor_it = _tensor_to_data.find(tensor);
211 if (tensor_it != _tensor_to_data.end())
213 auto *
data = _tensor_to_data.at(tensor);
217 _tensor_to_data[tensor] = new_data;
222 assert(_reader->get_current_subgraph_index() == _subgraph_index);
223 const auto graph_inputs = _reader->
inputs();
224 for (
int i = 0; i < _reader->
outputs().
size(); ++i)
226 const auto tensor_index = _reader->
outputs()[i];
227 assert(tensor_index != -1);
229 if (std::find(graph_inputs.begin(), graph_inputs.end(), tensor_index) != graph_inputs.end())
232 const auto tensor = _reader->
tensors()[tensor_index];
233 assert(tensor !=
nullptr);
235 auto tensor_it = _tensor_to_data.find(tensor);
236 if (tensor_it != _tensor_to_data.end())
238 auto *
data = _tensor_to_data.at(tensor);
240 _tensor_to_data.erase(tensor_it);
247 assert(_reader->get_current_subgraph_index() == _subgraph_index);
249 const auto tensor_index = _reader->
inputs()[input_index];
250 assert(tensor_index != -1);
251 const auto tensor = _reader->
tensors()[tensor_index];
252 assert(tensor !=
nullptr);
262 assert(_reader->get_current_subgraph_index() == _subgraph_index);
265 const auto tensor_index = _reader->
inputs()[input_index];
266 assert(tensor_index != -1);
267 const auto tensor = _reader->
tensors()[tensor_index];
268 assert(tensor !=
nullptr);
270 if (_tensor_to_data.find(tensor) != _tensor_to_data.end())
272 auto *data_prev = _tensor_to_data.at(tensor);
273 if (data_prev !=
data)
276 _tensor_to_data[tensor] =
data;
281 assert(_reader->get_current_subgraph_index() == _subgraph_index);
282 const auto tensor_index = _reader->
inputs()[input_index];
283 assert(tensor_index != -1);
284 const auto tensor = _reader->
tensors()[tensor_index];
285 assert(tensor !=
nullptr);
287 return Tensor::num_elements(tensor) *
size(Tensor::element_type(tensor));
292 assert(_reader->get_current_subgraph_index() == _subgraph_index);
293 return _reader->
inputs().size();
298 assert(_reader->get_current_subgraph_index() == _subgraph_index);
299 return _reader->
outputs().size();
304 assert(_reader->get_current_subgraph_index() == _subgraph_index);
306 const auto tensor_index = _reader->
inputs()[input_index];
307 const auto tensor = _reader->
tensors()[tensor_index];
308 assert(tensor !=
nullptr);
314 assert(_reader->get_current_subgraph_index() == _subgraph_index);
316 const auto tensor_index = _reader->
outputs()[input_index];
317 const auto tensor = _reader->
tensors()[tensor_index];
318 assert(tensor !=
nullptr);
324 assert(_reader->get_current_subgraph_index() == _subgraph_index);
326 const auto tensor_index = _reader->
outputs()[output_index];
327 assert(tensor_index != -1);
328 const auto tensor = _reader->
tensors()[tensor_index];
329 assert(tensor !=
nullptr);
331 uint32_t num_elements = Tensor::num_elements(tensor);
332 auto it = _dynamic_tensor_shapes.find(tensor);
333 if (it != _dynamic_tensor_shapes.end())
335 num_elements = it->second.flatSize();
338 return num_elements *
size(Tensor::element_type(tensor));
343 assert(_reader->get_current_subgraph_index() == _subgraph_index);
345 const auto tensor_index = _reader->
outputs()[output_index];
346 assert(tensor_index != -1);
347 const auto tensor = _reader->
tensors()[tensor_index];
348 assert(tensor !=
nullptr);
350 assert(_tensor_to_data.find(tensor) != _tensor_to_data.end());
352 return _tensor_to_data[tensor];
357 assert(_reader->get_current_subgraph_index() == _subgraph_index);
359 if (raw_tensor ==
nullptr)
362 if (_tensor_to_data.find(raw_tensor) == _tensor_to_data.end())
367 return _tensor_to_data.at(raw_tensor);
373 const circle::Tensor *dst_tensor)
375 assert(_reader->get_current_subgraph_index() == _subgraph_index);
376 assert(removing_tensor !=
nullptr);
378 auto src_it = _tensor_to_data.find(removing_tensor);
380 if (src_it == _tensor_to_data.end())
383 auto *
data = _tensor_to_data[removing_tensor];
385 _tensor_to_data.erase(src_it);
387 if (dst_tensor ==
nullptr)
393 assert(_tensor_to_data.find(dst_tensor) == _tensor_to_data.end() &&
394 "Failed makeInplaceOperation");
395 _tensor_to_data[dst_tensor] =
data;
400 assert(_reader->get_current_subgraph_index() == _subgraph_index);
401 if (raw_tensor ==
nullptr)
404#ifdef ENABLE_TRAINING
405 assert(_number_of_last_trainable_layers == 0 or
406 _storage !=
nullptr &&
"Storage should not be null here");
408 if (_storage !=
nullptr)
410 uint8_t *result =
nullptr;
411 _storage->getTrainWeightDataByTensor(raw_tensor, &result);
413 if (result !=
nullptr)
419 auto const &buffer =
wrap(_reader->
buffers()[raw_tensor->buffer()]->
data());
421 return const_cast<uint8_t *
>(buffer.data());
426 assert(_reader->get_current_subgraph_index() == _subgraph_index);
430 const auto raw_tensor = _reader->
tensors()[index];
442 assert(op !=
nullptr);
450 buildAllocDeallocPlan(dealloc_input);
457 _tensor_to_data[tensor] =
data;
468 const auto operators = _reader->
operators();
470 for (uint32_t i = 0; i < operators_size; ++i)
472 const auto op = operators.
at(i);
473 assert(op !=
nullptr);
484#ifdef ENABLE_TRAINING
485 if (_number_of_last_trainable_layers > 0)
487 const auto graph_output = _reader->
outputs();
489 assert(graph_output.size() == 1);
491 const auto output_tensor = _reader->
tensors()[graph_output[0]];
492 uint8_t *output_data = _tensor_to_data.at(output_tensor);
493 _gradient_calc_storage->saveDataToTensor(output_tensor, output_data);
494 _tensor_to_data.erase(output_tensor);
Loads Circle file and provides helpers to access attributes.
CircleOperators operators() const
CircleBuffers buffers() const
CircleTensors tensors() const
VectorWrapper< int32_t > outputs() const
circle::BuiltinOperator builtin_code(const circle::Operator *op) const
VectorWrapper< int32_t > inputs() const
value_type at(uint32_t i) const
virtual void release_memory(luci_interpreter::Tensor &tensor)=0
virtual void allocate_memory(luci_interpreter::Tensor &tensor)=0
void execute_kernel(const circle::Operator *cur_op, circle::BuiltinOperator opcode, BaseRuntimeGraph *runtime_graph) const
void makeInplaceOperation(const circle::Tensor *src_tensor, const circle::Tensor *dst_tensor)
luci_interpreter::RuntimeShape * getDynamicShapeTensor(const circle::Tensor *tensor)
uint8_t * getConstDataByTensor(const circle::Tensor *raw_tensor)
void configure(bool dealloc_input)
void resetOutputTensorsData()
const circle::Tensor * getCircleTensorByIndex(int32_t index)
void addDynamicShapeTensor(const circle::Tensor *tensor, luci_interpreter::RuntimeShape &&shapes)
void setDataToTensor(const circle::Tensor *tensor, uint8_t *data)
void resetTensorData(uint8_t *new_data, const circle::Tensor *tensor)
int32_t getInputDataSizeByIndex(int32_t input_index)
int32_t getNumOfInputTensors()
int32_t getOutputDataSizeByIndex(int32_t output_index)
uint8_t * getOutputDataByIndex(int32_t output_index)
uint8_t * getDataByTensor(const circle::Tensor *raw_tensor)
const circle::Tensor * getOutputTensorByIndex(int32_t input_index)
int32_t getNumOfOutputTensors()
const circle::Tensor * getInputTensorByIndex(int32_t input_index)
void removeDynamicShapeTensor(const circle::Tensor *tensor)
uint8_t * configureGraphInput(int32_t input_index)
const T * data(const std::vector< T, Alloc > &v)
constexpr KernelConfigureRegistry kernel_configure
constexpr KernelExecuteRegistry kernel_executor
VectorWrapper< T > wrap(const flatbuffers::Vector< T > *vec)
loco::GraphInputIndex index(const TFPlaceholder *node)