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.

model_process.cc 11 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. /**
  2. * Copyright 2020 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 "serving/acl/model_process.h"
  17. #include <algorithm>
  18. #include <unordered_map>
  19. #include "include/infer_log.h"
  20. namespace mindspore {
  21. namespace inference {
  22. bool ModelProcess::LoadModelFromFile(const std::string &file_name, uint32_t &model_id) {
  23. aclError acl_ret = aclmdlLoadFromFile(file_name.c_str(), &model_id);
  24. if (acl_ret != ACL_ERROR_NONE) {
  25. MSI_LOG_ERROR << "Read model file failed, file name is " << file_name;
  26. return false;
  27. }
  28. MSI_LOG_INFO << "Load model success " << file_name;
  29. model_desc_ = aclmdlCreateDesc();
  30. acl_ret = aclmdlGetDesc(model_desc_, model_id);
  31. if (acl_ret != ACL_ERROR_NONE) {
  32. MSI_LOG_ERROR << "Read model desc failed";
  33. return false;
  34. }
  35. bool ret = InitInputsBuffer();
  36. if (!ret) {
  37. MSI_LOG_ERROR << "Create input buffer failed";
  38. return false;
  39. }
  40. ret = InitOutputsBuffer();
  41. if (!ret) {
  42. MSI_LOG_ERROR << "Create output buffer failed";
  43. return false;
  44. }
  45. model_id_ = model_id;
  46. return true;
  47. }
  48. bool ModelProcess::InitInputsBuffer() {
  49. aclError ret;
  50. inputs_ = aclmdlCreateDataset();
  51. if (inputs_ == nullptr) {
  52. MSI_LOG_ERROR << "Create input dataset failed";
  53. return false;
  54. }
  55. size_t input_size = aclmdlGetNumInputs(model_desc_);
  56. for (size_t i = 0; i < input_size; ++i) {
  57. auto buffer_size = aclmdlGetInputSizeByIndex(model_desc_, i);
  58. void *data_mem_buffer = nullptr;
  59. if (!is_run_on_device_) { // need to copy input/output to/from device
  60. ret = aclrtMalloc(&data_mem_buffer, buffer_size, ACL_MEM_MALLOC_NORMAL_ONLY);
  61. if (ret != ACL_ERROR_NONE) {
  62. MSI_LOG_ERROR << "Malloc device input buffer faild , input size " << buffer_size;
  63. return false;
  64. }
  65. }
  66. aclmdlIODims dims;
  67. ret = aclmdlGetInputDims(model_desc_, i, &dims);
  68. if (ret != ACL_ERROR_NONE) {
  69. MSI_LOG_ERROR << "Get input shape failed";
  70. return false;
  71. }
  72. aclDataType dataType = aclmdlGetInputDataType(model_desc_, i);
  73. std::vector<int64_t> shape(dims.dims, dims.dims + dims.dimCount);
  74. input_infos_.emplace_back(AclTensorInfo{data_mem_buffer, buffer_size, dataType, shape});
  75. }
  76. MSI_LOG_INFO << "Create model inputs success";
  77. return true;
  78. }
  79. bool ModelProcess::CreateDataBuffer(void *&data_mem_buffer, size_t buffer_size, aclmdlDataset *dataset) {
  80. aclError ret;
  81. auto free_data_buffer = [this](void *dataMemBuffer) {
  82. if (!is_run_on_device_) {
  83. aclrtFree(dataMemBuffer);
  84. } else {
  85. aclrtFreeHost(dataMemBuffer);
  86. }
  87. };
  88. if (!is_run_on_device_) {
  89. ret = aclrtMalloc(&data_mem_buffer, buffer_size, ACL_MEM_MALLOC_NORMAL_ONLY);
  90. if (ret != ACL_ERROR_NONE) {
  91. MSI_LOG_ERROR << "Malloc device buffer faild , buffer size " << buffer_size;
  92. return false;
  93. }
  94. } else {
  95. ret = aclrtMallocHost(&data_mem_buffer, buffer_size);
  96. if (ret != ACL_ERROR_NONE) {
  97. MSI_LOG_ERROR << "Malloc device buffer faild , buffer size " << buffer_size;
  98. return false;
  99. }
  100. }
  101. auto data_buffer = aclCreateDataBuffer(data_mem_buffer, buffer_size);
  102. if (data_buffer == nullptr) {
  103. MSI_LOG_ERROR << "Create Data Buffer failed";
  104. free_data_buffer(data_mem_buffer);
  105. return false;
  106. }
  107. ret = aclmdlAddDatasetBuffer(dataset, data_buffer);
  108. if (ret != ACL_ERROR_NONE) {
  109. MSI_LOG_ERROR << "add data buffer failed";
  110. free_data_buffer(data_mem_buffer);
  111. aclDestroyDataBuffer(data_buffer);
  112. return false;
  113. }
  114. return true;
  115. }
  116. bool ModelProcess::InitOutputsBuffer() {
  117. aclError ret;
  118. outputs_ = aclmdlCreateDataset();
  119. if (outputs_ == nullptr) {
  120. MSI_LOG_ERROR << "Create input dataset failed";
  121. return false;
  122. }
  123. size_t output_size = aclmdlGetNumOutputs(model_desc_);
  124. for (size_t i = 0; i < output_size; ++i) {
  125. auto buffer_size = aclmdlGetOutputSizeByIndex(model_desc_, i);
  126. void *data_mem_buffer = nullptr;
  127. if (CreateDataBuffer(data_mem_buffer, buffer_size, outputs_) != true) {
  128. MSI_LOG_ERROR << "add output data buffer failed, buffer size " << buffer_size;
  129. return false;
  130. }
  131. aclmdlIODims dims;
  132. ret = aclmdlGetOutputDims(model_desc_, i, &dims);
  133. if (ret != ACL_ERROR_NONE) {
  134. MSI_LOG_ERROR << "Get input shape failed";
  135. return false;
  136. }
  137. aclDataType dataType = aclmdlGetOutputDataType(model_desc_, i);
  138. std::vector<int64_t> shape(dims.dims, dims.dims + dims.dimCount);
  139. output_infos_.emplace_back(AclTensorInfo{data_mem_buffer, buffer_size, dataType, shape});
  140. }
  141. MSI_LOG_INFO << "Create model output success";
  142. return true;
  143. }
  144. void ModelProcess::DestroyInputsDataset() {
  145. if (inputs_ == nullptr) {
  146. return;
  147. }
  148. for (size_t i = 0; i < aclmdlGetDatasetNumBuffers(inputs_); i++) {
  149. auto dataBuffer = aclmdlGetDatasetBuffer(inputs_, i);
  150. aclDestroyDataBuffer(dataBuffer);
  151. }
  152. aclmdlDestroyDataset(inputs_);
  153. inputs_ = nullptr;
  154. }
  155. void ModelProcess::DestroyInputsDataMem() {
  156. if (!is_run_on_device_) {
  157. for (const auto &item : input_infos_) {
  158. aclrtFree(item.device_data);
  159. }
  160. }
  161. input_infos_.clear();
  162. }
  163. void ModelProcess::DestroyInputsBuffer() {
  164. DestroyInputsDataset();
  165. DestroyInputsDataMem();
  166. }
  167. void ModelProcess::DestroyOutputsBuffer() {
  168. if (outputs_ == nullptr) {
  169. return;
  170. }
  171. for (size_t i = 0; i < aclmdlGetDatasetNumBuffers(outputs_); i++) {
  172. auto dataBuffer = aclmdlGetDatasetBuffer(outputs_, i);
  173. auto data = aclGetDataBufferAddr(dataBuffer);
  174. if (!is_run_on_device_) {
  175. aclrtFree(data);
  176. } else {
  177. aclrtFreeHost(data);
  178. }
  179. aclDestroyDataBuffer(dataBuffer);
  180. }
  181. aclmdlDestroyDataset(outputs_);
  182. outputs_ = nullptr;
  183. output_infos_.clear();
  184. }
  185. void ModelProcess::UnLoad() {
  186. auto ret = aclmdlUnload(model_id_);
  187. if (ret != ACL_ERROR_NONE) {
  188. MSI_LOG_ERROR << "Unload model failed";
  189. }
  190. if (model_desc_ != nullptr) {
  191. aclmdlDestroyDesc(model_desc_);
  192. model_desc_ = nullptr;
  193. }
  194. DestroyInputsBuffer();
  195. DestroyOutputsBuffer();
  196. MSI_LOG_INFO << "End unload model " << model_id_;
  197. }
  198. bool ModelProcess::CheckAndInitInput(const RequestBase &request) {
  199. aclError ret;
  200. inputs_ = aclmdlCreateDataset();
  201. // check inputs
  202. if (request.size() != input_infos_.size()) {
  203. MSI_LOG_ERROR << "inputs count not match, required count " << input_infos_.size() << ", given count "
  204. << request.size();
  205. return false;
  206. }
  207. for (size_t i = 0; i < input_infos_.size(); i++) {
  208. if (request[i] == nullptr) {
  209. MSI_LOG_ERROR << "input " << i << " cannot be null";
  210. return false;
  211. }
  212. if (request[i]->data_size() != input_infos_[i].buffer_size) {
  213. MSI_LOG_ERROR << "input " << i << " data size not match, required size " << input_infos_[i].buffer_size
  214. << ", given count " << request[i]->data_size();
  215. return false;
  216. }
  217. }
  218. // copy inputs
  219. for (size_t i = 0; i < input_infos_.size(); i++) {
  220. void *input_buffer = nullptr;
  221. auto &info = input_infos_[i];
  222. const void *data = request[i]->data();
  223. if (!is_run_on_device_) {
  224. ret = aclrtMemcpy(info.device_data, info.buffer_size, data, request[i]->data_size(), ACL_MEMCPY_HOST_TO_DEVICE);
  225. if (ret != ACL_ERROR_NONE) {
  226. MSI_LOG_ERROR << "memcpy input " << i << " data to device failed, buffer size " << request[i]->data_size();
  227. return false;
  228. }
  229. input_buffer = info.device_data;
  230. } else {
  231. input_buffer = const_cast<void *>(data);
  232. }
  233. auto data_buffer = aclCreateDataBuffer(input_buffer, info.buffer_size);
  234. if (data_buffer == nullptr) {
  235. MSI_LOG_ERROR << "Create Data Buffer failed";
  236. return false;
  237. }
  238. ret = aclmdlAddDatasetBuffer(inputs_, data_buffer);
  239. if (ret != ACL_ERROR_NONE) {
  240. MSI_LOG_ERROR << "add data buffer failed";
  241. aclDestroyDataBuffer(data_buffer);
  242. return false;
  243. }
  244. }
  245. return true;
  246. }
  247. bool ModelProcess::BuildOutputs(ReplyBase &reply) {
  248. aclError ret;
  249. // copy outputs
  250. reply.clear();
  251. std::unordered_map<aclDataType, inference::DataType> dataTypeMap = {
  252. {ACL_FLOAT16, inference::kMSI_Float16}, {ACL_FLOAT, inference::kMSI_Float32}, {ACL_DOUBLE, inference::kMSI_Float64},
  253. {ACL_INT8, inference::kMSI_Int8}, {ACL_INT16, inference::kMSI_Int16}, {ACL_INT32, inference::kMSI_Int32},
  254. {ACL_INT64, inference::kMSI_Int64}, {ACL_UINT8, inference::kMSI_Uint8}, {ACL_UINT16, inference::kMSI_Uint16},
  255. {ACL_UINT32, inference::kMSI_Uint32}, {ACL_UINT64, inference::kMSI_Uint64}, {ACL_BOOL, inference::kMSI_Bool},
  256. };
  257. auto trans_to_serving_type = [&dataTypeMap](aclDataType data_type) {
  258. auto it = dataTypeMap.find(data_type);
  259. if (it == dataTypeMap.end()) {
  260. return inference::kMSI_Unknown;
  261. } else {
  262. return it->second;
  263. }
  264. };
  265. for (size_t i = 0; i < output_infos_.size(); i++) {
  266. auto &info = output_infos_[i];
  267. auto output = reply.add();
  268. if (output == nullptr) {
  269. MSI_LOG_ERROR << "add new output failed";
  270. return false;
  271. }
  272. output->set_data_type(trans_to_serving_type(info.data_type));
  273. output->set_shape(info.dims);
  274. if (!output->resize_data(info.buffer_size)) {
  275. MSI_LOG_ERROR << "new output data buffer failed, data size " << info.buffer_size;
  276. return false;
  277. }
  278. if (!is_run_on_device_) {
  279. ret = aclrtMemcpy(output->mutable_data(), output->data_size(), info.device_data, info.buffer_size,
  280. ACL_MEMCPY_DEVICE_TO_HOST);
  281. if (ret != ACL_ERROR_NONE) {
  282. MSI_LOG_ERROR << "Memcpy output " << i << " to host failed, memory size " << info.buffer_size;
  283. return false;
  284. }
  285. } else {
  286. ret = aclrtMemcpy(output->mutable_data(), output->data_size(), info.device_data, info.buffer_size,
  287. ACL_MEMCPY_HOST_TO_HOST);
  288. if (ret != ACL_ERROR_NONE) {
  289. MSI_LOG_ERROR << "Memcpy output " << i << " to host failed, memory size " << info.buffer_size;
  290. return false;
  291. }
  292. }
  293. }
  294. return true;
  295. }
  296. bool ModelProcess::Execute(const RequestBase &request, ReplyBase &reply) {
  297. aclError acl_ret;
  298. if (CheckAndInitInput(request) != true) {
  299. MSI_LOG_ERROR << "check or init input failed";
  300. DestroyInputsDataset();
  301. return false;
  302. }
  303. acl_ret = aclmdlExecute(model_id_, inputs_, outputs_);
  304. DestroyInputsDataset();
  305. if (acl_ret != ACL_ERROR_NONE) {
  306. MSI_LOG_ERROR << "Execute Model Failed";
  307. return false;
  308. }
  309. bool ret = BuildOutputs(reply);
  310. if (!ret) {
  311. MSI_LOG_ERROR << "Build outputs faield";
  312. return false;
  313. }
  314. MSI_LOG_INFO << "excute model success";
  315. return true;
  316. }
  317. } // namespace inference
  318. } // namespace mindspore