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 12 kB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  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 <vector>
  19. #include <utility>
  20. #include "coder/context.h"
  21. #include "coder/train.h"
  22. #include "coder/allocator/allocator.h"
  23. #include "coder/generator/generator.h"
  24. #include "coder/generator/inference/inference_generator.h"
  25. #include "coder/generator/train/train_generator.h"
  26. #include "coder/opcoders/op_coder_builder.h"
  27. #include "coder/utils/coder_utils.h"
  28. #include "coder/log.h"
  29. #include "src/ops/populate/populate_register.h"
  30. #include "src/common/version_manager.h"
  31. #include "src/runtime/infer_manager.h"
  32. #include "src/scheduler.h"
  33. #include "include/errorcode.h"
  34. #include "include/model.h"
  35. #include "src/common/file_utils.h"
  36. #include "coder/opcoders/nnacl/dequant/de_quant.h"
  37. namespace mindspore::lite::micro {
  38. CoderSession::CoderSession() { allocator_ = MemoryAllocator::GetInstance(); }
  39. void CoderSession::EndCode() {
  40. context_->set_tensor_map(allocator_->tensors_map());
  41. context_->set_saved_weights(allocator_->saved_weights());
  42. size_t de_quant_max_workspace_size = nnacl::Dequant::GetInstance()->de_quant_max_workspace();
  43. size_t final_total_size = allocator_->total_buffer_size() > de_quant_max_workspace_size
  44. ? allocator_->total_buffer_size()
  45. : de_quant_max_workspace_size;
  46. context_->set_total_buffer_size(final_total_size);
  47. context_->set_graph_inputs(coder_graph_->input_tensors());
  48. context_->set_graph_outputs(coder_graph_->output_tensors());
  49. Configurator *config = Configurator::GetInstance();
  50. if (config->debug_mode()) {
  51. std::vector<std::string> blocks;
  52. blocks = AddDumpDataInfo(context_->code_blocks(), op_coders_);
  53. context_->set_code_blocks(blocks);
  54. }
  55. if (config->code_mode() == Train) {
  56. Train::TransformGraphForTrain(context_.get(), op_coders_);
  57. }
  58. }
  59. int CoderSession::Run() {
  60. MS_LOG(INFO) << "start run opcoders";
  61. // 1. assign memory
  62. std::vector<lite::Tensor *> inputs = coder_graph_->input_tensors();
  63. int ret = allocator_->Assign(inputs, op_coders_);
  64. MS_CHECK_RET_CODE(ret, "assign memory failed");
  65. // 2. prepare, init model parameters
  66. for (const auto &op_coder : op_coders_) {
  67. MS_CHECK_PTR(op_coder);
  68. MS_LOG(DEBUG) << "prepare: " << op_coder->name();
  69. ret = op_coder->Prepare(context_.get());
  70. MS_CHECK_RET_CODE(ret, "prepare coder " << op_coder->name() << " failed");
  71. allocator_->enable_is_next();
  72. }
  73. // 3. docode, write operator code
  74. for (const auto &op_coder : op_coders_) {
  75. MS_CHECK_PTR(op_coder);
  76. MS_LOG(DEBUG) << "code: " << op_coder->name();
  77. ret = op_coder->DoCode(this->context_.get());
  78. MS_CHECK_RET_CODE(ret, "do coder " << op_coder->name() << " failed");
  79. }
  80. this->EndCode();
  81. MS_LOG(INFO) << "run opcoders success";
  82. return RET_OK;
  83. }
  84. int CoderSession::GenerateCode() {
  85. MS_LOG(INFO) << "CoderSession::GenerateCode start";
  86. std::shared_ptr<Generator> generator;
  87. Configurator *config = Configurator::GetInstance();
  88. CodeMode code_mode = config->code_mode();
  89. switch (code_mode) {
  90. case Inference:
  91. MS_LOG(INFO) << "generate code for Inference";
  92. generator = std::make_shared<InferenceGenerator>(std::move(context_));
  93. break;
  94. case Train:
  95. MS_LOG(INFO) << "generate code for Train";
  96. generator = std::make_shared<TrainGenerator>(std::move(context_));
  97. break;
  98. default:
  99. MS_LOG(ERROR) << "unsupported generator code mode, " << code_mode;
  100. return RET_ERROR;
  101. }
  102. // when use file, coder context need to remove initial parameters from tensors info
  103. // we use tmp_tensor_list to storage
  104. MS_CHECK_PTR(generator);
  105. int ret = generator->GenerateCode();
  106. if (ret != RET_OK) {
  107. MS_LOG(ERROR) << "generate code failed";
  108. }
  109. MS_LOG(INFO) << "CoderSession::GenerateCode done";
  110. return ret;
  111. }
  112. int CoderSession::Init(const std::string &model_path) {
  113. MS_LOG(INFO) << "CoderSession::Init start";
  114. // Load graph
  115. MS_LOG(DEBUG) << "start reading model file";
  116. size_t size = 0;
  117. char *graph_buf = ReadFile(model_path.c_str(), &size);
  118. if (graph_buf == nullptr) {
  119. MS_LOG(ERROR) << "read model file from path \"" << model_path << "\" failed.";
  120. return RET_ERROR;
  121. }
  122. // new a context for session
  123. if (size >= UINT_MAX) {
  124. MS_LOG(ERROR) << "the size is invalid";
  125. delete[] graph_buf;
  126. return RET_ERROR;
  127. }
  128. Model *model = lite::Model::Import(graph_buf, size);
  129. delete[] graph_buf;
  130. MS_CHECK_PTR(model);
  131. coder_graph_ = std::make_unique<CoderGraph>(model);
  132. context_ = std::make_unique<CoderContext>();
  133. MS_LOG(INFO) << "CoderSession::Init done";
  134. return RET_OK;
  135. }
  136. int CoderSession::Build() {
  137. if (coder_graph_ == nullptr) {
  138. return RET_ERROR;
  139. }
  140. int ret = this->CompileGraph();
  141. if (ret != RET_OK) {
  142. MS_LOG(ERROR) << "CompileGraph failed: " << ret;
  143. return ret;
  144. }
  145. return RET_OK;
  146. }
  147. int CoderSession::InitOpcodersInputsAndOutputs() {
  148. std::map<Tensor *, OperatorCoder *> input_node_map;
  149. std::map<Tensor *, OperatorCoder *> output_node_map;
  150. for (const auto &op_coder : op_coders_) {
  151. std::vector<Tensor *> inputs = op_coder->input_tensors();
  152. std::for_each(inputs.begin(), inputs.end(),
  153. [&](Tensor *t) { input_node_map.insert(std::make_pair(t, op_coder.get())); });
  154. std::vector<Tensor *> outputs = op_coder->input_tensors();
  155. std::for_each(outputs.begin(), outputs.end(),
  156. [&](Tensor *t) { output_node_map.insert(std::make_pair(t, op_coder.get())); });
  157. }
  158. for (const auto &op_coder : op_coders_) {
  159. std::vector<Tensor *> inputs = op_coder->input_tensors();
  160. for (const auto &tensor : inputs) {
  161. auto item = output_node_map.find(tensor);
  162. if (item != output_node_map.end()) {
  163. op_coder->AddInputOp(item->second);
  164. }
  165. }
  166. std::vector<Tensor *> outputs = op_coder->output_tensors();
  167. for (const auto &tensor : outputs) {
  168. auto item = input_node_map.find(tensor);
  169. if (item != input_node_map.end()) {
  170. op_coder->AddOutputOp(item->second);
  171. }
  172. }
  173. }
  174. return RET_OK;
  175. }
  176. int CoderSession::InitTensorsRef() {
  177. auto all_tensors = coder_graph_->all_tensors();
  178. for (auto &tensor : all_tensors) {
  179. size_t refcount = 0;
  180. for (const auto &node : this->op_coders_) {
  181. auto inputs = node->input_tensors();
  182. auto iter = std::find(inputs.begin(), inputs.end(), tensor);
  183. if (iter != inputs.end()) {
  184. refcount++;
  185. }
  186. }
  187. tensor->set_ref_count(refcount);
  188. }
  189. return RET_OK;
  190. }
  191. OpParameter *CoderSession::GenParameterAndInfer(const Model::Node *node, const std::vector<lite::Tensor *> &inputs,
  192. std::vector<lite::Tensor *> *outputs) const {
  193. auto primitive = node->primitive_;
  194. MS_CHECK_PTR_RET_NULL(primitive);
  195. int schema_version = VersionManager::GetInstance()->GetSchemaVersion();
  196. auto parame_gen = PopulateRegistry::GetInstance()->GetParameterCreator(GetPrimitiveType(primitive), schema_version);
  197. MS_CHECK_PTR_RET_NULL(parame_gen);
  198. auto parameter = parame_gen(primitive);
  199. MS_CHECK_PTR_RET_NULL(parameter);
  200. auto ret = KernelInferShape(inputs, *outputs, parameter);
  201. if (ret == RET_INFER_INVALID) {
  202. MS_LOG(INFO) << "InferShape shouldn't be done before runtime, name: " << node->name_
  203. << ", type: " << PrimitiveTypeName(GetPrimitiveType(primitive)) << "flag set to false.";
  204. } else if (ret != RET_OK) {
  205. MS_LOG(ERROR) << "InferShape failed, name: " << node->name_
  206. << ", type: " << PrimitiveTypeName(GetPrimitiveType(primitive));
  207. return nullptr;
  208. }
  209. return parameter;
  210. }
  211. int CoderSession::CreateOpCoders() {
  212. const Model *model = coder_graph_->model();
  213. if (model == nullptr) {
  214. MS_LOG(ERROR) << "Graph model is nullptr";
  215. return RET_ERROR;
  216. }
  217. Configurator *config = Configurator::GetInstance();
  218. Target code_target = config->target();
  219. CodeMode code_mode = config->code_mode();
  220. bool support_parallel = config->support_parallel();
  221. uint32_t nodes_size = model->all_nodes_.size();
  222. OpCoderBuilder builder;
  223. for (uint32_t i = 0; i < nodes_size; ++i) {
  224. const auto *node = model->all_nodes_.at(i);
  225. if (node == nullptr) {
  226. MS_LOG(ERROR) << "node is nullptr";
  227. return RET_ERROR;
  228. }
  229. std::vector<lite::Tensor *> all_tensors = coder_graph_->all_tensors();
  230. if (all_tensors.empty()) {
  231. MS_LOG(ERROR) << "coder_graph has no any tensors";
  232. return RET_ERROR;
  233. }
  234. // set op_coder's inputs && outputs info
  235. std::vector<uint32_t> input_indices;
  236. Uint32Vector node_input_indices = node->input_indices_;
  237. input_indices.insert(input_indices.end(), node_input_indices.begin(), node_input_indices.end());
  238. std::vector<uint32_t> output_indices;
  239. Uint32Vector node_output_indices = node->output_indices_;
  240. output_indices.insert(output_indices.end(), node_output_indices.begin(), node_output_indices.end());
  241. std::vector<lite::Tensor *> inputs;
  242. std::vector<lite::Tensor *> outputs;
  243. for (auto in_index : input_indices) {
  244. in_index = static_cast<size_t>(in_index);
  245. if (in_index > all_tensors.size()) {
  246. MS_LOG(ERROR) << "in_index is invalid";
  247. return RET_ERROR;
  248. }
  249. inputs.push_back(all_tensors.at(in_index));
  250. }
  251. for (auto ou_index : output_indices) {
  252. ou_index = static_cast<size_t>(ou_index);
  253. if (ou_index > all_tensors.size()) {
  254. MS_LOG(ERROR) << "ou_index is invalid";
  255. return RET_ERROR;
  256. }
  257. outputs.push_back(all_tensors.at(ou_index));
  258. }
  259. if (inputs.empty()) {
  260. MS_LOG(ERROR) << "node: " << node->name_ << "has no inputs tensor";
  261. return RET_ERROR;
  262. }
  263. if (outputs.empty()) {
  264. MS_LOG(ERROR) << "node: " << node->name_ << "has no outputs tensor";
  265. return RET_ERROR;
  266. }
  267. OpParameter *parameter = GenParameterAndInfer(node, inputs, &outputs);
  268. MS_CHECK_PTR(parameter);
  269. TypeId tensor_data_type = inputs.at(0)->data_type();
  270. std::unique_ptr<OperatorCoder> op_coder = builder.inputs(inputs)
  271. .outputs(outputs)
  272. .node(node)
  273. .parameter(parameter)
  274. .target(code_target)
  275. .support_parallel(support_parallel)
  276. .data_type(tensor_data_type)
  277. .mode(code_mode)
  278. .input_indices(input_indices)
  279. .output_indices(output_indices)
  280. .build();
  281. if (op_coder == nullptr) {
  282. coder_graph_->DumpUnSupportLayer(code_target);
  283. return RET_ERROR;
  284. }
  285. op_coders_.push_back(std::move(op_coder));
  286. builder.Reset();
  287. }
  288. InitOpcodersInputsAndOutputs();
  289. return RET_OK;
  290. }
  291. int CoderSession::InitCodeGraph() {
  292. MS_CHECK_RET_CODE(coder_graph_->ConvertTensors(), "convert tensors failed");
  293. MS_CHECK_RET_CODE(coder_graph_->InitGraphInOutTensors(), "init graph inputs and outputs failed");
  294. return RET_OK;
  295. }
  296. int CoderSession::CompileGraph() {
  297. MS_LOG(INFO) << "CompileGraph";
  298. MS_CHECK_RET_CODE(InitCodeGraph(), "InitGraphInOutTensors failed");
  299. MS_CHECK_RET_CODE(CreateOpCoders(), "CreateOpCoders failed!");
  300. MS_CHECK_RET_CODE(InitTensorsRef(), "InitTensorsRefcount failed!");
  301. return RET_OK;
  302. }
  303. std::shared_ptr<CoderSession> CreateCoderSession() {
  304. auto session = std::make_shared<CoderSession>();
  305. return session;
  306. }
  307. CoderSession::~CoderSession() { allocator_->Free(); }
  308. } // namespace mindspore::lite::micro