• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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