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 11 kB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  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 output file failed.");
  32. return FAILED;
  33. }
  34. char real_path[MMPA_MAX_PATH] = {0};
  35. GE_IF_BOOL_EXEC(mmRealPath(file_path.c_str(), real_path, MMPA_MAX_PATH) != EN_OK,
  36. GELOGI("File %s is not exist, it will be created.", file_path.c_str()));
  37. // Open file
  38. mmMode_t mode = M_IRUSR | M_IWUSR;
  39. fd = mmOpen2(real_path, M_RDWR | M_CREAT | O_TRUNC, mode);
  40. if (fd == EN_INVALID_PARAM || fd == EN_ERROR) {
  41. // -1: Failed to open file; - 2: Illegal parameter
  42. GELOGE(FAILED, "Open file failed. mmpa_errno = %d, %s", fd, strerror(errno));
  43. return FAILED;
  44. }
  45. return SUCCESS;
  46. }
  47. Status FileSaver::WriteData(const void *data, uint32_t size, int32_t fd) {
  48. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(size == 0 || data == nullptr, return PARAM_INVALID);
  49. mmSsize_t write_count;
  50. uint32_t size_2g = ((uint32_t) 0x1 << 31);
  51. uint32_t size_1g = ((uint32_t) 0x1 << 30);
  52. // Write data
  53. if (size > size_2g) {
  54. auto seek = reinterpret_cast<uint8_t *>(const_cast<void *>(data));
  55. while (size > size_1g) {
  56. write_count = mmWrite(fd, reinterpret_cast<void *>(seek), size_1g);
  57. if (write_count == EN_INVALID_PARAM || write_count == EN_ERROR) {
  58. GELOGE(FAILED, "Write data failed. mmpa_errorno = %d, %s", write_count, strerror(errno));
  59. return FAILED;
  60. }
  61. size -= size_1g;
  62. seek += size_1g;
  63. }
  64. write_count = mmWrite(fd, reinterpret_cast<void *>(seek), size);
  65. } else {
  66. write_count = mmWrite(fd, const_cast<void *>(data), size);
  67. }
  68. // -1: Failed to write to file; - 2: Illegal parameter
  69. if (write_count == EN_INVALID_PARAM || write_count == EN_ERROR) {
  70. GELOGE(FAILED, "Write data failed. mmpa_errorno = %d, %s", write_count, strerror(errno));
  71. return FAILED;
  72. }
  73. return SUCCESS;
  74. }
  75. Status FileSaver::SaveWithFileHeader(const std::string &file_path, const ModelFileHeader &file_header, const void *data,
  76. int len) {
  77. if (data == nullptr || len <= 0) {
  78. GELOGE(FAILED, "Model_data is null or the length[%d] less than 1.", len);
  79. return FAILED;
  80. }
  81. // Open file
  82. int32_t fd = 0;
  83. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(OpenFile(fd, file_path) != SUCCESS, return FAILED, "OpenFile FAILED");
  84. Status ret = SUCCESS;
  85. do {
  86. // Write file header
  87. GE_CHK_BOOL_EXEC(WriteData(static_cast<const void *>(&file_header), sizeof(ModelFileHeader), fd) == SUCCESS,
  88. ret = FAILED;
  89. break, "WriteData FAILED");
  90. // write data
  91. GE_CHK_BOOL_EXEC(WriteData(data, static_cast<uint32_t>(len), fd) == SUCCESS, ret = FAILED, "WriteData FAILED");
  92. } while (0);
  93. // Close file
  94. if (mmClose(fd) != 0) { // mmClose 0: success
  95. GELOGE(FAILED, "Close file failed.");
  96. ret = FAILED;
  97. }
  98. return ret;
  99. }
  100. Status FileSaver::SaveWithFileHeader(const std::string &file_path, const ModelFileHeader &file_header,
  101. ModelPartitionTable &model_partition_table,
  102. const std::vector<ModelPartition> &partition_datas) {
  103. GE_CHK_BOOL_RET_STATUS(!partition_datas.empty() && model_partition_table.num != 0
  104. && model_partition_table.num == partition_datas.size(), FAILED,
  105. "Invalid param:partition data size is (%u), model_partition_table.num is (%zu).",
  106. model_partition_table.num, partition_datas.size());
  107. // Open file
  108. int32_t fd = 0;
  109. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(OpenFile(fd, file_path) != SUCCESS, return FAILED);
  110. Status ret = SUCCESS;
  111. do {
  112. // Write file header
  113. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(
  114. WriteData(static_cast<const void *>(&file_header), sizeof(ModelFileHeader), fd) != SUCCESS, ret = FAILED;
  115. break);
  116. // Write model partition table
  117. uint32_t table_size = static_cast<uint32_t>(SIZE_OF_MODEL_PARTITION_TABLE(model_partition_table));
  118. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(
  119. WriteData(static_cast<const void *>(&model_partition_table), table_size, fd) != SUCCESS, ret = FAILED; break);
  120. // Write partition data
  121. for (const auto &partitionData : partition_datas) {
  122. GELOGI("GC:size[%zu]", partitionData.size);
  123. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(
  124. WriteData(static_cast<const void *>(partitionData.data), partitionData.size, fd) != SUCCESS, ret = FAILED;
  125. break);
  126. }
  127. } while (0);
  128. // Close file
  129. GE_CHK_BOOL_RET_STATUS(mmClose(fd) == EN_OK, FAILED, "Close file failed.");
  130. return ret;
  131. }
  132. Status FileSaver::SaveToBuffWithFileHeader(const ModelFileHeader &file_header,
  133. ModelPartitionTable &model_partition_table,
  134. const std::vector<ModelPartition> &partitionDatas,
  135. ge::ModelBufferData &model) {
  136. GE_CHK_BOOL_RET_STATUS(
  137. !partitionDatas.empty() && model_partition_table.num != 0 && model_partition_table.num == partitionDatas.size(),
  138. FAILED, "Invalid param:partition data size is (%u), model_partition_table.num is (%zu).",
  139. model_partition_table.num, partitionDatas.size());
  140. uint32_t model_header_size = sizeof(ModelFileHeader);
  141. uint32_t table_size = static_cast<uint32_t>(SIZE_OF_MODEL_PARTITION_TABLE(model_partition_table));
  142. uint32_t total_size = model_header_size + table_size;
  143. for (const auto &partitionData : partitionDatas) {
  144. auto ret = ge::CheckUint32AddOverflow(total_size, partitionData.size);
  145. GE_CHK_BOOL_RET_STATUS(ret == SUCCESS, FAILED, "add uint32 overflow!");
  146. total_size = total_size + partitionData.size;
  147. }
  148. auto buff = reinterpret_cast<uint8_t *>(malloc(total_size));
  149. GE_CHK_BOOL_RET_STATUS(buff != nullptr, FAILED, "malloc failed!");
  150. GE_PRINT_DYNAMIC_MEMORY(malloc, "file buffer.", total_size)
  151. model.data.reset(buff, [](uint8_t *buff) {
  152. GELOGD("Free online model memory.");
  153. free(buff);
  154. buff = nullptr;
  155. });
  156. model.length = total_size;
  157. uint32_t left_space = total_size;
  158. auto ret_mem1 = memcpy_s(buff, left_space, reinterpret_cast<void *>(const_cast<ModelFileHeader *>(&file_header)),
  159. model_header_size);
  160. GE_CHK_BOOL_RET_STATUS(ret_mem1 == 0, FAILED, "memcpy_s failed!");
  161. buff += model_header_size;
  162. left_space -= model_header_size;
  163. auto ret_mem2 = memcpy_s(buff, left_space, reinterpret_cast<void *>(&model_partition_table), table_size);
  164. GE_CHK_BOOL_RET_STATUS(ret_mem2 == 0, FAILED, "memcpy_s failed!");
  165. buff += table_size;
  166. left_space -= table_size;
  167. for (const auto &partitionData : partitionDatas) {
  168. auto ret_mem3 = memcpy_s(buff, left_space, reinterpret_cast<void *>(const_cast<uint8_t *>(partitionData.data)),
  169. partitionData.size);
  170. GE_CHK_BOOL_RET_STATUS(ret_mem3 == 0, FAILED, "memcpy failed!");
  171. buff += partitionData.size;
  172. left_space -= partitionData.size;
  173. }
  174. return SUCCESS;
  175. }
  176. FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY Status FileSaver::CheckPath(const std::string &file_path) {
  177. // Determine file path length
  178. if (file_path.size() >= MMPA_MAX_PATH) {
  179. GELOGE(FAILED, "Path is too long:%zu", file_path.size());
  180. return FAILED;
  181. }
  182. // Find the last separator
  183. int path_split_pos = static_cast<int>(file_path.size() - 1);
  184. for (; path_split_pos >= 0; path_split_pos--) {
  185. if (file_path[path_split_pos] == '\\' || file_path[path_split_pos] == '/') {
  186. break;
  187. }
  188. }
  189. if (path_split_pos == 0) {
  190. return SUCCESS;
  191. }
  192. // If there is a path before the file name, create the path
  193. if (path_split_pos != -1) {
  194. if (CreateDirectory(std::string(file_path).substr(0, static_cast<size_t>(path_split_pos))) != kFileOpSuccess) {
  195. GELOGE(FAILED, "CreateDirectory failed, file path:%s.", file_path.c_str());
  196. return FAILED;
  197. }
  198. }
  199. return SUCCESS;
  200. }
  201. FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY Status
  202. FileSaver::SaveToFile(const string &file_path, const ge::ModelData &model, const ModelFileHeader *model_file_header) {
  203. if (file_path.empty() || model.model_data == nullptr || model.model_len == 0) {
  204. GELOGE(FAILED, "Incorrected input param. file_path.empty() || model.model_data == nullptr || model.model_len == 0");
  205. return FAILED;
  206. }
  207. ModelFileHeader file_header;
  208. int32_t copy_header_ret = 0;
  209. GE_IF_BOOL_EXEC(model_file_header != nullptr, copy_header_ret = memcpy_s(&file_header, sizeof(ModelFileHeader),
  210. model_file_header, sizeof(ModelFileHeader)));
  211. GE_CHK_BOOL_RET_STATUS(copy_header_ret == 0, FAILED, "Copy ModelFileHeader failed, memcpy_s return: %d",
  212. copy_header_ret);
  213. file_header.length = model.model_len;
  214. file_header.is_encrypt = ModelEncryptType::UNENCRYPTED;
  215. const Status ret = SaveWithFileHeader(file_path, file_header, model.model_data, file_header.length);
  216. if (ret != SUCCESS) {
  217. GELOGE(FAILED, "Save file failed, file_path:%s, file header len:%u.", file_path.c_str(), file_header.length);
  218. return FAILED;
  219. }
  220. return SUCCESS;
  221. }
  222. FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY Status
  223. FileSaver::SaveToFile(const string &file_path, ModelFileHeader &file_header, ModelPartitionTable &model_partition_table,
  224. const std::vector<ModelPartition> &partition_datas) {
  225. file_header.is_encrypt = ModelEncryptType::UNENCRYPTED;
  226. const Status ret = SaveWithFileHeader(file_path, file_header, model_partition_table, partition_datas);
  227. GE_CHK_BOOL_RET_STATUS(ret == SUCCESS, FAILED, "save file failed, file_path:%s, file header len:%u.",
  228. file_path.c_str(), file_header.length);
  229. return SUCCESS;
  230. }
  231. FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY Status FileSaver::SaveToFile(const string &file_path, const void *data,
  232. int len) {
  233. if (data == nullptr || len <= 0) {
  234. GELOGE(FAILED, "Model_data is null or the length[%d] less than 1.", len);
  235. return FAILED;
  236. }
  237. // Open file
  238. int32_t fd = 0;
  239. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(OpenFile(fd, file_path) != SUCCESS, return FAILED, "OpenFile FAILED");
  240. Status ret = SUCCESS;
  241. // write data
  242. GE_CHK_BOOL_EXEC(SUCCESS == WriteData(data, (uint32_t)len, fd), ret = FAILED, "WriteData FAILED");
  243. // Close file
  244. if (mmClose(fd) != 0) { // mmClose 0: success
  245. GELOGE(FAILED, "Close file failed.");
  246. ret = FAILED;
  247. }
  248. return ret;
  249. }
  250. } // namespace ge

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