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
17 #if defined(__ANDROID__) || defined(MS_COMPILE_OHOS)
18 #include <sys/auxv.h>
19 #include <asm/hwcap.h>
20 #endif
21 #include "src/common/utils.h"
22 #if defined(_MSC_VER) || defined(_WIN32)
23 #include <windows.h>
24 #undef ERROR
25 #else
26 #include <unistd.h>
27 #include <sys/types.h>
28 #include <sys/param.h>
29 #endif
30
31 namespace mindspore {
32 namespace lite {
33 namespace {
34 constexpr int32_t kNum3 = 3;
35 constexpr auto kNumberChars = "0123456789";
36 } // namespace
37
GetTimeUs()38 uint64_t GetTimeUs() {
39 #ifdef _MSC_VER
40 const int sec_to_us = 1000000;
41 LARGE_INTEGER cur_time;
42 LARGE_INTEGER frequency;
43 QueryPerformanceCounter(&cur_time);
44 QueryPerformanceFrequency(&frequency);
45 uint64_t sec = cur_time.QuadPart / frequency.QuadPart;
46 uint64_t usec = (cur_time.QuadPart % frequency.QuadPart) * sec_to_us / frequency.QuadPart;
47 return sec * sec_to_us + usec;
48 #else
49 struct timespec ts = {0, 0};
50 if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
51 return 0;
52 }
53 // USECS_IN_SEC *NSECS_IN_USEC;
54 auto ret_val = static_cast<uint64_t>((ts.tv_sec * USEC) + (ts.tv_nsec / MSEC));
55 return ret_val;
56 #endif
57 }
58
RemoveSubStr(const std::string & from,const std::string & sub_str,RemoveSubStrMode mode)59 std::string RemoveSubStr(const std::string &from, const std::string &sub_str, RemoveSubStrMode mode) {
60 std::string result = from;
61 if (from.empty()) {
62 MS_LOG(ERROR) << "string is empty";
63 return "";
64 }
65 if (sub_str.length() > from.length()) {
66 MS_LOG(ERROR) << "sub_str is longer than from";
67 return "";
68 }
69 if (mode == PREFIX) {
70 if (from.substr(0, sub_str.length()) == sub_str) {
71 result = from.substr(sub_str.length());
72 }
73 } else if (mode == SUFFIX) {
74 if (from.rfind(sub_str) == from.length() - sub_str.length()) {
75 result = from.substr(0, from.length() - sub_str.length());
76 }
77 } else {
78 size_t index;
79 while ((index = result.find(sub_str)) != std::string::npos) {
80 result = result.erase(index, sub_str.length());
81 }
82 }
83
84 return result;
85 }
86
StrSplit(const std::string & str,const std::string & delim)87 std::vector<std::string> StrSplit(const std::string &str, const std::string &delim) {
88 if (str.empty()) {
89 return {};
90 }
91 auto start = 0U;
92 auto end = str.find(delim);
93 std::vector<std::string> substrs;
94 while (end != std::string::npos) {
95 substrs.push_back(str.substr(start, end - start));
96 start = end + delim.length();
97 end = str.find(delim, start);
98 }
99 substrs.push_back(str.substr(start, end));
100 return substrs;
101 }
102
ParseShapeStr(const std::string & shape_str,std::vector<int64_t> * shape_ptr)103 bool ParseShapeStr(const std::string &shape_str, std::vector<int64_t> *shape_ptr) {
104 if (shape_ptr == nullptr) {
105 MS_LOG(ERROR) << "Input argument shape_ptr is nullptr";
106 return false;
107 }
108 auto str_dims = lite::StrSplit(shape_str, ",");
109 if (str_dims.empty()) {
110 MS_LOG(ERROR) << "Invalid input shape dim, dims number cannot be 0";
111 return false;
112 }
113 auto &shape = *shape_ptr;
114 shape.resize(str_dims.size());
115 for (size_t i = 0; i != str_dims.size(); ++i) {
116 int32_t dim = 0;
117 if (!ConvertStrToInt(str_dims[i], &dim)) {
118 MS_LOG(ERROR) << "Invalid input shape dim, dim value range or format is invalid: " << shape_str;
119 return false;
120 }
121 if (dim <= 0 && dim != -1) {
122 MS_LOG(ERROR) << "Invalid input shape dim, dim can only be -1 when dim < 0: " << shape_str;
123 return false;
124 }
125 shape[i] = dim;
126 }
127 return true;
128 }
129
ParseShapeStr(const std::string & shape_str,std::vector<ShapeDim> * shape_ptr)130 bool ParseShapeStr(const std::string &shape_str, std::vector<ShapeDim> *shape_ptr) {
131 if (shape_ptr == nullptr) {
132 return false;
133 }
134 auto str_dims = lite::StrSplit(shape_str, ",");
135 if (str_dims.empty()) {
136 MS_LOG(ERROR) << "Invalid input shape dim, dims number cannot be 0: " << shape_str;
137 return false;
138 }
139 auto &shape = *shape_ptr;
140 shape.resize(str_dims.size());
141 constexpr size_t range_value_size = 1;
142 constexpr size_t range_min_max_size = 2;
143 for (size_t i = 0; i != str_dims.size(); ++i) {
144 auto dim_range = lite::StrSplit(str_dims[i], "~");
145 if (dim_range.size() == range_value_size) {
146 int32_t dim = 0;
147 if (!ConvertStrToInt(str_dims[i], &dim)) {
148 MS_LOG(ERROR) << "Invalid input shape dim, dim value range or format is invalid: " << shape_str;
149 return false;
150 }
151 if (dim <= 0 && dim != -1) {
152 MS_LOG(ERROR) << "Invalid input shape dim, dim can only be -1 when dim < 0: " << shape_str;
153 return false;
154 }
155 shape[i].dim = dim;
156 shape[i].min = dim;
157 shape[i].max = dim;
158 } else if (dim_range.size() == range_min_max_size) {
159 int32_t left = 0;
160 if (!ConvertStrToInt(dim_range[0], &left)) {
161 MS_LOG(ERROR) << "Invalid input shape dim range, dim value range or format is invalid: " << shape_str;
162 return false;
163 }
164 int32_t right = 0;
165 if (!ConvertStrToInt(dim_range[1], &right)) {
166 MS_LOG(ERROR) << "Invalid input shape dim range, dim value range or format is invalid: " << shape_str;
167 return false;
168 }
169 if (left < 1 || right < 1 || left > right) {
170 MS_LOG(ERROR) << "Invalid input shape dim range, dim value range or format is invalid: " << shape_str;
171 return false;
172 }
173 shape[i].dim = -1;
174 shape[i].min = left;
175 shape[i].max = right;
176 } else {
177 MS_LOG(ERROR) << "Invalid input shape dim range, dim value range or format is invalid: " << shape_str;
178 return false;
179 }
180 }
181 return true;
182 }
183
ConvertStrToInt(const std::string & str,int * value)184 bool ConvertStrToInt(const std::string &str, int *value) {
185 if (value == nullptr) {
186 MS_LOG(ERROR) << "Value is nullptr";
187 return false;
188 }
189 if (str.empty()) {
190 return false;
191 }
192 char *ptr = nullptr;
193 constexpr int kBase = 10;
194 auto int_val = std::strtol(str.c_str(), &ptr, kBase);
195 if (ptr != (str.c_str() + str.size())) {
196 return false;
197 }
198 if (int_val > INT32_MAX || int_val < INT32_MIN || errno == ERANGE) {
199 MS_LOG(WARNING) << "The range of value is beyond the range of int32";
200 return false;
201 }
202 *value = static_cast<int32_t>(int_val);
203 return true;
204 }
205
ConvertStrToInt(const std::string & str,int64_t * value)206 bool ConvertStrToInt(const std::string &str, int64_t *value) {
207 if (value == nullptr) {
208 MS_LOG(ERROR) << "Value is nullptr";
209 return false;
210 }
211 if (str.empty()) {
212 return false;
213 }
214 char *ptr = nullptr;
215 constexpr int kBase = 10;
216 auto int_val = std::strtol(str.c_str(), &ptr, kBase);
217 if (ptr != (str.c_str() + str.size())) {
218 return false;
219 }
220 if (errno == ERANGE) {
221 MS_LOG(WARNING) << "The range of value is beyond the range of int64";
222 return false;
223 }
224 *value = int_val;
225 return true;
226 }
227
Tokenize(const std::string & src,const std::string & delimiters,const Option<size_t> & max_token_num)228 std::vector<std::string> Tokenize(const std::string &src, const std::string &delimiters,
229 const Option<size_t> &max_token_num) {
230 if (max_token_num.IsSome() && max_token_num.Get() == 0) {
231 return {};
232 }
233
234 if (src.empty()) {
235 MS_LOG(ERROR) << "string is empty";
236 return {};
237 }
238
239 std::vector<std::string> tokens;
240 size_t offset = 0;
241
242 while (true) {
243 size_t nonDelimiter = src.find_first_not_of(delimiters, offset);
244 if (nonDelimiter == std::string::npos) {
245 break;
246 }
247 size_t delimiter = src.find_first_of(delimiters, nonDelimiter);
248 if (delimiter == std::string::npos || (max_token_num.IsSome() && tokens.size() == max_token_num.Get() - 1)) {
249 tokens.push_back(src.substr(nonDelimiter));
250 break;
251 }
252
253 tokens.push_back(src.substr(nonDelimiter, delimiter - nonDelimiter));
254 offset = delimiter;
255 }
256 return tokens;
257 }
258
GetShortVersionStr(const std::string & str)259 std::string GetShortVersionStr(const std::string &str) {
260 size_t first_digit = str.find_first_of(kNumberChars);
261 if (first_digit == std::string::npos) {
262 return "";
263 }
264 auto str_splits = StrSplit(str.substr(first_digit), ".");
265 if (str_splits.size() < kNum3) {
266 return "";
267 }
268 auto str3 = str_splits[kNum3 - 1];
269 size_t last_digit = str3.find_first_not_of(kNumberChars);
270 if (last_digit != std::string::npos) {
271 str_splits[kNum3 - 1] = str3.substr(0, last_digit);
272 }
273 return str_splits[0] + "." + str_splits[1] + "." + str_splits[kNum3 - 1];
274 }
275
IsVersionGreaterThan(const std::string & str1,const std::string & str2)276 bool IsVersionGreaterThan(const std::string &str1, const std::string &str2) {
277 auto str1_splits = StrSplit(str1, ".");
278 auto str2_splits = StrSplit(str2, ".");
279 size_t len1 = str1_splits.size();
280 size_t len2 = str2_splits.size();
281 size_t len = std::min(len1, len2);
282 for (size_t i = 0; i < len; ++i) {
283 if (str1_splits[i] != str2_splits[i]) {
284 return std::stoi(str1_splits[i]) > std::stoi(str2_splits[i]);
285 }
286 }
287 return len1 > len2;
288 }
289
290 #if defined(__ANDROID__) || defined(MS_COMPILE_OHOS)
getHwCap(int hwcap_type)291 uint32_t getHwCap(int hwcap_type) {
292 uint32_t ret = getauxval(hwcap_type);
293 return ret;
294 }
295 #endif
296
IsSupportSDot()297 bool IsSupportSDot() {
298 bool status = false;
299 #ifdef ENABLE_ARM64
300 #if defined(__ANDROID__) || defined(MS_COMPILE_OHOS)
301 int hwcap_type = 16;
302 uint32_t hwcap = getHwCap(hwcap_type);
303 if (hwcap & HWCAP_ASIMDDP) {
304 MS_LOG(DEBUG) << "Hw cap support SMID Dot Product, hwcap: 0x" << hwcap;
305 status = true;
306 } else {
307 MS_LOG(DEBUG) << "Hw cap NOT support SIMD Dot Product, hwcap: 0x" << hwcap;
308 status = false;
309 }
310 #endif
311 #endif
312 return status;
313 }
314
GetMaxMallocSize()315 size_t GetMaxMallocSize() {
316 size_t max_malloc_size = 0;
317 #if defined(_MSC_VER) || defined(_WIN32)
318 MEMORYSTATUSEX status;
319 status.dwLength = sizeof(status);
320 GlobalMemoryStatusEx(&status);
321 max_malloc_size = static_cast<size_t>(status.ullTotalPhys);
322 #else
323 max_malloc_size = static_cast<size_t>(sysconf(_SC_PHYS_PAGES)) * static_cast<size_t>(sysconf(_SC_PAGESIZE));
324 #endif
325 return max_malloc_size;
326 }
327
GetCoreNum()328 int GetCoreNum() {
329 int core_num = 1;
330 #if defined(_MSC_VER) || defined(_WIN32)
331 SYSTEM_INFO sysinfo;
332 GetSystemInfo(&sysinfo);
333 core_num = sysinfo.dwNumberOfProcessors;
334 #else
335 core_num = sysconf(_SC_NPROCESSORS_CONF);
336 #endif
337 return core_num;
338 }
339 } // namespace lite
340 } // namespace mindspore
341