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.

session.cc 17 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  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/session.h"
  17. #include <set>
  18. #include <queue>
  19. #include <vector>
  20. #include <utility>
  21. #include "coder/allocator/allocator.h"
  22. #include "coder/context.h"
  23. #include "coder/generator/generator.h"
  24. #include "coder/generator/inference/inference_generator.h"
  25. #include "coder/opcoders/op_coder_builder.h"
  26. #include "coder/utils/coder_utils.h"
  27. #include "coder/log.h"
  28. #include "include/errorcode.h"
  29. #include "src/common/file_utils.h"
  30. namespace mindspore::lite::micro {
  31. CoderSession::CoderSession() { allocator_ = MemoryAllocator::GetInstance(); }
  32. int CoderSession::InferShape() {
  33. const Model *model = coder_graph_->model();
  34. std::vector<lite::Tensor *> all_tensors = coder_graph_->all_tensors();
  35. size_t nodes_num = model->all_nodes_.size();
  36. for (size_t i = 0; i < nodes_num; ++i) {
  37. auto curr_node = model->all_nodes_.at(i);
  38. if (!curr_node) {
  39. MS_LOG(ERROR) << "model's node is null, who's index is " << i << ". InferShape failed ";
  40. return RET_ERROR;
  41. }
  42. std::vector<Tensor *> inputs;
  43. std::vector<Tensor *> outputs;
  44. size_t input_nums = curr_node->input_indices_.size();
  45. inputs.reserve(input_nums);
  46. for (size_t j = 0; j < input_nums; ++j) {
  47. inputs.push_back(all_tensors.at(curr_node->input_indices_.at(j)));
  48. }
  49. size_t output_nums = curr_node->output_indices_.size();
  50. outputs.reserve(output_nums);
  51. for (size_t j = 0; j < output_nums; ++j) {
  52. outputs.push_back(all_tensors.at(curr_node->output_indices_.at(j)));
  53. }
  54. PrimitiveC *primitive = curr_node->primitive_;
  55. if (primitive == nullptr) {
  56. MS_LOG(ERROR) << "Op " << curr_node->name_ << " should exist in model!";
  57. return RET_ERROR;
  58. }
  59. primitive->set_infer_flag(true);
  60. int ret = primitive->InferShape(inputs, outputs);
  61. if (ret == RET_INFER_INVALID) {
  62. MS_LOG(INFO) << "InferShape shouldn't be done before runtime, name: " << curr_node->name_
  63. << ", type: " << schema::EnumNamePrimitiveType(static_cast<schema::PrimitiveType>(primitive->Type()))
  64. << "flag set to false.";
  65. primitive->set_infer_flag(false);
  66. } else if (ret != RET_OK) {
  67. MS_LOG(ERROR) << "InferShape failed, name: " << curr_node->name_ << ", type: "
  68. << schema::EnumNamePrimitiveType(static_cast<schema::PrimitiveType>(primitive->Type()));
  69. return RET_ERROR;
  70. }
  71. }
  72. return RET_OK;
  73. }
  74. void CoderSession::EndCode() {
  75. context_->set_tensor_map(allocator_->tensors_map());
  76. context_->set_saved_weights(allocator_->saved_weights());
  77. context_->set_total_buffer_size(allocator_->total_buffer_size());
  78. context_->set_graph_inputs(coder_graph_->input_tensors());
  79. context_->set_graph_outputs(coder_graph_->output_tensors());
  80. Configurator *config = Configurator::GetInstance();
  81. if (config->debug_mode()) {
  82. std::vector<std::string> blocks;
  83. blocks = AddDumpDataInfo(context_->code_blocks(), op_coders_);
  84. context_->set_code_blocks(blocks);
  85. }
  86. }
  87. int CoderSession::Run() {
  88. MS_LOG(INFO) << "start run opcoders";
  89. // 1. assign memory
  90. std::vector<lite::Tensor *> inputs = coder_graph_->input_tensors();
  91. int ret = allocator_->Assign(inputs, op_coders_);
  92. MS_CHECK_RET_CODE(ret, "assign memory failed");
  93. // 2. prepare, init model parameters
  94. for (const auto &op_coder : op_coders_) {
  95. MS_CHECK_PTR(op_coder);
  96. ret = op_coder->Prepare(context_.get());
  97. MS_CHECK_RET_CODE(ret, "prepare coder " << op_coder->ID() << " failed");
  98. allocator_->enable_is_next();
  99. }
  100. // 3. docode, write operator code
  101. for (const auto &op_coder : op_coders_) {
  102. MS_CHECK_PTR(op_coder);
  103. ret = op_coder->DoCode(this->context_.get());
  104. MS_CHECK_RET_CODE(ret, "do coder " << op_coder->ID() << " failed");
  105. }
  106. this->EndCode();
  107. MS_LOG(INFO) << "run opcoders success";
  108. return RET_OK;
  109. }
  110. int CoderSession::GenerateCode() {
  111. MS_LOG(INFO) << "CoderSession::GenerateCode start";
  112. std::shared_ptr<Generator> generator;
  113. Configurator *config = Configurator::GetInstance();
  114. CodeMode code_mode = config->code_mode();
  115. switch (code_mode) {
  116. case Code_Normal:
  117. case Code_Android:
  118. MS_LOG(INFO) << "generate code for Android";
  119. generator = std::make_shared<InferenceGenerator>(std::move(context_));
  120. break;
  121. default:
  122. MS_LOG(ERROR) << "unsupported generator code mode, " << code_mode;
  123. return RET_ERROR;
  124. }
  125. // when use file, coder context need to remove initial parameters from tensors info
  126. // we use tmp_tensor_list to storage
  127. int ret = generator->GenerateCode();
  128. if (ret != RET_OK) {
  129. MS_LOG(ERROR) << "generate code failed";
  130. }
  131. MS_LOG(INFO) << "CoderSession::GenerateCode done";
  132. return ret;
  133. }
  134. int CoderSession::Init(const std::string &model_path) {
  135. MS_LOG(INFO) << "CoderSession::Init start";
  136. // Load graph
  137. MS_LOG(DEBUG) << "start reading model file";
  138. size_t size = 0;
  139. char *graph_buf = ReadFile(model_path.c_str(), &size);
  140. MS_CHECK_PTR(graph_buf);
  141. // new a context for session
  142. if (size >= UINT_MAX) {
  143. MS_LOG(ERROR) << "the size is invalid";
  144. delete[] graph_buf;
  145. return RET_ERROR;
  146. }
  147. Model *model = lite::Model::Import(graph_buf, size);
  148. delete[] graph_buf;
  149. MS_CHECK_PTR(model);
  150. coder_graph_ = std::make_unique<CoderGraph>(model);
  151. context_ = std::make_unique<CoderContext>();
  152. allocator_->RecordRuntimeAddrs(context_->input_name(), context_->buffer_name(), context_->weight_name());
  153. MS_LOG(INFO) << "CoderSession::Init done";
  154. return RET_OK;
  155. }
  156. int CoderSession::Build() {
  157. if (coder_graph_ == nullptr) {
  158. return RET_ERROR;
  159. }
  160. int ret = this->CompileGraph();
  161. if (ret != RET_OK) {
  162. MS_LOG(ERROR) << "CompileGraph failed: " << ret;
  163. return ret;
  164. }
  165. return RET_OK;
  166. }
  167. int CoderSession::InitOpcodersInputsAndOutputs() {
  168. std::map<Tensor *, OperatorCoder *> input_node_map;
  169. std::map<Tensor *, OperatorCoder *> output_node_map;
  170. for (const auto &op_coder : op_coders_) {
  171. std::vector<Tensor *> inputs = op_coder->input_tensors();
  172. std::for_each(inputs.begin(), inputs.end(),
  173. [&](Tensor *t) { input_node_map.insert(std::make_pair(t, op_coder.get())); });
  174. std::vector<Tensor *> outputs = op_coder->input_tensors();
  175. std::for_each(outputs.begin(), outputs.end(),
  176. [&](Tensor *t) { output_node_map.insert(std::make_pair(t, op_coder.get())); });
  177. }
  178. for (const auto &op_coder : op_coders_) {
  179. std::vector<Tensor *> inputs = op_coder->input_tensors();
  180. for (const auto &tensor : inputs) {
  181. auto item = output_node_map.find(tensor);
  182. if (item != output_node_map.end()) {
  183. op_coder->AddInputOp(item->second);
  184. }
  185. }
  186. std::vector<Tensor *> outputs = op_coder->output_tensors();
  187. for (const auto &tensor : outputs) {
  188. auto item = input_node_map.find(tensor);
  189. if (item != input_node_map.end()) {
  190. op_coder->AddOutputOp(item->second);
  191. }
  192. }
  193. }
  194. return RET_OK;
  195. }
  196. int CoderSession::InitTensorsRef() {
  197. auto all_tensors = coder_graph_->all_tensors();
  198. for (auto &tensor : all_tensors) {
  199. size_t refcount = 0;
  200. for (const auto &node : this->op_coders_) {
  201. auto inputs = node->input_tensors();
  202. auto iter = std::find(inputs.begin(), inputs.end(), tensor);
  203. if (iter != inputs.end()) {
  204. refcount++;
  205. }
  206. }
  207. tensor->set_ref_count(refcount);
  208. }
  209. return RET_OK;
  210. }
  211. int CoderSession::ConvertTensors() {
  212. auto model = coder_graph_->model();
  213. if (model == nullptr) {
  214. MS_LOG(ERROR) << "Graph model is nullptr";
  215. return RET_ERROR;
  216. }
  217. std::vector<Tensor *> all_tensors;
  218. auto clear_tensors = [&all_tensors]() {
  219. std::for_each(all_tensors.begin(), all_tensors.end(), [](Tensor *&t) {
  220. delete t;
  221. t = nullptr;
  222. });
  223. all_tensors.clear();
  224. };
  225. auto check_dim = [](int dim) -> int {
  226. MS_CHECK_TRUE(dim > 0, "invalid dim value!");
  227. return RET_OK;
  228. };
  229. // deal with allTensors
  230. uint32_t tensorCount = model->all_tensors_.size();
  231. for (uint32_t i = 0; i < tensorCount; ++i) {
  232. schema::Tensor *origin_tensor = model->all_tensors_.at(i);
  233. MS_CHECK_PTR_WITH_EXE(origin_tensor, clear_tensors());
  234. // tensor dims
  235. std::vector<int> shape;
  236. if (origin_tensor->nodeType() == schema::NodeType_ValueNode) {
  237. MS_CHECK_PTR_WITH_EXE(origin_tensor->dims(), clear_tensors());
  238. for (uint32_t j = 0; j < origin_tensor->dims()->size(); j++) {
  239. MS_CHECK_PTR(origin_tensor->dims()->data());
  240. int dim = static_cast<int>(origin_tensor->dims()->data()[j]);
  241. MS_CHECK_RET_CODE_WITH_EXE(check_dim(dim), "parse shape failed!", clear_tensors());
  242. shape.push_back(dim);
  243. }
  244. }
  245. // tensor Datatype
  246. int origin_data_type = static_cast<int>(origin_tensor->dataType());
  247. Tensor *dstTensor = new (std::nothrow)
  248. lite::Tensor(TypeId(origin_data_type), shape, origin_tensor->format(), TensorCategory(origin_tensor));
  249. MS_CHECK_PTR(dstTensor);
  250. if (origin_tensor->nodeType() == schema::NodeType_ValueNode && origin_tensor->data() != nullptr &&
  251. origin_tensor->data()->size() > 0) {
  252. if (shape.empty()) {
  253. shape.push_back(1);
  254. }
  255. // copy data, this is weight && bias
  256. MS_CHECK_TRUE_WITH_EXE(origin_tensor->data()->size() > 0, "invalid meta_tensor data size.", delete dstTensor);
  257. auto data_size = static_cast<size_t>(origin_tensor->data()->size());
  258. MS_CHECK_RET_CODE_WITH_EXE(dstTensor->MallocData(), "dst tensor malloc data failed!", delete dstTensor);
  259. void *dst_data = dstTensor->data_c();
  260. MS_CHECK_RET_CODE_WITH_EXE(memcpy_s(dst_data, data_size, origin_tensor->data()->data(), data_size),
  261. "memcpy_s copy data failed!", delete dstTensor);
  262. dstTensor->set_data(dst_data);
  263. }
  264. auto quant_params = origin_tensor->quantParams();
  265. if (quant_params != nullptr) {
  266. for (int j = 0; j < static_cast<int>(quant_params->size()); j++) {
  267. QuantArg quant_arg{};
  268. quant_arg.scale = quant_params->Get(j)->scale();
  269. quant_arg.zeroPoint = quant_params->Get(j)->zeroPoint();
  270. dstTensor->AddQuantParam(quant_arg);
  271. }
  272. }
  273. all_tensors.emplace_back(dstTensor);
  274. }
  275. coder_graph_->SetAllTensors(all_tensors);
  276. return RET_OK;
  277. }
  278. int CoderSession::CreateOpCoders() {
  279. const Model *model = coder_graph_->model();
  280. if (model == nullptr) {
  281. MS_LOG(ERROR) << "Graph model is nullptr";
  282. return RET_ERROR;
  283. }
  284. Configurator *config = Configurator::GetInstance();
  285. Target code_target = config->target();
  286. CodeMode code_mode = config->code_mode();
  287. uint32_t nodes_size = model->all_nodes_.size();
  288. OpCoderBuilder builder;
  289. for (uint32_t i = 0; i < nodes_size; ++i) {
  290. const auto *node = model->all_nodes_.at(i);
  291. if (node == nullptr) {
  292. MS_LOG(ERROR) << "node is nullptr";
  293. return RET_ERROR;
  294. }
  295. std::vector<lite::Tensor *> all_tensors = coder_graph_->all_tensors();
  296. if (all_tensors.empty()) {
  297. MS_LOG(ERROR) << "coder_graph has no any tensors";
  298. return RET_ERROR;
  299. }
  300. // set op_coder's inputs && outputs info
  301. std::vector<uint32_t> input_indices;
  302. Uint32Vector node_input_indices = node->input_indices_;
  303. input_indices.insert(input_indices.end(), node_input_indices.begin(), node_input_indices.end());
  304. std::vector<uint32_t> output_indices;
  305. Uint32Vector node_output_indices = node->output_indices_;
  306. output_indices.insert(output_indices.end(), node_output_indices.begin(), node_output_indices.end());
  307. std::vector<lite::Tensor *> inputs;
  308. std::vector<lite::Tensor *> outputs;
  309. for (auto in_index : input_indices) {
  310. in_index = static_cast<size_t>(in_index);
  311. if (in_index > all_tensors.size()) {
  312. MS_LOG(ERROR) << "in_index is invalid";
  313. return RET_ERROR;
  314. }
  315. inputs.push_back(all_tensors.at(in_index));
  316. }
  317. for (auto ou_index : output_indices) {
  318. ou_index = static_cast<size_t>(ou_index);
  319. if (ou_index > all_tensors.size()) {
  320. MS_LOG(ERROR) << "ou_index is invalid";
  321. return RET_ERROR;
  322. }
  323. outputs.push_back(all_tensors.at(ou_index));
  324. }
  325. if (inputs.empty()) {
  326. MS_LOG(ERROR) << "node: " << node->name_ << "has no inputs tensor";
  327. return RET_ERROR;
  328. }
  329. if (outputs.empty()) {
  330. MS_LOG(ERROR) << "node: " << node->name_ << "has no outputs tensor";
  331. return RET_ERROR;
  332. }
  333. TypeId tensor_data_type = inputs.at(0)->data_type();
  334. std::unique_ptr<OperatorCoder> op_coder = builder.inputs(inputs)
  335. .outputs(outputs)
  336. .node(node)
  337. .target(code_target)
  338. .data_type(tensor_data_type)
  339. .mode(code_mode)
  340. .input_indices(input_indices)
  341. .output_indices(output_indices)
  342. .build();
  343. MS_CHECK_PTR(op_coder);
  344. op_coders_.push_back(std::move(op_coder));
  345. builder.Reset();
  346. }
  347. InitOpcodersInputsAndOutputs();
  348. return RET_OK;
  349. }
  350. int CoderSession::InitGraphInOutTensors() {
  351. const Model *model = coder_graph_->model();
  352. if (model == nullptr) {
  353. return RET_ERROR;
  354. }
  355. std::vector<size_t> graph_input_node_indexes = lite::GetGraphInputNodes(model);
  356. std::vector<uint32_t> input_indices;
  357. for (auto in_node_index : graph_input_node_indexes) {
  358. in_node_index = static_cast<uint32_t>(in_node_index);
  359. auto *in_node = model->all_nodes_.at(in_node_index);
  360. if (in_node == nullptr) {
  361. return RET_ERROR;
  362. }
  363. for (uint32_t i = 0; i < in_node->input_indices_.size(); i++) {
  364. auto in_tensor_index = size_t(in_node->input_indices_.at(i));
  365. bool is_graph_input = false;
  366. for (uint32_t j = 0; j < model->sub_graphs_.at(0)->input_indices_.size(); j++) {
  367. if (in_tensor_index == size_t(model->sub_graphs_.at(0)->input_indices_.at(j))) {
  368. input_indices.push_back(static_cast<uint32_t>(in_tensor_index));
  369. is_graph_input = true;
  370. break;
  371. }
  372. }
  373. if (!is_graph_input) {
  374. continue;
  375. }
  376. if (in_tensor_index < coder_graph_->all_tensors().size()) {
  377. lite::Tensor *in_tensor = this->coder_graph_->all_tensors().at(in_tensor_index);
  378. coder_graph_->AddInputMap(in_node->name_, in_tensor);
  379. }
  380. }
  381. }
  382. coder_graph_->SetInputIndices(input_indices);
  383. std::vector<uint32_t> output_indices;
  384. auto graph_output_node_indexes = lite::GetGraphOutputNodes(model);
  385. for (auto out_node_index : graph_output_node_indexes) {
  386. out_node_index = static_cast<uint32_t>(out_node_index);
  387. auto *out_node = model->all_nodes_.at(out_node_index);
  388. for (uint32_t i = 0; i < out_node->output_indices_.size(); i++) {
  389. auto out_tensor_index = size_t(out_node->output_indices_.at(i));
  390. bool is_graph_output = false;
  391. for (uint32_t j = 0; j < model->sub_graphs_.at(0)->output_indices_.size(); j++) {
  392. if (out_tensor_index == size_t(model->sub_graphs_.at(0)->output_indices_.at(j))) {
  393. output_indices.push_back(static_cast<uint32_t>(out_tensor_index));
  394. is_graph_output = true;
  395. break;
  396. }
  397. }
  398. if (!is_graph_output) {
  399. continue;
  400. }
  401. if (out_tensor_index < coder_graph_->all_tensors().size()) {
  402. lite::Tensor *out_tensor = this->coder_graph_->all_tensors().at(out_tensor_index);
  403. if (out_tensor == nullptr) {
  404. MS_LOG(ERROR) << "can not find any output tensor in all_tensors";
  405. return RET_ERROR;
  406. }
  407. coder_graph_->AddOutputMap(out_node->name_, out_tensor);
  408. }
  409. }
  410. }
  411. coder_graph_->SetOutputIndices(output_indices);
  412. coder_graph_->InitInputs();
  413. coder_graph_->InitOutputs();
  414. return RET_OK;
  415. }
  416. int CoderSession::CompileGraph() {
  417. MS_LOG(INFO) << "CompileGraph";
  418. MS_CHECK_RET_CODE(ConvertTensors(), "ConvertTensors failed");
  419. MS_CHECK_RET_CODE(InitGraphInOutTensors(), "InitGraphInOutTensors failed");
  420. MS_CHECK_RET_CODE(InferShape(), "do infershape failed!");
  421. MS_CHECK_RET_CODE(CreateOpCoders(), "CreateOpCoders failed!");
  422. MS_CHECK_RET_CODE(InitTensorsRef(), "InitTensorsRefcount failed!");
  423. return RET_OK;
  424. }
  425. std::shared_ptr<CoderSession> CreateCoderSession() {
  426. auto session = std::make_shared<CoderSession>();
  427. return session;
  428. }
  429. CoderSession::~CoderSession() { allocator_->Free(); }
  430. } // namespace mindspore::lite::micro