• 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/generator/component/common_component.h"
18 #include <memory>
19 #include "coder/generator/component/const_blocks/license.h"
20 #include "coder/generator/component/component.h"
21 #include "coder/utils/type_cast.h"
22 #include "coder/utils/coder_utils.h"
23 #include "coder/log.h"
24 #include "include/errorcode.h"
25 #include "nnacl/op_base.h"
26 
27 namespace mindspore::lite::micro {
CodeSessionCompileGraph(std::ofstream & ofs,const std::unique_ptr<CoderContext> & ctx,const Configurator * config)28 void CodeSessionCompileGraph(std::ofstream &ofs, const std::unique_ptr<CoderContext> &ctx, const Configurator *config) {
29   auto array_tostring = [&ofs](const std::vector<int> &array, const std::string &name) {
30     size_t num = array.size();
31     ofs << "  Vector<int32_t> " << name << ";\n";
32     ofs << "  " << name << ".resize(" << num << ");\n";
33     for (size_t i = 0; i < num; ++i) {
34       ofs << "  " << name << "[" << i << "] = " << array[i] << ";\n";
35     }
36   };
37   std::vector<Tensor *> inputs = ctx->graph_inputs();
38   std::vector<Tensor *> outputs = ctx->graph_outputs();
39   size_t inputs_size = inputs.size();
40   size_t outputs_size = outputs.size();
41   ofs << kNameSpaceMindSpore << " {\n";
42   ofs << kNameSpaceLite << " {\n";
43   ofs << "int LiteSession::CompileGraph(lite::Model *model) {\n";
44   ofs << "  inputs_.resize(" << inputs_size << ");\n";
45   for (size_t i = 0; i < inputs_size; ++i) {
46     Tensor *input = inputs[i];
47     std::string shape_i = "in_shape_" + std::to_string(i);
48     array_tostring(input->shape(), shape_i);
49     ofs << "  inputs_[" << i << "] = new (std::nothrow) MTensor(String(\"" << input->tensor_name() << "\"), "
50         << EnumNameDataType(input->data_type()) << ", " << shape_i << ");\n";
51     ofs << "  MS_ERROR_IF_NULL(inputs_[" << i << "]);\n";
52   }
53   ofs << "  outputs_.resize(" << outputs_size << ");\n";
54   for (size_t i = 0; i < outputs_size; ++i) {
55     Tensor *output = outputs[i];
56     std::string shape_i = "out_shape_" + std::to_string(i);
57     array_tostring(output->shape(), shape_i);
58     ofs << "  outputs_[" << i << "] = new (std::nothrow) MTensor(String(\"" << output->tensor_name() << "\"), "
59         << EnumNameDataType(output->data_type()) << ", " << shape_i << ");\n";
60     ofs << "  MS_ERROR_IF_NULL(outputs_[" << i << "]);\n";
61   }
62   if (config->target() != kARM32M) {
63     ofs << "  int ret = Init(model->buf, static_cast<MModel *>(model)->buf_size());\n"
64            "  return ret;\n"
65            "}\n\n";
66     return;
67   }
68   ofs << "  return RET_OK;\n";
69   ofs << "}\n\n";
70 }
71 
CodeCreateSessionImplement(std::ofstream & ofs,const Configurator * config)72 void CodeCreateSessionImplement(std::ofstream &ofs, const Configurator *config) {
73   ofs << "session::LiteSession *session::LiteSession::CreateSession(const lite::Context *context) {\n"
74          "  auto *session = new (std::nothrow) lite::LiteSession();\n"
75          "  MS_NULLPTR_IF_NULL(session);\n"
76          "  int ret = session->InitRuntimeBuffer();\n"
77          "  MS_NULLPTR_IF_ERROR(ret);\n";
78   if (config->support_parallel()) {
79     ofs << "  MS_NULLPTR_IF_NULL(context);\n"
80            "  ret = CreateThreadPool(context->thread_num_);\n"
81            "  MS_NULLPTR_IF_ERROR(ret);\n"
82            "  SetCoreAffinity(context->device_list_[0].device_info_.cpu_device_info_.cpu_bind_mode_);\n";
83   }
84   ofs << "  return session;\n"
85          "}\n\n";
86   ofs << "session::LiteSession *session::LiteSession::CreateSession(const char *model_buf, size_t size,\n"
87          "                                                          const lite::Context *context) {\n"
88          "  session::LiteSession *session = CreateSession(context);\n"
89          "  MS_NULLPTR_IF_NULL(session);\n"
90          "  lite::Model *model = lite::Model::Import(model_buf, size);\n"
91          "  int ret = session->CompileGraph(model);\n"
92          "  MS_NULLPTR_IF_ERROR(ret);\n"
93          "  delete model;\n"
94          "  return session;\n"
95          "}\n"
96          "}  // namespace mindspore\n\n";
97 }
98 
CodeCreateSessionDestructor(std::ofstream & ofs,const Configurator * config)99 void CodeCreateSessionDestructor(std::ofstream &ofs, const Configurator *config) {
100   ofs << "LiteSession::~LiteSession() {\n"
101          "  FreeResource();\n"
102          "  if (runtime_buffer_ != nullptr) {\n"
103          "    free(runtime_buffer_);\n"
104          "    runtime_buffer_ = nullptr;\n"
105          "  }\n"
106          "  for (auto &input : inputs_) {\n"
107          "    if (input == nullptr) {\n"
108          "      continue;\n"
109          "    }\n"
110          "    delete input;\n"
111          "    input = nullptr;\n"
112          "  }\n"
113          "  for (auto &output : outputs_) {\n"
114          "    if (output == nullptr) {\n"
115          "      continue;\n"
116          "    }\n"
117          "    delete output;\n"
118          "    output = nullptr;\n"
119          "  }\n";
120   if (config->support_parallel()) {
121     ofs << "  ClearThreadPool();\n";
122   }
123   ofs << "}\n";
124 }
125 
CodeCopyOutputsState(std::ofstream & ofs)126 void CodeCopyOutputsState(std::ofstream &ofs) { ofs << "int CopyOutputsData(void **outputs, int num);\n\n"; }
127 
CodeCopyOutputsImplement(std::ofstream & ofs,const std::unique_ptr<CoderContext> & ctx)128 void CodeCopyOutputsImplement(std::ofstream &ofs, const std::unique_ptr<CoderContext> &ctx) {
129   auto tensor_map = ctx->tensors_map();
130   std::vector<Tensor *> outputs = ctx->graph_outputs();
131   size_t outputs_size = outputs.size();
132 
133   ofs << "int CopyOutputsData(void **outputs, int num) {\n"
134          "  if (outputs == NULL) {\n"
135          "    return RET_ERROR;\n"
136          "  }\n"
137       << "  if (num != " << outputs_size << ") {\n"
138       << "    return RET_ERROR;\n"
139          "  }\n";
140   for (size_t i = 0; i < outputs_size; ++i) {
141     Tensor *output = outputs[i];
142     MS_CHECK_PTR_IF_NULL(output);
143     ofs << "  memcpy(outputs[" << i << "], " << tensor_map[output] << ", " << output->Size() << ");\n";
144   }
145   ofs << "  return RET_OK;\n"
146          "}\n\n";
147 }
148 
CodeInputState(std::ofstream & ofs)149 void CodeInputState(std::ofstream &ofs) {
150   ofs << "/**\n"
151       << "  * set input tensors\n"
152       << "  * @param inputs, the input data ptr's array of the model, the tensors' count of input may be greater than "
153          "one.\n"
154       << "  * @param num, the input data's number of the model.\n"
155       << "  **/\n"
156       << "int "
157       << "SetInputs(const void **inputs, int num);\n\n";
158 }
159 
CodeInputImplement(std::ofstream & ofs,const std::unique_ptr<CoderContext> & ctx)160 void CodeInputImplement(std::ofstream &ofs, const std::unique_ptr<CoderContext> &ctx) {
161   // input tensors
162   std::vector<Tensor *> inputs = ctx->graph_inputs();
163   for (size_t i = 0; i < inputs.size(); ++i) {
164     ofs << "static const unsigned char *" << ctx->input_name() + std::to_string(i) << " = 0;\n";
165   }
166   size_t size = inputs.size();
167   ofs << "int "
168       << "SetInputs(const void **inputs, int num) {\n"
169       << "  if (inputs == NULL) {\n"
170          "    return RET_ERROR;\n"
171          "  }\n"
172       << "  if (num !=" << size << ") {\n"
173       << "    return RET_ERROR;\n"
174          "  }\n";
175   for (size_t i = 0; i < size; ++i) {
176     ofs << "\t" << ctx->input_name() << i << " = inputs[" << i << "];\n";
177   }
178   ofs << "  return RET_OK;\n}\n";
179 }
180 
CodeGraphQuantArgsState(std::ofstream & ofs)181 void CodeGraphQuantArgsState(std::ofstream &ofs) {
182   ofs << "/**\n"
183       << "  * get input and output QuantArgs of the model \n"
184       << "  **/\n"
185       << "GraphQuantArgs "
186       << "GetInOutQuantArgs();\n\n";
187 }
188 
CodeGraphQuantArgsImplement(std::ofstream & ofs,const std::unique_ptr<CoderContext> & ctx)189 void CodeGraphQuantArgsImplement(std::ofstream &ofs, const std::unique_ptr<CoderContext> &ctx) {
190   std::vector<Tensor *> graph_inputs = ctx->graph_inputs();
191   if (graph_inputs.empty()) {
192     MS_LOG(ERROR) << "graph input tensors' number is 0";
193     return;
194   }
195   Tensor *in_tensor = graph_inputs.at(kInputIndex);
196   MS_CHECK_PTR_IF_NULL(in_tensor);
197   std::vector<Tensor *> graph_outputs = ctx->graph_outputs();
198   if (graph_outputs.empty()) {
199     MS_LOG(ERROR) << "graph output tensors' number is 0";
200     return;
201   }
202   Tensor *out_tensor = graph_outputs.at(kOutputIndex);
203   MS_CHECK_PTR_IF_NULL(out_tensor);
204   std::vector<LiteQuantParam> in_quant_args = in_tensor->quant_params();
205   std::vector<LiteQuantParam> out_quant_args = out_tensor->quant_params();
206   if (in_quant_args.empty() || out_quant_args.empty()) {
207     MS_LOG(ERROR) << "code model quant args failed";
208     return;
209   }
210   ofs << "GraphQuantArgs "
211       << "GetInOutQuantArgs() {\n"
212       << "\t\tGraphQuantArgs quan_args = { " << in_quant_args.at(0).scale << ", " << out_quant_args.at(0).scale << ", "
213       << in_quant_args.at(0).zeroPoint << ", " << out_quant_args.at(0).zeroPoint << "};\n"
214       << "\t\treturn quan_args;\n"
215       << "}\n";
216 }
217 
CodeManageResourceState(std::ofstream & ofs)218 void CodeManageResourceState(std::ofstream &ofs) {
219   ofs << "/**\n"
220       << "  * get the memory space size of the inference.\n"
221       << "  **/\n"
222       << "int "
223       << "GetBufferSize();\n";
224 
225   ofs << "/**\n"
226       << "  * set the memory space for the inference\n"
227       << "  **/\n"
228       << "int "
229       << "SetBuffer(void *buffer);\n\n";
230 
231   ofs << "/**\n"
232       << "  * free the memory of packed weights, and set the membuf buffer and input address to NULL\n"
233       << "  **/\n"
234       << "void "
235       << "FreeResource();\n";
236 }
237 
CodeInitResourceImplement(std::ofstream & ofs,const std::unique_ptr<CoderContext> & ctx)238 void CodeInitResourceImplement(std::ofstream &ofs, const std::unique_ptr<CoderContext> &ctx) {
239   ofs << "int "
240       << "GetBufferSize() {\n"
241       << "  return " << ctx->total_buffer_size() << ";\n"
242       << "}\n";
243   ofs << "int "
244       << "SetBuffer( void *buffer) {\n";
245   ofs << "  if (buffer == NULL) {\n"
246          "    return RET_ERROR;\n"
247          "  }\n";
248   ofs << "  " << ctx->buffer_name() << " = buffer;\n"
249       << "  return RET_OK;\n"
250          "}\n";
251 }
252 
CodeFreeResourceImplement(std::ofstream & ofs,const std::unique_ptr<CoderContext> & ctx)253 void CodeFreeResourceImplement(std::ofstream &ofs, const std::unique_ptr<CoderContext> &ctx) {
254   ofs << "void "
255       << "FreeResource() {\n";
256   ofs << "  " << ctx->buffer_name() << "= NULL;\n";
257   std::vector<Tensor *> inputs = ctx->graph_inputs();
258   size_t size = inputs.size();
259   for (size_t i = 0; i < size; ++i) {
260     ofs << "  " << ctx->input_name() + std::to_string(i) << " = NULL;\n";
261   }
262   ofs << "  void *allocated[] = {";
263   size_t num = 0;
264   for (const auto &item : ctx->tensors_map()) {
265     Tensor *tensor = item.first;
266     std::string name = item.second;
267     if (tensor->data() != nullptr && !(CheckConstantTensor(tensor))) {
268       ofs << name << ", ";
269       num++;
270     }
271   }
272   ofs << "  };\n";
273   ofs << "  for (int i = 0; i < " << num << "; ++i) {\n"
274       << "    free(allocated[i]);\n"
275       << "    allocated[i] = NULL;\n"
276       << "  }\n";
277   ofs << "}\n";
278 }
279 
CodeInferenceState(std::ofstream & ofs)280 void CodeInferenceState(std::ofstream &ofs) {
281   ofs << "/**\n"
282       << "  * net inference function\n"
283       << "  **/\n"
284       << "void "
285       << "Inference();\n\n";
286 }
287 }  // namespace mindspore::lite::micro
288