• 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/const_blocks/benchmark.h"
18 
19 namespace mindspore::lite::micro {
20 const char benchmark_source[] = R"RAW(
21 /**
22  * Copyright 2021 Huawei Technologies Co., Ltd
23  *
24  * Licensed under the Apache License, Version 2.0 (the "License");
25  * you may not use this file except in compliance with the License.
26  * You may obtain a copy of the License at
27  *
28  * http://www.apache.org/licenses/LICENSE-2.0
29  *
30  * Unless required by applicable law or agreed to in writing, software
31  * distributed under the License is distributed on an "AS IS" BASIS,
32  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
33  * See the License for the specific language governing permissions and
34  * limitations under the License.
35  */
36 
37 #include <iostream>
38 #include <string>
39 #include <cstring>
40 
41 #include "include/lite_session.h"
42 #include "include/ms_tensor.h"
43 #include "include/errorcode.h"
44 
45 #include "load_input.h"
46 #include "calib_output.h"
47 
48 using namespace mindspore;
49 
50 void usage() {
51   printf(
52     "-- mindspore benchmark params usage:\n"
53     "args[0]: executable file\n"
54     "args[1]: inputs binary file\n"
55     "args[2]: model weight binary file\n"
56     "args[3]: loop count for performance test\n"
57     "args[4]: calibration file\n"
58     "args[5]: runtime thread num\n"
59     "args[6]: runtime thread bind mode\n\n");
60 }
61 
62 uint64_t GetTimeUs() {
63   const int USEC = 1000000;
64   const int MSEC = 1000;
65   struct timespec ts = {0, 0};
66   if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
67     return 0;
68   }
69   uint64_t retval = (uint64_t)((ts.tv_sec * USEC) + (ts.tv_nsec / MSEC));
70   return retval;
71 }
72 
73 template <typename T>
74 void PrintData(void *data, size_t data_number) {
75   if (data == nullptr) {
76     return;
77   }
78   auto casted_data = static_cast<T *>(data);
79   for (size_t i = 0; i < 10 && i < data_number; i++) {
80     printf("%s, ", std::to_string(casted_data[i]).c_str());
81   }
82   printf("\n");
83 }
84 
85 void TensorToString(tensor::MSTensor *tensor) {
86   printf("name: %s, ", tensor->tensor_name().c_str());
87   printf("DataType: %d, ", tensor->data_type());
88   printf("Elements: %d, ", tensor->ElementsNum());
89   printf("Shape: [");
90   for (auto &dim : tensor->shape()) {
91     printf("%d ", dim);
92   }
93   printf("], Data: \n");
94   switch (tensor->data_type()) {
95     case kNumberTypeFloat32: {
96       PrintData<float>(tensor->MutableData(), tensor->ElementsNum());
97     } break;
98     case kNumberTypeFloat16: {
99       PrintData<int16_t>(tensor->MutableData(), tensor->ElementsNum());
100     } break;
101     case kNumberTypeInt32: {
102       PrintData<int32_t>(tensor->MutableData(), tensor->ElementsNum());
103     } break;
104     case kNumberTypeInt16: {
105       PrintData<int16_t>(tensor->MutableData(), tensor->ElementsNum());
106     } break;
107     case kNumberTypeInt8: {
108       PrintData<int8_t>(tensor->MutableData(), tensor->ElementsNum());
109     } break;
110     case kNumberTypeUInt8: {
111       PrintData<uint8_t>(tensor->MutableData(), tensor->ElementsNum());
112     } break;
113     default:
114       std::cout << "Unsupported data type to print" << std::endl;
115       break;
116   }
117 }
118 
119 int main(int argc, const char **argv) {
120   if (argc < 2) {
121     printf("input command is invalid\n");
122     usage();
123     return lite::RET_ERROR;
124   }
125   printf("=======run benchmark======\n");
126 
127   const char *model_buffer = nullptr;
128   int model_size = 0;
129   // read .bin file by ReadBinaryFile;
130   if (argc >= 3) {
131     model_buffer = static_cast<const char *>(ReadInputData(argv[2], &model_size));
132   }
133 
134   lite::Context *context = nullptr;
135   if (argc >= 7) {
136     // config benchmark context
137     context = new (std::nothrow) lite::Context();
138     if (context == nullptr) {
139       return lite::RET_ERROR;
140     }
141     context->thread_num_ = atoi(argv[5]);
142     if (context->thread_num_ < 1) {
143       printf("Thread number error! It should be greater than 0\n");
144       return lite::RET_ERROR;
145     }
146     context->device_list_.resize(1);
147     context->device_list_[0].device_type_ = lite::DT_CPU;
148     context->device_list_[0].device_info_.cpu_device_info_.enable_float16_ = false;
149     lite::CpuBindMode bind_mode = static_cast<lite::CpuBindMode>(atoi(argv[6]));
150     if (bind_mode < lite::NO_BIND || bind_mode > lite::MID_CPU) {
151       printf("Thread bind mode error! 0: No bind, 1: Bind hign cpu, 2: Bind mid cpu.\n");
152       return lite::RET_ERROR;
153     }
154     context->device_list_[0].device_info_.cpu_device_info_.cpu_bind_mode_ = bind_mode;
155     printf("context: ThreadNum: %d, BindMode: %d\n", context->thread_num_,
156            context->device_list_[0].device_info_.cpu_device_info_.cpu_bind_mode_);
157   }
158 
159   session::LiteSession *session = mindspore::session::LiteSession::CreateSession(model_buffer, model_size, context);
160   if (session == nullptr) {
161     printf("create lite session failed\n");
162     return lite::RET_ERROR;
163   }
164   delete[] model_buffer;
165 
166   // set model inputs tensor data
167   Vector<tensor::MSTensor *> inputs = session->GetInputs();
168   size_t inputs_num = inputs.size();
169   void *inputs_binbuf[inputs_num];
170   int inputs_size[inputs_num];
171   for (size_t i = 0; i < inputs_num; ++i) {
172     inputs_size[i] = inputs[i]->Size();
173   }
174   int ret = ReadInputsFile(const_cast<char *>(argv[1]), inputs_binbuf, inputs_size, inputs_num);
175   if (ret != lite::RET_OK) {
176     delete session;
177     return lite::RET_ERROR;
178   }
179   for (size_t i = 0; i < inputs_num; ++i) {
180     void *input_data = inputs[i]->MutableData();
181     memcpy(input_data, inputs_binbuf[i], inputs_size[i]);
182   }
183 
184   if (argc >= 4) {
185     int loop_count = atoi(argv[3]);
186     printf("\nloop count: %d\n", loop_count);
187     uint64_t start_time = GetTimeUs();
188     for (int i = 0; i < loop_count; ++i) {
189       ret = session->RunGraph();
190       if (ret != lite::RET_OK) {
191         delete session;
192         return lite::RET_ERROR;
193       }
194     }
195     uint64_t end_time = GetTimeUs();
196     float total_time = (float)(end_time - start_time) / 1000.0f;
197     printf("total time: %.5fms, per time: %.5fms\n", total_time, total_time / loop_count);
198   }
199   ret = session->RunGraph();
200   if (ret != lite::RET_OK) {
201     delete session;
202     return lite::RET_ERROR;
203   }
204 
205   printf("\noutputs: \n");
206   Vector<String> outputs_name = session->GetOutputTensorNames();
207   Vector<tensor::MSTensor *> outputs;
208   for (const auto &name : outputs_name) {
209     auto output = session->GetOutputByTensorName(name);
210     outputs.push_back(output);
211     TensorToString(output);
212   }
213   if (argc >= 5) {
214     lite::Calibrator *calibrator = new (std::nothrow) lite::Calibrator();
215     if (calibrator == nullptr) {
216       delete session;
217       return lite::RET_NULL_PTR;
218     }
219     ret = calibrator->ReadCalibData(argv[4]);
220     if (ret != lite::RET_OK) {
221       delete session;
222       delete calibrator;
223       return lite::RET_ERROR;
224     }
225     ret = calibrator->CompareOutputs(outputs);
226     if (ret != lite::RET_OK) {
227       delete session;
228       delete calibrator;
229       return lite::RET_ERROR;
230     }
231     delete calibrator;
232   }
233   printf("========run success=======\n");
234   delete session;
235   session = nullptr;
236   if (context != nullptr) {
237     delete context;
238     context = nullptr;
239   }
240   for (size_t i = 0; i < inputs_num; ++i) {
241     free(inputs_binbuf[i]);
242     inputs_binbuf[i] = nullptr;
243   }
244   return lite::RET_OK;
245 }
246 
247 )RAW";
248 }  // namespace mindspore::lite::micro
249