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