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.

kernel_pack.cc 8.4 kB

5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
4 years ago
4 years ago
5 years ago
4 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. /**
  2. * Copyright 2019-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. #include <unistd.h>
  17. #include <fstream>
  18. #include <thread>
  19. #include "nlohmann/json.hpp"
  20. #include "securec/include/securec.h"
  21. #include "utils/log_adapter.h"
  22. #include "include/common/utils/convert_utils.h"
  23. #include "utils/system/sha256.h"
  24. #include "kernel/common_utils.h"
  25. namespace mindspore {
  26. namespace kernel {
  27. constexpr size_t kJsonSuffixLength = 5;
  28. namespace {
  29. bool CheckHash(const std::string &json_file, const std::string &bin_file, const nlohmann::json &js) {
  30. if (js.find("sha256") == js.end()) {
  31. MS_LOG(ERROR) << "No sha256 found in " << json_file;
  32. return false;
  33. }
  34. std::string sha256_cal = system::sha256::GetHashFromFile(bin_file);
  35. std::string sha256_str = js["sha256"];
  36. if (sha256_cal.empty() || sha256_cal != sha256_str) {
  37. MS_LOG(ERROR) << "Cal sha256 of " << bin_file << " failed.";
  38. return false;
  39. }
  40. return true;
  41. }
  42. } // namespace
  43. bool KernelPack::ReadFromJsonFileHelper(std::ifstream &kernel_bin) {
  44. size_t bin_size = LongToSize(kernel_bin.seekg(0, std::ios::end).tellg());
  45. // free old data
  46. if (kernel_ != nullptr) {
  47. delete[] kernel_;
  48. kernel_ = nullptr;
  49. }
  50. void *ptr = static_cast<void *>(new (std::nothrow) uint8_t[sizeof(KernelPack) + bin_size]);
  51. if (ptr != nullptr) {
  52. kernel_ = static_cast<FlexArray *>(ptr);
  53. }
  54. if (kernel_ == nullptr) {
  55. MS_LOG(ERROR) << "Memory malloc failed.";
  56. kernel_bin.close();
  57. return false;
  58. }
  59. if (memset_s(kernel_, sizeof(KernelPack) + bin_size, 0, sizeof(KernelPack) + bin_size) != EOK) {
  60. MS_LOG(ERROR) << "Memset kernel_ failed.";
  61. delete[] kernel_;
  62. kernel_ = nullptr;
  63. kernel_bin.close();
  64. return false;
  65. }
  66. kernel_->len = bin_size;
  67. (void)kernel_bin.seekg(0, std::ios::beg);
  68. (void)kernel_bin.read(kernel_->contents, SizeToLong(kernel_->len));
  69. return true;
  70. }
  71. bool KernelPack::ReadFromJsonFile(const std::string &json_f, const std::string &processor) {
  72. if (json_f.length() <= strlen(kJsonSuffix)) {
  73. MS_LOG(ERROR) << "Please check json path, file name: " << json_f;
  74. return false;
  75. }
  76. std::ifstream kernel_json(json_f);
  77. if (!kernel_json.is_open()) {
  78. MS_LOG(DEBUG) << "Read json file(" << json_f << ") error, please check kernel_meta.";
  79. return false;
  80. }
  81. nlohmann::json js;
  82. kernel_json >> js;
  83. size_t bin_size = LongToSize(kernel_json.seekg(0, std::ios::end).tellg());
  84. void *ptr = static_cast<void *>(new (std::nothrow) uint8_t[sizeof(KernelPack) + bin_size]);
  85. if (ptr != nullptr) {
  86. json_ = static_cast<FlexArray *>(ptr);
  87. }
  88. if (json_ == nullptr) {
  89. MS_LOG(ERROR) << "memory malloc failed.";
  90. kernel_json.close();
  91. return false;
  92. }
  93. json_->len = bin_size;
  94. (void)kernel_json.seekg(0, std::ios::beg);
  95. (void)kernel_json.read(json_->contents, SizeToLong(json_->len));
  96. if (processor == kProcessorCpu) {
  97. std::string bin_f = json_f.substr(0, json_f.length() - 5) + ".so";
  98. if (!CheckHash(json_f, bin_f, js)) {
  99. return false;
  100. }
  101. return true;
  102. }
  103. if (processor == kProcessorCuda) {
  104. std::string bin_f = json_f.substr(0, json_f.length() - kJsonSuffixLength) + ".ptx";
  105. std::ifstream kernelbin(bin_f);
  106. if (!kernelbin.is_open()) {
  107. MS_LOG(ERROR) << "read kernel ptx file error, please check kernelmeta.";
  108. kernel_json.close();
  109. return false;
  110. }
  111. if (!ReadFromJsonFileHelper(kernelbin)) {
  112. delete[] json_;
  113. json_ = nullptr;
  114. kernel_json.close();
  115. return false;
  116. }
  117. kernel_json.close();
  118. if (!CheckHash(json_f, bin_f, js)) {
  119. return false;
  120. }
  121. // cuda json file may have workspace information
  122. if (js.find("workspace") != js.end()) {
  123. auto workspace = js.at("workspace");
  124. std::vector<size_t> sizes = workspace.at("size");
  125. for (auto size : sizes) {
  126. kernel_json_info_.workspaces.push_back(size);
  127. }
  128. }
  129. return true;
  130. }
  131. std::string binfile_suffix = js["binFileSuffix"];
  132. std::string bin_f = json_f.substr(0, json_f.length() - kJsonSuffixLength) + binfile_suffix;
  133. if (binfile_suffix == ".so") {
  134. // change "xx/xx.so" -> "xx/libxx.so"
  135. auto sp = bin_f.rfind('/');
  136. if (sp == std::string::npos) {
  137. MS_LOG(ERROR) << "illegal bin file path " << bin_f;
  138. kernel_json.close();
  139. return false;
  140. }
  141. bin_f = bin_f.substr(0, sp + 1) + "lib" + bin_f.substr(sp + 1, bin_f.length() - sp - 1);
  142. }
  143. std::ifstream kernelbin(bin_f, std::ios::binary);
  144. if (!kernelbin.is_open()) {
  145. MS_LOG(ERROR) << "read kernel binary file error, please check kernelmeta.";
  146. kernel_json.close();
  147. delete[] json_;
  148. json_ = nullptr;
  149. return false;
  150. }
  151. MS_LOG(INFO) << "kernelbin_name:" << bin_f;
  152. if (!ReadFromJsonFileHelper(kernelbin)) {
  153. delete[] json_;
  154. json_ = nullptr;
  155. kernel_json.close();
  156. return false;
  157. }
  158. kernel_json.close();
  159. if (!CheckHash(json_f, bin_f, js)) {
  160. return false;
  161. }
  162. return true;
  163. }
  164. void KernelPack::ParseKernelJson(const nlohmann::json &js) {
  165. kernel_json_info_.bin_file_name = js["binFileName"];
  166. kernel_json_info_.bin_file_suffix = js["binFileSuffix"];
  167. kernel_json_info_.block_dim = js["blockDim"];
  168. kernel_json_info_.kernel_name = js["kernelName"];
  169. kernel_json_info_.magic = js["magic"];
  170. if (js.contains("opParaSize")) {
  171. kernel_json_info_.op_para_size = js["opParaSize"];
  172. }
  173. if (js.find("parameters") != js.end()) {
  174. if (!js.at("parameters").is_array()) {
  175. MS_LOG(DEBUG) << "Format error!,parameters should be array.";
  176. }
  177. std::vector<size_t> sizes = js.at("parameters");
  178. for (auto size : sizes) {
  179. kernel_json_info_.parameters.push_back(size);
  180. }
  181. }
  182. if (js.find("workspace") != js.end()) {
  183. auto workspace = js.at("workspace");
  184. std::vector<size_t> sizes = workspace.at("size");
  185. for (auto size : sizes) {
  186. kernel_json_info_.workspaces.push_back(size);
  187. }
  188. }
  189. kernel_json_info_.sha256 = js["sha256"];
  190. kernel_json_info_.has_kernel_list = js.find("kernelList") != js.end();
  191. }
  192. bool KernelPack::LoadKernelMeta(const std::string &json_f) {
  193. if (json_f.length() <= strlen(kJsonSuffix)) {
  194. MS_LOG(ERROR) << "please check json path.";
  195. return false;
  196. }
  197. std::ifstream kernel_json(json_f);
  198. if (!kernel_json.is_open()) {
  199. MS_LOG(INFO) << "Open json file: " << json_f << " error, please check kernel_meta.";
  200. return false;
  201. }
  202. nlohmann::json js;
  203. try {
  204. kernel_json >> js;
  205. kernel_json.close();
  206. } catch (std::exception &e) {
  207. MS_LOG(WARNING) << "Parse json file error: " << json_f << ", sleep 500ms and retry again. error ms: " << e.what();
  208. kernel_json.close();
  209. std::this_thread::sleep_for(std::chrono::microseconds(500000));
  210. std::ifstream retry_tmp(json_f);
  211. if (!retry_tmp.is_open()) {
  212. MS_LOG(INFO) << "Open json file: " << json_f << " error, please check kernel_meta.";
  213. return false;
  214. }
  215. retry_tmp >> js;
  216. retry_tmp.close();
  217. }
  218. ParseKernelJson(js);
  219. std::string bin_f = json_f.substr(0, json_f.length() - kJsonSuffixLength) + kernel_json_info_.bin_file_suffix;
  220. if (kernel_json_info_.bin_file_suffix == ".so") {
  221. // change "xx/xx.so" -> "xx/libxx.so"
  222. auto sp = bin_f.rfind('/');
  223. if (sp == std::string::npos) {
  224. MS_LOG(ERROR) << "illegal bin file path " << bin_f;
  225. return false;
  226. }
  227. bin_f = bin_f.substr(0, sp + 1) + "lib" + bin_f.substr(sp + 1, bin_f.length() - sp - 1);
  228. }
  229. std::ifstream kernelbin(bin_f, std::ios::binary);
  230. if (!kernelbin.is_open()) {
  231. MS_LOG(ERROR) << "read kernel binary file error, please check kernelmeta.";
  232. return false;
  233. }
  234. if (!ReadFromJsonFileHelper(kernelbin)) {
  235. return false;
  236. }
  237. return CheckHash(json_f, bin_f, js);
  238. }
  239. KernelJsonInfo KernelPack::kernel_json_info() const { return kernel_json_info_; }
  240. } // namespace kernel
  241. } // namespace mindspore