• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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