Imported Upstream version 1.9.0
[platform/core/ml/nnfw.git] / runtime / onert / core / src / backend / cpu_common / DynamicTensorManager.cc
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 "backend/cpu_common/DynamicTensorManager.h"
18
19 #include "util/logging.h"
20
21 namespace onert
22 {
23 namespace backend
24 {
25 namespace cpu_common
26 {
27
28 DynamicTensorManager::DynamicTensorManager(const std::shared_ptr<TensorRegistry> &reg)
29     : _dynamic_mem_mgr{new DynamicMemoryManager()}, _tensors{reg}
30 {
31   // DO NOTHING
32 }
33
34 void DynamicTensorManager::applyShape(const ir::OperandIndex &ind, const ir::Shape &new_shape)
35 {
36   VERBOSE_F() << ind << std::endl;
37
38   auto tensor = _tensors->getNativeTensor(ind);
39   assert(tensor);
40
41   bool previously_dynamic = tensor->is_dynamic();
42
43   auto allocTensorMem = [&](bool overwrite = false) {
44     auto capacity = tensor->total_size();
45     auto alloc = _dynamic_mem_mgr->allocate(ind, capacity);
46
47     if (overwrite)
48       tensor->overwriteBuffer(alloc);
49     else
50       tensor->setBuffer(alloc);
51   };
52
53   if (!previously_dynamic)
54   {
55     // TODO deallocate tensor->buffer()
56     // issue is that staticTensorManager might have allocate this memory
57     tensor->setShape(new_shape);
58     tensor->set_dynamic();
59     allocTensorMem(true);
60   }
61   else if (tensor->buffer() == nullptr)
62   {
63     tensor->setShape(new_shape);
64     tensor->set_dynamic();
65     allocTensorMem();
66   }
67   // when buffer was already allocated and new_shape requires different size
68   else
69   {
70     auto previous_size = tensor->total_size();
71     auto new_size = new_shape.num_elements() * sizeOfDataType(tensor->data_type());
72     if (previous_size != new_size)
73     {
74       _dynamic_mem_mgr->deallocate(ind);
75
76       tensor->setShape(new_shape);
77       tensor->set_dynamic();
78       allocTensorMem(true);
79     }
80     else
81     { // when buffer with same size was already allocated, shape could differ
82       tensor->setShape(new_shape);
83     }
84   }
85 }
86
87 void DynamicTensorManager::buildTensor(const ir::OperandIndex &ind,
88                                        const ir::OperandInfo &tensor_info,
89                                        ir::Layout backend_layout)
90 {
91   assert(_tensors->getNativeTensor(ind) == nullptr);
92   auto tensor = std::make_shared<Tensor>(tensor_info, backend_layout, this);
93   _tensors->setNativeTensor(ind, tensor);
94 }
95
96 void DynamicTensorManager::planDealloc(ir::OperationIndex op_ind, ir::OperandIndex operand_ind)
97 {
98   _dealloc_tensor_map[op_ind].emplace(operand_ind);
99 }
100
101 void DynamicTensorManager::deallocInput(ir::OperationIndex op_ind)
102 {
103   auto find = _dealloc_tensor_map.find(op_ind);
104   if (find == _dealloc_tensor_map.end())
105     return;
106
107   auto &input_set = find->second;
108   for (auto input_ind : input_set)
109   {
110     auto *tensor = _tensors->getNativeTensor(input_ind).get();
111     if (!tensor->is_dynamic())
112       continue;
113
114     _dynamic_mem_mgr->deallocate(input_ind);
115     tensor->resetBuffer();
116
117     VERBOSE(DynamicTensorManager) << "Deallocating #" << input_ind.value()
118                                   << " (input of op_ind: " << op_ind.value() << ")" << std::endl;
119   }
120 }
121
122 void DynamicTensorManager::deallocSubgraphOutput(ir::OperandIndex output_ind)
123 {
124   auto *tensor = _tensors->getNativeTensor(output_ind).get();
125   if (!tensor->is_dynamic())
126     return;
127
128   _dynamic_mem_mgr->deallocate(output_ind);
129   tensor->resetBuffer();
130
131   VERBOSE(DynamicTensorManager) << "Deallocating #" << output_ind.value()
132                                 << " (output of a subgraph)" << std::endl;
133 }
134
135 } // namespace cpu_common
136 } // namespace backend
137 } // namespace onert