You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

graph.cc 10 kB

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