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