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.

plugin_manager.cc 12 kB

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
5 years ago
5 years ago
5 years ago
5 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
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
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  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/ge/plugin_manager.h"
  17. #include <sys/stat.h>
  18. #include <algorithm>
  19. #include <cstring>
  20. #include <fstream>
  21. #include <iostream>
  22. #include <memory>
  23. #include <string>
  24. #include "framework/common/debug/log.h"
  25. #include "framework/common/util.h"
  26. namespace {
  27. const int kMaxNumOfSo = 64;
  28. const int kMaxSizeOfSo = 209100800; // = 200M(unit is Byte)
  29. const int kMaxSizeOfLoadedSo = 522752000; // = 500M(unit is Byte)
  30. const char *const kExt = ".so"; // supported extension of shared object
  31. } // namespace
  32. namespace ge {
  33. void PluginManager::ClearHandles_() noexcept {
  34. for (const auto &handle : handles_) {
  35. if (mmDlclose(handle.second) != 0) {
  36. const char *error = mmDlerror();
  37. GE_IF_BOOL_EXEC(error == nullptr, error = "");
  38. GELOGW("Failed to close handle of %s, errmsg:%s", handle.first.c_str(), error);
  39. }
  40. }
  41. handles_.clear();
  42. }
  43. PluginManager::~PluginManager() { ClearHandles_(); }
  44. string PluginManager::GetPath() {
  45. mmDlInfo dl_info;
  46. if (mmDladdr(reinterpret_cast<void *>(&PluginManager::GetPath), &dl_info) != EN_OK) {
  47. const char *error = mmDlerror();
  48. GE_IF_BOOL_EXEC(error == nullptr, error = "");
  49. GELOGW("Failed to read the shared library file path! errmsg:%s", error);
  50. return string();
  51. } else {
  52. GE_IF_BOOL_EXEC(dl_info.dli_fname == nullptr, return string());
  53. std::string so_path = dl_info.dli_fname;
  54. char path[MMPA_MAX_PATH] = {0};
  55. if (so_path.length() >= MMPA_MAX_PATH) {
  56. GELOGW("The shared library file path is too long!");
  57. return string();
  58. }
  59. if (mmRealPath(so_path.c_str(), path, MMPA_MAX_PATH) != EN_OK) {
  60. GELOGW("Failed to get realpath of %s, errmsg:%s", so_path.c_str(), strerror(errno));
  61. return string();
  62. }
  63. so_path = path;
  64. so_path = so_path.substr(0, so_path.rfind('/') + 1);
  65. return so_path;
  66. }
  67. }
  68. void PluginManager::SplitPath(const string &mutil_path, vector<string> &path_vec) {
  69. std::string tmp_string = mutil_path + ":";
  70. std::string::size_type start_pos = 0;
  71. std::string::size_type cur_pos = tmp_string.find(':', 0);
  72. while (cur_pos != std::string::npos) {
  73. std::string path = tmp_string.substr(start_pos, cur_pos - start_pos);
  74. if (!path.empty()) {
  75. path_vec.push_back(path);
  76. }
  77. start_pos = cur_pos + 1;
  78. cur_pos = tmp_string.find(':', start_pos);
  79. }
  80. }
  81. Status PluginManager::LoadSo(const string &path, const vector<string> &func_check_list) {
  82. uint32_t num_of_loaded_so = 0;
  83. int64_t size_of_loaded_so = 0;
  84. so_list_.clear();
  85. ClearHandles_();
  86. std::vector<std::string> path_vec;
  87. SplitPath(path, path_vec);
  88. for (const auto &single_path : path_vec) {
  89. GE_IF_BOOL_EXEC(single_path.length() >= MMPA_MAX_PATH, GELOGE(ACL_ERROR_GE_PLGMGR_PATH_INVALID,
  90. "The shared library file path is too long!");
  91. continue);
  92. // load break when number of loaded so reach maximum
  93. if (num_of_loaded_so >= kMaxNumOfSo) {
  94. GELOGW("The number of dynamic libraries loaded exceeds the kMaxNumOfSo,"
  95. " and only the first %d shared libraries will be loaded.", kMaxNumOfSo);
  96. break;
  97. }
  98. std::string file_name = single_path.substr(single_path.rfind('/') + 1, string::npos);
  99. string file_path_dlopen = RealPath(single_path.c_str());
  100. if (file_path_dlopen.empty()) {
  101. GELOGW("Failed to get realpath of %s!", single_path.c_str());
  102. continue;
  103. }
  104. int64_t file_size = 0;
  105. if (ValidateSo(file_path_dlopen, size_of_loaded_so, file_size) != SUCCESS) {
  106. GELOGW("Failed to validate the shared library: %s", file_path_dlopen.c_str());
  107. continue;
  108. }
  109. GELOGI("dlopen the shared library path name: %s.", file_path_dlopen.c_str());
  110. // load continue when dlopen is failed
  111. auto handle = mmDlopen(file_path_dlopen.c_str(), MMPA_RTLD_NOW | MMPA_RTLD_GLOBAL);
  112. if (handle == nullptr) {
  113. const char *error = mmDlerror();
  114. GE_IF_BOOL_EXEC(error == nullptr, error = "");
  115. REPORT_INNER_ERROR("E19999", "DLOpen SharedLibraryPath failed, path[%s]. Errormessage[%s]!",
  116. file_path_dlopen.c_str(), error);
  117. GELOGE(ACL_ERROR_GE_PLGMGR_PATH_INVALID,
  118. "[DLOpen][SharedLibraryPath]Failed, path[%s]. Errormessage[%s]!",
  119. file_path_dlopen.c_str(), error);
  120. continue;
  121. }
  122. // load continue when so is invalid
  123. bool is_valid = true;
  124. for (const auto &func_name : func_check_list) {
  125. auto real_fn = (void (*)())mmDlsym(handle, const_cast<char *>(func_name.c_str()));
  126. if (real_fn == nullptr) {
  127. const char *error = mmDlerror();
  128. GE_IF_BOOL_EXEC(error == nullptr, error = "");
  129. REPORT_INNER_ERROR("E19999", "[Check][So]%s is skipped since function %s is not existed! errmsg:%s",
  130. func_name.c_str(), func_name.c_str(), error);
  131. GELOGE(ACL_ERROR_GE_PLGMGR_PATH_INVALID,
  132. "[Check][So]%s is skipped since function %s is not existed! errmsg:%s",
  133. func_name.c_str(), func_name.c_str(), error);
  134. is_valid = false;
  135. break;
  136. }
  137. }
  138. if (!is_valid) {
  139. if (mmDlclose(handle) != 0) {
  140. const char *error = mmDlerror();
  141. GE_IF_BOOL_EXEC(error == nullptr, error = "");
  142. GELOGE(FAILED, "[DLClose][Handle]Failed. errmsg:%s", error);
  143. }
  144. continue;
  145. }
  146. // add file to list
  147. size_of_loaded_so += file_size;
  148. so_list_.emplace_back(file_name);
  149. handles_[string(file_name)] = handle;
  150. num_of_loaded_so++;
  151. }
  152. GELOGI("The total number of shared libraries loaded: %u", num_of_loaded_so);
  153. for (auto name : so_list_) {
  154. GELOGI("load shared library %s successfully", name.c_str());
  155. }
  156. if (num_of_loaded_so == 0) {
  157. GELOGW("No loadable shared library found in the path: %s", path.c_str());
  158. return SUCCESS;
  159. }
  160. return SUCCESS;
  161. }
  162. Status PluginManager::ValidateSo(const string &file_path, int64_t size_of_loaded_so, int64_t &file_size) const {
  163. // read file size
  164. struct stat stat_buf;
  165. if (stat(file_path.c_str(), &stat_buf) != 0) {
  166. GELOGW("The shared library file check failed: %s", file_path.c_str());
  167. return FAILED;
  168. }
  169. // load continue when the size itself reaches maximum
  170. file_size = stat_buf.st_size;
  171. if (stat_buf.st_size > kMaxSizeOfSo) {
  172. GELOGW("The %s is skipped since its size exceeds maximum! (size: %ldB, maximum: %dB)", file_path.c_str(), file_size,
  173. kMaxSizeOfSo);
  174. return FAILED;
  175. }
  176. // load continue if the total size of so reaches maximum when it is loaded
  177. if (size_of_loaded_so + file_size > kMaxSizeOfLoadedSo) {
  178. GELOGW(
  179. "%s is skipped because the size of loaded share library reaches maximum if it is loaded! "
  180. "(size: %ldB, size of loaded share library: %ldB, maximum: %dB)",
  181. file_path.c_str(), file_size, size_of_loaded_so, kMaxSizeOfLoadedSo);
  182. return FAILED;
  183. }
  184. return SUCCESS;
  185. }
  186. Status PluginManager::Load(const string &path, const vector<string> &func_check_list) {
  187. uint32_t num_of_loaded_so = 0;
  188. int64_t size_of_loaded_so = 0;
  189. const unsigned char is_folder = 0x4;
  190. const std::string ext = kExt;
  191. so_list_.clear();
  192. ClearHandles_();
  193. char canonical_path[MMPA_MAX_PATH] = {0};
  194. GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(path.length() >= MMPA_MAX_PATH, GELOGW("File path is too long!");
  195. return FAILED, "File path is too long!");
  196. if (mmRealPath(path.c_str(), canonical_path, MMPA_MAX_PATH) != EN_OK) {
  197. GELOGW("Failed to get realpath of %s, errmsg:%s", path.c_str(), strerror(errno));
  198. return SUCCESS;
  199. }
  200. INT32 is_dir = mmIsDir(canonical_path);
  201. // Lib plugin path not exist
  202. if (is_dir != EN_OK) {
  203. GELOGW("Invalid path for load: %s, errmsg:%s", path.c_str(), strerror(errno));
  204. return SUCCESS;
  205. }
  206. mmDirent **entries = nullptr;
  207. auto ret = mmScandir(canonical_path, &entries, nullptr, nullptr);
  208. if (ret < EN_OK) {
  209. GELOGW("scan dir failed. path = %s, ret = %d, errmsg = %s", canonical_path, ret, strerror(errno));
  210. return FAILED;
  211. }
  212. for (int i = 0; i < ret; ++i) {
  213. mmDirent *entry = entries[i];
  214. // read fileName and fileType
  215. std::string file_name = entry->d_name;
  216. unsigned char file_type = entry->d_type;
  217. // ignore folder
  218. bool invalid_file = (file_type == is_folder ||
  219. // ignore file whose name length is less than 3
  220. file_name.size() <= ext.size() ||
  221. // ignore file whose extension is not so
  222. file_name.compare(file_name.size() - ext.size(), ext.size(), ext) != 0);
  223. if (invalid_file) {
  224. continue;
  225. }
  226. // load break when number of loaded so reach maximum
  227. if (num_of_loaded_so >= kMaxNumOfSo) {
  228. GELOGW("The number of dynamic libraries loaded exceeds the kMaxNumOfSo,"
  229. " and only the first %d shared libraries will be loaded.", kMaxNumOfSo);
  230. break;
  231. }
  232. std::string canonical_path_str = (std::string(canonical_path) + "/" + file_name);
  233. string file_path_dlopen = RealPath(canonical_path_str.c_str());
  234. if (file_path_dlopen.empty()) {
  235. GELOGW("failed to get realpath of %s", canonical_path_str.c_str());
  236. continue;
  237. }
  238. int64_t file_size = 0;
  239. if (ValidateSo(file_path_dlopen, size_of_loaded_so, file_size) != SUCCESS) {
  240. GELOGW("Failed to validate the shared library: %s", canonical_path_str.c_str());
  241. continue;
  242. }
  243. GELOGI("Dlopen so path name: %s. ", file_path_dlopen.c_str());
  244. // load continue when dlopen is failed
  245. auto handle = mmDlopen(file_path_dlopen.c_str(), MMPA_RTLD_NOW | MMPA_RTLD_GLOBAL);
  246. if (handle == nullptr) {
  247. const char *error = mmDlerror();
  248. GE_IF_BOOL_EXEC(error == nullptr, error = "");
  249. GELOGW("Failed in dlopen %s!", error);
  250. continue;
  251. }
  252. GELOGW("The shared library will not be checked. Please ensure that the source of the shared library is trusted.");
  253. // load continue when so is invalid
  254. bool is_valid = true;
  255. for (const auto &func_name : func_check_list) {
  256. auto real_fn = (void (*)())mmDlsym(handle, const_cast<char *>(func_name.c_str()));
  257. if (real_fn == nullptr) {
  258. const char *error = mmDlerror();
  259. GE_IF_BOOL_EXEC(error == nullptr, error = "");
  260. GELOGW("The %s is skipped since function %s is not existed! errmsg:%s",
  261. file_name.c_str(), func_name.c_str(), error);
  262. is_valid = false;
  263. break;
  264. }
  265. }
  266. if (!is_valid) {
  267. if (mmDlclose(handle) != 0) {
  268. const char *error = mmDlerror();
  269. GE_IF_BOOL_EXEC(error == nullptr, error = "");
  270. GELOGE(FAILED, "[DLClose][Handle]Failed. errmsg:%s", error);
  271. }
  272. continue;
  273. }
  274. // add file to list
  275. size_of_loaded_so += file_size;
  276. so_list_.emplace_back(file_name);
  277. handles_[string(file_name)] = handle;
  278. num_of_loaded_so++;
  279. }
  280. mmScandirFree(entries, ret);
  281. if (num_of_loaded_so == 0) {
  282. GELOGW("No loadable shared library found in the path: %s", path.c_str());
  283. return SUCCESS;
  284. }
  285. return SUCCESS;
  286. }
  287. const vector<string> &PluginManager::GetSoList() const { return so_list_; }
  288. } // namespace ge

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