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.

file_saver.cc 18 kB

5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
4 years ago
5 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
4 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
4 years ago
4 years ago
4 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  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 "common/auth/file_saver.h"
  17. #include <securec.h>
  18. #include <cstdlib>
  19. #include <fstream>
  20. #include <vector>
  21. #include "common/math/math_util.h"
  22. #include "framework/common/debug/ge_log.h"
  23. #include "framework/common/debug/log.h"
  24. #include "framework/common/util.h"
  25. namespace {
  26. const int kFileOpSuccess = 0;
  27. } // namespace
  28. namespace ge {
  29. Status FileSaver::OpenFile(int32_t &fd, const std::string &file_path) {
  30. if (CheckPath(file_path) != SUCCESS) {
  31. GELOGE(FAILED, "[Check][FilePath]Check output file failed, file_path:%s.",
  32. file_path.c_str());
  33. REPORT_CALL_ERROR("E19999", "Check output file failed, file_path:%s.",
  34. file_path.c_str());
  35. return FAILED;
  36. }
  37. char real_path[MMPA_MAX_PATH] = {0};
  38. GE_IF_BOOL_EXEC(mmRealPath(file_path.c_str(), real_path, MMPA_MAX_PATH) != EN_OK,
  39. GELOGI("File %s is not exist, it will be created.", file_path.c_str()));
  40. // Open file
  41. mmMode_t mode = M_IRUSR | M_IWUSR;
  42. fd = mmOpen2(real_path, M_RDWR | M_CREAT | O_TRUNC, mode);
  43. if (fd == EN_INVALID_PARAM || fd == EN_ERROR) {
  44. // -1: Failed to open file; - 2: Illegal parameter
  45. GELOGE(FAILED, "[Open][File]Failed. errno:%d, errmsg:%s", fd, strerror(errno));
  46. REPORT_INNER_ERROR("E19999", "Open file failed, errno:%d, errmsg:%s.",
  47. fd, strerror(errno));
  48. return FAILED;
  49. }
  50. return SUCCESS;
  51. }
  52. Status FileSaver::WriteData(const void *data, uint32_t size, int32_t fd) {
  53. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(size == 0 || data == nullptr, return PARAM_INVALID);
  54. mmSsize_t write_count;
  55. uint32_t size_2g = 2147483648; // 0x1 << 31
  56. uint32_t size_1g = 1073741824; // 0x1 << 30
  57. // Write data
  58. if (size > size_2g) {
  59. auto seek = reinterpret_cast<uint8_t *>(const_cast<void *>(data));
  60. while (size > size_1g) {
  61. write_count = mmWrite(fd, reinterpret_cast<void *>(seek), size_1g);
  62. if (write_count == EN_INVALID_PARAM || write_count == EN_ERROR) {
  63. GELOGE(FAILED, "[Write][Data]Failed, errno:%ld, errmsg:%s",
  64. write_count, strerror(errno));
  65. REPORT_INNER_ERROR("E19999", "Write data failed, errno:%ld, errmsg:%s.",
  66. write_count, strerror(errno));
  67. return FAILED;
  68. }
  69. size -= size_1g;
  70. seek += size_1g;
  71. }
  72. write_count = mmWrite(fd, reinterpret_cast<void *>(seek), size);
  73. } else {
  74. write_count = mmWrite(fd, const_cast<void *>(data), size);
  75. }
  76. // -1: Failed to write to file; - 2: Illegal parameter
  77. if (write_count == EN_INVALID_PARAM || write_count == EN_ERROR) {
  78. GELOGE(FAILED, "[Write][Data]Failed. mmpa_errorno = %ld, error:%s",
  79. write_count, strerror(errno));
  80. REPORT_INNER_ERROR("E19999", "Write data failed, mmpa_errorno = %ld, error:%s.",
  81. write_count, strerror(errno));
  82. return FAILED;
  83. }
  84. return SUCCESS;
  85. }
  86. Status FileSaver::SaveWithFileHeader(const std::string &file_path, const ModelFileHeader &file_header, const void *data,
  87. int len) {
  88. if (data == nullptr || len <= 0) {
  89. GELOGE(FAILED, "[Check][Param]Failed, model_data is null or the "
  90. "length[%d] is less than 1.", len);
  91. REPORT_INNER_ERROR("E19999", "Save file failed, model_data is null or the "
  92. "length:%d is less than 1.", len);
  93. return FAILED;
  94. }
  95. // Open file
  96. int32_t fd = 0;
  97. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(OpenFile(fd, file_path) != SUCCESS, return FAILED, "OpenFile FAILED");
  98. Status ret = SUCCESS;
  99. do {
  100. // Write file header
  101. GE_CHK_BOOL_EXEC(WriteData(static_cast<const void *>(&file_header), sizeof(ModelFileHeader), fd) == SUCCESS,
  102. ret = FAILED;
  103. break, "WriteData FAILED");
  104. // write data
  105. GE_CHK_BOOL_EXEC(WriteData(data, static_cast<uint32_t>(len), fd) == SUCCESS, ret = FAILED, "WriteData FAILED");
  106. } while (0);
  107. // Close file
  108. if (mmClose(fd) != 0) { // mmClose 0: success
  109. GELOGE(FAILED, "[Close][File]Failed, error_code:%u errmsg:%s", ret, strerror(errno));
  110. REPORT_INNER_ERROR("E19999", "Close file failed, error_code:%u errmsg:%s",
  111. ret, strerror(errno));
  112. ret = FAILED;
  113. }
  114. return ret;
  115. }
  116. Status FileSaver::SaveWithFileHeader(const std::string &file_path, const ModelFileHeader &file_header,
  117. ModelPartitionTable &model_partition_table,
  118. const std::vector<ModelPartition> &partition_datas) {
  119. GE_CHK_BOOL_RET_STATUS(!partition_datas.empty() && model_partition_table.num != 0
  120. && model_partition_table.num == partition_datas.size(), FAILED,
  121. "Invalid param:partition data size is (%u), model_partition_table.num is (%zu).",
  122. model_partition_table.num, partition_datas.size());
  123. // Open file
  124. int32_t fd = 0;
  125. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(OpenFile(fd, file_path) != SUCCESS, return FAILED);
  126. Status ret = SUCCESS;
  127. do {
  128. // Write file header
  129. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(
  130. WriteData(static_cast<const void *>(&file_header), sizeof(ModelFileHeader), fd) != SUCCESS, ret = FAILED;
  131. break);
  132. // Write model partition table
  133. uint32_t table_size = static_cast<uint32_t>(SIZE_OF_MODEL_PARTITION_TABLE(model_partition_table));
  134. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(
  135. WriteData(static_cast<const void *>(&model_partition_table), table_size, fd) != SUCCESS, ret = FAILED; break);
  136. // Write partition data
  137. for (const auto &partitionData : partition_datas) {
  138. GELOGI("GC:size[%u]", partitionData.size);
  139. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(
  140. WriteData(static_cast<const void *>(partitionData.data), partitionData.size, fd) != SUCCESS, ret = FAILED;
  141. break);
  142. }
  143. } while (0);
  144. // Close file
  145. if (mmClose(fd) != EN_OK) {
  146. GELOGE(FAILED, "[Close][File]Failed, error_code:%u errmsg:%s", ret, strerror(errno));
  147. REPORT_CALL_ERROR("E19999", "Close file failed, error_code:%u errmsg:%s",
  148. ret, strerror(errno));
  149. ret = FAILED;
  150. }
  151. return ret;
  152. }
  153. Status FileSaver::SaveToBuffWithFileHeader(const ModelFileHeader &file_header,
  154. ModelPartitionTable &model_partition_table,
  155. const std::vector<ModelPartition> &partition_datas,
  156. ge::ModelBufferData &model) {
  157. const vector<ModelPartitionTable *> model_partition_tables = { &model_partition_table };
  158. const std::vector<std::vector<ModelPartition>> all_partition_datas = { partition_datas };
  159. return SaveToBuffWithFileHeader(file_header, model_partition_tables, all_partition_datas, model);
  160. }
  161. Status FileSaver::SaveToBuffWithFileHeader(const ModelFileHeader &file_header,
  162. const vector<ModelPartitionTable *> &model_partition_tables,
  163. const std::vector<std::vector<ModelPartition>> &all_partition_datas,
  164. ge::ModelBufferData &model) {
  165. GE_CHK_BOOL_RET_STATUS(model_partition_tables.size() == all_partition_datas.size(), PARAM_INVALID,
  166. "Model table size %zu does not match partition size %zu.",
  167. model_partition_tables.size(), all_partition_datas.size());
  168. for (size_t index = 0; index < model_partition_tables.size(); ++index) {
  169. auto &cur_partiton_data = all_partition_datas[index];
  170. auto &cur_model_partition_table = *model_partition_tables[index];
  171. GE_CHK_BOOL_RET_STATUS(!cur_partiton_data.empty() && cur_model_partition_table.num != 0
  172. && cur_model_partition_table.num == cur_partiton_data.size(), FAILED,
  173. "Invalid param: partition data size is (%zu), model_partition_table.num is (%u).",
  174. cur_partiton_data.size(), cur_model_partition_table.num);
  175. }
  176. uint64_t model_header_size = sizeof(ModelFileHeader);
  177. uint64_t total_size = model_header_size;
  178. for (size_t index = 0; index < model_partition_tables.size(); ++index) {
  179. auto &cur_model_partition_table = *model_partition_tables[index];
  180. total_size += static_cast<uint64_t>(SIZE_OF_MODEL_PARTITION_TABLE(cur_model_partition_table));
  181. auto &cur_partition_data = all_partition_datas[index];
  182. for (const auto &partition_data : cur_partition_data) {
  183. auto ret = ge::CheckUint64AddOverflow(total_size, partition_data.size);
  184. GE_CHK_BOOL_RET_STATUS(ret == SUCCESS, FAILED, "Add uint64 overflow!");
  185. total_size += partition_data.size;
  186. }
  187. }
  188. // save to buff
  189. auto buff = reinterpret_cast<uint8_t *>(malloc(total_size));
  190. GE_CHK_BOOL_RET_STATUS(buff != nullptr, FAILED, "Malloc failed!");
  191. GE_PRINT_DYNAMIC_MEMORY(malloc, "File buffer.", total_size)
  192. model.data.reset(buff, [](uint8_t *buff) {
  193. GELOGD("Free online model memory.");
  194. free(buff);
  195. buff = nullptr;
  196. });
  197. model.length = total_size;
  198. uint64_t left_space = total_size;
  199. auto ret_mem = memcpy_s(buff, left_space, reinterpret_cast<void *>(const_cast<ModelFileHeader *>(&file_header)),
  200. model_header_size);
  201. GE_CHK_BOOL_RET_STATUS(ret_mem == EOK, FAILED, "Memcpy_s failed!");
  202. buff += model_header_size;
  203. left_space -= model_header_size;
  204. for (size_t index = 0; index < model_partition_tables.size(); ++index) {
  205. auto &cur_tabel = *model_partition_tables[index];
  206. uint64_t table_size = static_cast<uint64_t>(SIZE_OF_MODEL_PARTITION_TABLE(cur_tabel));
  207. ret_mem = memcpy_s(buff, left_space, reinterpret_cast<void *>(&cur_tabel), table_size);
  208. GE_CHK_BOOL_RET_STATUS(ret_mem == EOK, FAILED, "Memcpy_s failed!");
  209. buff += table_size;
  210. left_space -= table_size;
  211. auto &cur_partition_data = all_partition_datas[index];
  212. for (const auto &partition_data : cur_partition_data) {
  213. ret_mem = memcpy_s(buff, left_space, reinterpret_cast<void *>(const_cast<uint8_t *>(partition_data.data)),
  214. partition_data.size);
  215. GE_CHK_BOOL_RET_STATUS(ret_mem == EOK, FAILED, "Memcpy_s failed!");
  216. buff += partition_data.size;
  217. left_space -= partition_data.size;
  218. }
  219. }
  220. return SUCCESS;
  221. }
  222. FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY Status FileSaver::CheckPath(const std::string &file_path) {
  223. // Determine file path length
  224. if (file_path.size() >= MMPA_MAX_PATH) {
  225. GELOGE(FAILED, "[Check][FilePath]Failed, file path's length:%zu > mmpa_max_path:%d",
  226. file_path.size(), MMPA_MAX_PATH);
  227. REPORT_INNER_ERROR("E19999", "Check file path failed, file path's length:%zu > "
  228. "mmpa_max_path:%d", file_path.size(), MMPA_MAX_PATH);
  229. return FAILED;
  230. }
  231. // Find the last separator
  232. int path_split_pos = static_cast<int>(file_path.size() - 1);
  233. for (; path_split_pos >= 0; path_split_pos--) {
  234. if (file_path[path_split_pos] == '\\' || file_path[path_split_pos] == '/') {
  235. break;
  236. }
  237. }
  238. if (path_split_pos == 0) {
  239. return SUCCESS;
  240. }
  241. // If there is a path before the file name, create the path
  242. if (path_split_pos != -1) {
  243. if (CreateDirectory(std::string(file_path).substr(0, static_cast<size_t>(path_split_pos))) != kFileOpSuccess) {
  244. GELOGE(FAILED, "[Create][Directory]Failed, file path:%s.", file_path.c_str());
  245. return FAILED;
  246. }
  247. }
  248. return SUCCESS;
  249. }
  250. FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY Status
  251. FileSaver::SaveToFile(const string &file_path, const ge::ModelData &model, const ModelFileHeader *model_file_header) {
  252. if (file_path.empty() || model.model_data == nullptr || model.model_len == 0) {
  253. GELOGE(FAILED, "[Save][File]Incorrect input param, "
  254. "file_path is empty or model_data is nullptr or model_len is 0");
  255. REPORT_INNER_ERROR("E19999", "Save file failed, at least one of the "
  256. "input parameters(file_path, model_data, model_len) is incorrect");
  257. return FAILED;
  258. }
  259. ModelFileHeader file_header;
  260. int32_t copy_header_ret = 0;
  261. GE_IF_BOOL_EXEC(model_file_header != nullptr, copy_header_ret = memcpy_s(&file_header, sizeof(ModelFileHeader),
  262. model_file_header, sizeof(ModelFileHeader)));
  263. GE_CHK_BOOL_RET_STATUS(copy_header_ret == 0, FAILED, "Copy ModelFileHeader failed, memcpy_s return: %d",
  264. copy_header_ret);
  265. file_header.length = model.model_len;
  266. file_header.is_encrypt = ModelEncryptType::UNENCRYPTED;
  267. const Status ret = SaveWithFileHeader(file_path, file_header, model.model_data, file_header.length);
  268. if (ret != SUCCESS) {
  269. GELOGE(FAILED, "[Save][File]Failed, file_path:%s, file_header_len:%u, error_code:%u.",
  270. file_path.c_str(), file_header.length, ret);
  271. return FAILED;
  272. }
  273. return SUCCESS;
  274. }
  275. FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY Status
  276. FileSaver::SaveToFile(const string &file_path, ModelFileHeader &file_header, ModelPartitionTable &model_partition_table,
  277. const std::vector<ModelPartition> &partition_datas) {
  278. file_header.is_encrypt = ModelEncryptType::UNENCRYPTED;
  279. const Status ret = SaveWithFileHeader(file_path, file_header, model_partition_table, partition_datas);
  280. GE_CHK_BOOL_RET_STATUS(ret == SUCCESS, FAILED, "save file failed, file_path:%s, file header len:%u.",
  281. file_path.c_str(), file_header.length);
  282. return SUCCESS;
  283. }
  284. FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY Status
  285. FileSaver::SaveToFile(const string &file_path, ModelFileHeader &file_header,
  286. vector<ModelPartitionTable *> &model_partition_tables,
  287. const vector<vector<ModelPartition>> &all_partition_datas) {
  288. file_header.is_encrypt = ModelEncryptType::UNENCRYPTED;
  289. const Status ret = SaveWithFileHeader(file_path, file_header, model_partition_tables, all_partition_datas);
  290. GE_CHK_BOOL_RET_STATUS(ret == SUCCESS, FAILED, "save file failed, file_path:%s, file header len:%u.",
  291. file_path.c_str(), file_header.length);
  292. return SUCCESS;
  293. }
  294. Status FileSaver::SaveWithFileHeader(const std::string &file_path, const ModelFileHeader &file_header,
  295. vector<ModelPartitionTable *> &model_partition_tables,
  296. const vector<vector<ModelPartition>> &all_partition_datas) {
  297. GE_CHK_BOOL_EXEC(model_partition_tables.size() == all_partition_datas.size(),
  298. return PARAM_INVALID,
  299. "model table size %zu does not match partition size %zu",
  300. model_partition_tables.size(), all_partition_datas.size())
  301. for (size_t index = 0; index < model_partition_tables.size(); ++index) {
  302. auto &cur_partiton_data = all_partition_datas[index];
  303. auto &cur_model_partition_table = *model_partition_tables[index];
  304. GE_CHK_BOOL_RET_STATUS(!cur_partiton_data.empty() && cur_model_partition_table.num != 0
  305. && cur_model_partition_table.num == cur_partiton_data.size(), FAILED,
  306. "Invalid param:partition data size is (%u), model_partition_table.num is (%zu).",
  307. cur_model_partition_table.num, cur_partiton_data.size());
  308. }
  309. // Open file
  310. int32_t fd = 0;
  311. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(OpenFile(fd, file_path) != SUCCESS, return FAILED);
  312. Status ret = SUCCESS;
  313. do {
  314. // Write file header
  315. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(
  316. WriteData(static_cast<const void *>(&file_header), sizeof(ModelFileHeader), fd) != SUCCESS, ret = FAILED;
  317. break);
  318. for (size_t index = 0; index < model_partition_tables.size(); ++index) {
  319. // Write model partition table
  320. auto &cur_tabel = *model_partition_tables[index];
  321. uint32_t table_size = static_cast<uint32_t>(SIZE_OF_MODEL_PARTITION_TABLE(cur_tabel));
  322. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(
  323. WriteData(static_cast<const void *>(&cur_tabel), table_size, fd) != SUCCESS, ret = FAILED; break);
  324. // Write partition data
  325. auto &cur_partition_datas = all_partition_datas[index];
  326. for (const auto &partition_data : cur_partition_datas) {
  327. GELOGI("part_size[%u]", partition_data.size);
  328. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(
  329. WriteData(static_cast<const void *>(partition_data.data), partition_data.size, fd) != SUCCESS, ret = FAILED;
  330. break);
  331. }
  332. }
  333. } while (0);
  334. // Close file
  335. if (mmClose(fd) != 0) { // mmClose 0: success
  336. GELOGE(FAILED, "[Close][File]Failed, error_code:%u errmsg:%s", ret, strerror(errno));
  337. REPORT_CALL_ERROR("E19999", "Close file failed, error_code:%u errmsg:%s",
  338. ret, strerror(errno));
  339. ret = FAILED;
  340. }
  341. return ret;
  342. }
  343. FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY Status FileSaver::SaveToFile(const string &file_path, const void *data,
  344. int len) {
  345. if (data == nullptr || len <= 0) {
  346. GELOGE(FAILED, "[Check][Param]Failed, model_data is null or the "
  347. "length[%d] is less than 1.", len);
  348. REPORT_INNER_ERROR("E19999", "Save file failed, the model_data is null or "
  349. "its length:%d is less than 1.", len);
  350. return FAILED;
  351. }
  352. // Open file
  353. int32_t fd = 0;
  354. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(OpenFile(fd, file_path) != SUCCESS, return FAILED, "OpenFile FAILED");
  355. Status ret = SUCCESS;
  356. // write data
  357. GE_CHK_BOOL_EXEC(SUCCESS == WriteData(data, (uint32_t)len, fd), ret = FAILED, "WriteData FAILED");
  358. // Close file
  359. if (mmClose(fd) != 0) { // mmClose 0: success
  360. GELOGE(FAILED, "[Close][File]Failed, error_code:%u errmsg:%s", ret, strerror(errno));
  361. REPORT_CALL_ERROR("E19999", "Close file failed, error_code:%u errmsg:%s",
  362. ret, strerror(errno));
  363. ret = FAILED;
  364. }
  365. return ret;
  366. }
  367. } // namespace ge

图引擎模块(GE)是MindSpore的一个子模块,其代码由C++实现,位于前端模块ME和底层硬件之间,起到承接作用。图引擎模块以ME下发的图作为输入,然后进行一系列的深度图优化操作,最后输出一张可以在底层硬件上高效运行的图。GE针对昇腾AI处理器的硬件结构特点,做了特定的优化工作,以此来充分发挥出昇腾AI处理器的强大算力。在进行模型训练/推理时,GE会被自动调用而用户并不感知。GE主要由GE API和GE Core两部分组成,详细的架构图如下所示