1 /**
2 * Copyright 2020 Huawei Technologies Co., Ltd
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 "src/sub_graph_kernel.h"
18 #include <algorithm>
19 #include "src/tensor.h"
20 #ifndef CONTROLFLOW_TENSORLIST_CLIP
21 #include "src/tensorlist.h"
22 #endif
23 #ifdef ENABLE_FP16
24 #include "src/runtime/kernel/arm/fp16/fp16_op_handler.h"
25 #endif
26 #include "src/common/version_manager.h"
27 #include "src/runtime/infer_manager.h"
28 #include "src/common/tensor_util.h"
29 #include "src/common/utils.h"
30
31 namespace mindspore::kernel {
32 using mindspore::lite::RET_ERROR;
33 using mindspore::lite::RET_INFER_ERR;
34 using mindspore::lite::RET_INFER_INVALID;
35 using mindspore::lite::RET_OK;
36
Prepare()37 int SubGraphKernel::Prepare() {
38 for (auto node : this->nodes_) {
39 if (node == nullptr) {
40 MS_LOG(ERROR) << "node in Subgraph is nullptr";
41 return mindspore::lite::RET_NULL_PTR;
42 }
43 auto ret = node->Prepare();
44 if (ret != RET_OK) {
45 MS_LOG(ERROR) << "prepare node " << node->name() << " failed";
46 return ret;
47 }
48 }
49 return RET_OK;
50 }
51
ToString() const52 std::string SubGraphKernel::ToString() const {
53 std::ostringstream oss;
54 oss << "===============================================" << std::endl << "Subgraph type : " << this->subgraph_type_;
55 oss << std::endl << this->in_tensors().size() << "Subgraph inputTensors:";
56 for (auto tensor : in_tensors()) {
57 oss << " " << tensor;
58 }
59 oss << std::endl << this->out_tensors().size() << "Subgraph outputTensors:";
60 for (auto tensor : out_tensors()) {
61 oss << " " << tensor;
62 }
63 oss << std::endl << "Subgraph input nodes :" << std::endl;
64 for (auto kernel : this->in_nodes_) {
65 oss << " " << kernel->ToString() << std::endl;
66 }
67 oss << std::endl << "Subgraph output nodes :" << std::endl;
68 for (auto kernel : this->out_nodes_) {
69 oss << " " << kernel->ToString() << std::endl;
70 }
71 oss << std::endl << nodes_.size() << " nodes in subgraph :";
72 for (auto kernel : this->nodes_) {
73 oss << " " << kernel->name();
74 }
75 return oss.str();
76 }
77
Execute(const KernelCallBack & before,const KernelCallBack & after)78 int SubGraphKernel::Execute(const KernelCallBack &before, const KernelCallBack &after) {
79 if (this->executor_ == nullptr) {
80 MS_LOG(ERROR) << "executor is nullptr";
81 return RET_ERROR;
82 }
83 auto ret = executor_->Run(this->in_tensors(), this->out_tensors(), this->nodes_, before, after);
84 if (ret != RET_OK) {
85 MS_LOG(ERROR) << "Run sub graph failed: " << ret;
86 return ret;
87 }
88
89 return lite::RET_OK;
90 }
91
ReSize()92 int SubGraphKernel::ReSize() {
93 for (auto kernel : nodes_) {
94 if (kernel == nullptr) {
95 MS_LOG(ERROR) << "input kernel is nullptr!";
96 return RET_ERROR;
97 }
98 if (kernel->subgraph_type() != kernel::kNotSubGraph) {
99 MS_LOG(ERROR) << "all nodes in should be kernel";
100 return RET_ERROR;
101 }
102 std::vector<lite::Tensor *> inputs = kernel->in_tensors();
103 std::vector<lite::Tensor *> outputs = kernel->out_tensors();
104 for (auto &output : outputs) {
105 output->FreeData();
106 }
107 int ret;
108 #ifndef CUSTOM_KERNEL_REGISTRY_CLIP
109 ret = lite::KernelInferShape(inputs, outputs, kernel->kernel()->primitive(), kernel->Context()->GetProviders(),
110 schema_version_, kernel->kernel());
111 if (ret == lite::RET_NOT_SUPPORT) {
112 #endif
113 auto parameter = kernel->op_parameter();
114 if (parameter == nullptr) {
115 MS_LOG(ERROR) << "kernel(" << kernel->name() << ")'s op_parameter is nullptr!";
116 return RET_ERROR;
117 }
118 ret = lite::KernelInferShape(inputs, outputs, parameter);
119 #ifndef CUSTOM_KERNEL_REGISTRY_CLIP
120 }
121 #endif
122 if (ret == RET_INFER_INVALID) {
123 MS_LOG(INFO) << "InferShape shouldn't be done before runtime, type:"
124 << schema::EnumNamePrimitiveType(static_cast<schema::PrimitiveType>(kernel->type()))
125 << "flag set to false.";
126 } else if (ret != RET_OK) {
127 MS_LOG(ERROR) << "InferShape failed, type: "
128 << schema::EnumNamePrimitiveType(static_cast<schema::PrimitiveType>(kernel->type()));
129 return RET_INFER_ERR;
130 }
131 if (ret == RET_OK) {
132 ret = kernel->ReSize();
133 if (ret != RET_OK) {
134 MS_LOG(ERROR) << "kernel " << kernel->name() << " resize fail!ret = " << ret;
135 return ret;
136 }
137 }
138 }
139 return RET_OK;
140 }
InitInputTensorInitRefCount()141 void SubGraphKernel::InitInputTensorInitRefCount() {
142 for (auto &input : this->in_tensors()) {
143 int input_init_ref_count = input->init_ref_count();
144 for (auto *node : nodes_) {
145 input_init_ref_count += std::count_if(node->in_tensors().begin(), node->in_tensors().end(),
146 [&input](lite::Tensor *item) { return item == input; });
147 }
148 input->set_init_ref_count(input_init_ref_count);
149 }
150 }
151
InitOutTensorInitRefCount(const std::vector<LiteKernel * > * mask_kernels)152 void SubGraphKernel::InitOutTensorInitRefCount(const std::vector<LiteKernel *> *mask_kernels) {
153 for (auto *node : nodes_) {
154 node->InitOutTensorInitRefCount(mask_kernels);
155 }
156 }
157
DropNode(LiteKernel * node)158 void SubGraphKernel::DropNode(LiteKernel *node) {
159 lite::VectorErase(&nodes_, node);
160 lite::VectorErase(&in_nodes_, node);
161 lite::VectorErase(&out_nodes_, node);
162 }
163
Prepare()164 int CustomSubGraph::Prepare() {
165 auto ret = SubGraphKernel::Prepare();
166 if (ret != RET_OK) {
167 return ret;
168 }
169 if (nodes_.size() < 1) {
170 return RET_OK;
171 }
172 auto provider = nodes_[0]->desc().provider;
173 auto context = this->Context();
174 AllocatorPtr allocator = context->allocator;
175 auto iter = std::find_if(context->device_list_.begin(), context->device_list_.end(),
176 [&provider](const auto &dev) { return dev.provider_ == provider; });
177 if (iter != context->device_list_.end()) {
178 allocator = iter->allocator_;
179 }
180
181 for (size_t i = 0; i < nodes_.size() - 1; ++i) {
182 auto node = nodes_[i];
183 for (auto tensor : node->out_tensors()) {
184 MS_ASSERT(tensor != nullptr);
185 tensor->set_allocator(allocator);
186 }
187 }
188
189 auto node = nodes_[nodes_.size() - 1];
190 for (auto tensor : node->out_tensors()) {
191 MS_ASSERT(tensor != nullptr);
192 tensor->set_allocator(context->allocator);
193 }
194 return RET_OK;
195 }
196
Execute(const KernelCallBack & before,const KernelCallBack & after)197 int CustomSubGraph::Execute(const KernelCallBack &before, const KernelCallBack &after) {
198 for (auto kernel : nodes_) {
199 MS_ASSERT(kernel != nullptr);
200 auto ret = kernel->Execute(before, after);
201 if (ret != RET_OK) {
202 MS_LOG(ERROR) << "run kernel failed, name: " << kernel->name();
203 return ret;
204 }
205 }
206
207 return RET_OK;
208 }
209
Prepare()210 int CpuSubGraph::Prepare() {
211 auto ret = SubGraphKernel::Prepare();
212 if (ret != RET_OK) {
213 return ret;
214 }
215 for (auto node : nodes_) {
216 for (auto tensor : node->out_tensors()) {
217 MS_ASSERT(tensor != nullptr);
218 tensor->set_allocator(this->Context()->allocator);
219 }
220 }
221 for (auto &out : this->out_tensors()) {
222 out->set_allocator(this->Context()->allocator);
223 }
224 return RET_OK;
225 }
226
Execute(const KernelCallBack & before,const KernelCallBack & after)227 int CpuSubGraph::Execute(const KernelCallBack &before, const KernelCallBack &after) {
228 MS_ASSERT(this->Context()->allocator.get() != nullptr);
229
230 for (auto *kernel : nodes_) {
231 MS_ASSERT(kernel != nullptr);
232 auto ret = kernel->Execute(before, after);
233 if (ret != RET_OK) {
234 MS_LOG(ERROR) << "run kernel failed, name: " << kernel->name();
235 return ret;
236 }
237 }
238 return RET_OK;
239 }
240 } // namespace mindspore::kernel
241