• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright 2021 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 "coder/graph.h"
18 #include <queue>
19 #include <deque>
20 #include <string>
21 #include <memory>
22 #include <algorithm>
23 #include <set>
24 #include "coder/log.h"
25 #include "coder/opcoders/op_coder_register.h"
26 #include "coder/utils/type_cast.h"
27 #include "schema/inner/model_generated.h"
28 #include "securec/include/securec.h"
29 #include "src/common/prim_util.h"
30 #include "src/lite_model.h"
31 
32 namespace mindspore::lite::micro {
~CoderGraph()33 CoderGraph::~CoderGraph() {
34   if (model_ != nullptr) {
35     model_->Free();
36     delete model_;
37     model_ = nullptr;
38   }
39   for (auto &tensor : all_tensors_) {
40     delete tensor;
41   }
42 }
43 
ConvertTensors()44 int CoderGraph::ConvertTensors() {
45   if (model_ == nullptr) {
46     MS_LOG(ERROR) << "Graph model is nullptr";
47     return RET_ERROR;
48   }
49   std::vector<Tensor *> all_tensors;
50   auto clear_tensors = [&all_tensors]() {
51     std::for_each(all_tensors.begin(), all_tensors.end(), [](Tensor *&t) {
52       delete t;
53       t = nullptr;
54     });
55     all_tensors.clear();
56   };
57   auto check_dim = [](int dim) -> int {
58     MS_CHECK_TRUE(dim > 0, "invalid dim value!");
59     return RET_OK;
60   };
61 
62   // deal with allTensors
63   uint32_t tensorCount = model_->all_tensors_.size();
64   for (uint32_t i = 0; i < tensorCount; ++i) {
65     schema::Tensor *origin_tensor = model_->all_tensors_.at(i);
66     MS_CHECK_PTR_WITH_EXE(origin_tensor, clear_tensors());
67     // tensor dims
68     std::vector<int> shape;
69     if (origin_tensor->dims() != nullptr) {
70       for (uint32_t j = 0; j < origin_tensor->dims()->size(); j++) {
71         MS_CHECK_PTR(origin_tensor->dims()->data());
72         int dim = static_cast<int>(origin_tensor->dims()->data()[j]);
73         MS_CHECK_RET_CODE_WITH_EXE(check_dim(dim), "parse shape failed!", clear_tensors());
74         shape.push_back(dim);
75       }
76     }
77     // tensor Datatype
78     if (shape.empty()) {
79       shape.push_back(1);
80     }
81     int origin_data_type = static_cast<int>(origin_tensor->dataType());
82     Tensor *dstTensor = new (std::nothrow)
83       lite::Tensor(TypeId(origin_data_type), shape, static_cast<mindspore::Format>(origin_tensor->format()),
84                    TensorCategory(origin_tensor));
85     MS_CHECK_PTR(dstTensor);
86     if (origin_tensor->nodeType() == NodeType_ValueNode && origin_tensor->data() != nullptr &&
87         origin_tensor->data()->size() > 0) {
88       // copy data, this is weight && bias
89       MS_CHECK_TRUE_WITH_EXE(origin_tensor->data()->size() > 0, "invalid meta_tensor data size.", delete dstTensor);
90       auto data_size = static_cast<size_t>(origin_tensor->data()->size());
91       MS_CHECK_RET_CODE_WITH_EXE(dstTensor->MallocData(), "dst tensor malloc data failed!", delete dstTensor);
92       void *dst_data = dstTensor->data();
93       MS_CHECK_RET_CODE_WITH_EXE(memcpy_s(dst_data, dstTensor->Size(), origin_tensor->data()->data(), data_size),
94                                  "memcpy_s copy data failed!", delete dstTensor);
95       dstTensor->set_data(dst_data);
96     }
97     if (origin_tensor->name() != nullptr) {
98       dstTensor->set_tensor_name(origin_tensor->name()->str());
99     }
100     auto quant_params = origin_tensor->quantParams();
101     if (quant_params != nullptr) {
102       for (int j = 0; j < static_cast<int>(quant_params->size()); j++) {
103         auto quant_param = quant_params->Get(j);
104         LiteQuantParam quant_arg{};
105         if (quant_param == nullptr) {
106           quant_arg.inited = false;
107         } else {
108           quant_arg.inited = true;
109           quant_arg.bitNum = quant_param->numBits();
110           quant_arg.scale = quant_param->scale();
111           quant_arg.zeroPoint = quant_param->zeroPoint();
112           quant_arg.var_corr = quant_param->varCorr();
113           quant_arg.mean_corr = quant_param->meanCorr();
114           quant_arg.roundType = quant_param->roundType();
115           quant_arg.multiplier = quant_param->multiplier();
116           quant_arg.dstDtype = quant_param->dstDtype();
117         }
118         dstTensor->AddQuantParam(quant_arg);
119       }
120     }
121     all_tensors.emplace_back(dstTensor);
122   }
123   SetAllTensors(all_tensors);
124   return RET_OK;
125 }
126 
InitGraphInOutTensors()127 int CoderGraph::InitGraphInOutTensors() {
128   if (model_ == nullptr) {
129     return RET_ERROR;
130   }
131   std::vector<size_t> graph_input_node_indexes = lite::GetGraphInputNodes(model_);
132   std::vector<uint32_t> input_indices;
133   for (auto in_node_index : graph_input_node_indexes) {
134     in_node_index = static_cast<uint32_t>(in_node_index);
135     auto in_node = model_->all_nodes_.at(in_node_index);
136     MS_CHECK_PTR(in_node);
137     for (uint32_t i = 0; i < in_node->input_indices_.size(); i++) {
138       auto in_tensor_index = size_t(in_node->input_indices_.at(i));
139       bool is_graph_input = false;
140       for (uint32_t j = 0; j < model_->input_indices_.size(); j++) {
141         if (in_tensor_index == size_t(model_->input_indices_.at(j))) {
142           input_indices.push_back(static_cast<uint32_t>(in_tensor_index));
143           is_graph_input = true;
144           break;
145         }
146       }
147       if (!is_graph_input) {
148         continue;
149       }
150       if (in_tensor_index < all_tensors_.size()) {
151         lite::Tensor *in_tensor = all_tensors_.at(in_tensor_index);
152         AddInputMap(in_node->name_, in_tensor);
153       }
154     }
155   }
156   SetInputIndices(input_indices);
157   std::vector<uint32_t> output_indices;
158   auto graph_output_node_indexes = lite::GetGraphOutputNodes(model_);
159   for (auto out_node_index : graph_output_node_indexes) {
160     out_node_index = static_cast<uint32_t>(out_node_index);
161     auto *out_node = model_->all_nodes_.at(out_node_index);
162     for (uint32_t i = 0; i < out_node->output_indices_.size(); i++) {
163       auto out_tensor_index = size_t(out_node->output_indices_.at(i));
164       bool is_graph_output = false;
165       for (uint32_t j = 0; j < model_->output_indices_.size(); j++) {
166         if (out_tensor_index == size_t(model_->output_indices_.at(j))) {
167           output_indices.push_back(static_cast<uint32_t>(out_tensor_index));
168           is_graph_output = true;
169           break;
170         }
171       }
172       if (!is_graph_output) {
173         continue;
174       }
175       if (out_tensor_index < all_tensors_.size()) {
176         lite::Tensor *out_tensor = all_tensors_.at(out_tensor_index);
177         if (out_tensor == nullptr) {
178           MS_LOG(ERROR) << "can not find any output tensor in all_tensors";
179           return RET_ERROR;
180         }
181         AddOutputMap(out_node->name_, out_tensor);
182       }
183     }
184   }
185   SetOutputIndices(output_indices);
186   InitInputs();
187   InitOutputs();
188   return RET_OK;
189 }
190 
input_tensors() const191 std::vector<lite::Tensor *> CoderGraph::input_tensors() const { return input_tensors_; }
192 
output_tensors() const193 std::vector<lite::Tensor *> CoderGraph::output_tensors() const { return output_tensors_; }
194 
InitInputs()195 void CoderGraph::InitInputs() {
196   for (const auto &pair : inputs_map_) {
197     std::vector<Tensor *> tensors = pair.second;
198     input_tensors_.insert(input_tensors_.end(), tensors.begin(), tensors.end());
199   }
200   // remove duplicate tensors
201   std::set<lite::Tensor *> unique;
202   unique.insert(input_tensors_.begin(), input_tensors_.end());
203   input_tensors_.clear();
204   input_tensors_.insert(input_tensors_.end(), unique.begin(), unique.end());
205 }
206 
InitOutputs()207 void CoderGraph::InitOutputs() {
208   std::transform(output_indices_.begin(), output_indices_.end(), std::back_inserter(output_tensors_),
209                  [&](uint32_t a) { return this->all_tensors_.at(a); });
210 }
211 
SetAllTensors(const std::vector<Tensor * > & all_tensors)212 void CoderGraph::SetAllTensors(const std::vector<Tensor *> &all_tensors) {
213   all_tensors_.insert(all_tensors_.end(), all_tensors.begin(), all_tensors.end());
214 }
215 
SetInputIndices(const std::vector<uint32_t> & input_indices)216 void CoderGraph::SetInputIndices(const std::vector<uint32_t> &input_indices) {
217   input_indices_.insert(input_indices_.end(), input_indices.begin(), input_indices.end());
218 }
219 
SetOutputIndices(const std::vector<uint32_t> & output_indices)220 void CoderGraph::SetOutputIndices(const std::vector<uint32_t> &output_indices) {
221   output_indices_.insert(output_indices_.end(), output_indices.begin(), output_indices.end());
222 }
223 
AddInputMap(const std::string & node_id,Tensor * input_tensor)224 void CoderGraph::AddInputMap(const std::string &node_id, Tensor *input_tensor) {
225   if (!input_tensor) {
226     MS_LOG(ERROR) << "input tensor is nullptr, can not added to coder_graph";
227     return;
228   }
229   this->inputs_map_[node_id].emplace_back(input_tensor);
230 }
231 
AddOutputMap(const std::string & node_id,Tensor * output_tensor)232 void CoderGraph::AddOutputMap(const std::string &node_id, Tensor *output_tensor) {
233   if (!output_tensor) {
234     MS_LOG(ERROR) << "output tensor is nullptr, can not added to coder_graph";
235     return;
236   }
237   this->outputs_map_[node_id].emplace_back(output_tensor);
238 }
239 
all_tensors() const240 std::vector<lite::Tensor *> CoderGraph::all_tensors() const { return this->all_tensors_; }
241 
GetOutputsMap() const242 const std::map<std::string, std::vector<lite::Tensor *>> &CoderGraph::GetOutputsMap() const { return outputs_map_; }
243 
input_indices() const244 std::vector<uint32_t> CoderGraph::input_indices() const { return this->input_indices_; }
245 
output_indices() const246 std::vector<uint32_t> CoderGraph::output_indices() const { return this->output_indices_; }
247 
DumpUnSupportLayer(Target target)248 void CoderGraph::DumpUnSupportLayer(Target target) {
249   std::cerr << "==========dump all unsupported layer for codegen=====" << std::endl;
250   std::for_each(model_->all_nodes_.begin(), model_->all_nodes_.end(), [this, target](const Model::Node *node) {
251     if (node->primitive_ == nullptr) {
252       return;
253     }
254     // fake create opcoders
255     uint32_t input_idx = node->input_indices_.at(0);
256     Tensor *t = all_tensors_.at(input_idx);
257     TypeId dtype = t->data_type();
258     int pt = GetPrimitiveType(node->primitive_, reinterpret_cast<lite::LiteModel *>(model_)->GetSchemaVersion());
259     CoderKey key(target, dtype, pt);
260     // search from the opcoder registry
261     if (OpCoderFactory::GetInstance()->FindOpCoder(key) == nullptr) {
262       std::cerr << node->name_ << ", primitive type: "
263                 << mindspore::schema::EnumNamePrimitiveType(static_cast<schema::PrimitiveType>(pt))
264                 << ", data_type: " << EnumNameDataType(dtype) << std::endl;
265     }
266   });
267 }
268 }  // namespace mindspore::lite::micro
269