/** * Copyright 2019 Huawei Technologies Co., Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "common/utils.h" namespace mindspore { namespace predict { uint64_t GetTimeUs() { struct timespec ts = {0, 0}; if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) { return 0; } // USECS_IN_SEC *NSECS_IN_USEC; auto retval = static_cast((ts.tv_sec * USEC) + (ts.tv_nsec / MSEC)); return retval; } static const unsigned int FP32_BIT_SIZE = 32; static const unsigned int FP32_EXPONENT_BIAS = 127; static const unsigned int FP32_SIGNIFICAND = 23; static const unsigned int FP32_EXPONENT_MAX = 255; static const unsigned int FP16_BIT_SIZE = 16; static const unsigned int FP16_EXPONENT_BIAS = 15; static const unsigned int FP16_SIGNIFICAND = 10; static const int FP16_EXPONENT_MAX = 30; static const int FP16_EXPONENT_MIN = -10; float ShortToFloat32(int16_t srcValue) { uint16_t expHalf16 = srcValue & 0x7C00; int exp1 = static_cast(expHalf16); uint16_t mantissa16 = srcValue & 0x03FF; int mantissa1 = static_cast(mantissa16); int sign = static_cast(srcValue & 0x8000); sign = sign << FP16_BIT_SIZE; // nan or inf if (expHalf16 == 0x7C00) { // nan if (mantissa16 > 0) { int res = (0x7FC00000 | sign); int *iRes = &res; MS_ASSERT(iRes != nullptr); auto fres = static_cast(*iRes); return fres; } // inf int res = (0x7F800000 | sign); int *iRes = &res; MS_ASSERT(iRes != nullptr); auto fres = static_cast(*iRes); return fres; } if (expHalf16 != 0) { exp1 += ((FP32_EXPONENT_BIAS - FP16_EXPONENT_BIAS) << FP16_SIGNIFICAND); // exponents converted to float32 bias int res = (exp1 | mantissa1); res = res << (FP32_SIGNIFICAND - FP16_SIGNIFICAND); res = (res | sign); int *iRes = &res; auto fres = static_cast(*iRes); return fres; } int xmm1 = exp1 > (1 << FP16_SIGNIFICAND) ? exp1 : (1 << FP16_SIGNIFICAND); xmm1 = (xmm1 << (FP32_SIGNIFICAND - FP16_SIGNIFICAND)); xmm1 += ((FP32_EXPONENT_BIAS - FP16_EXPONENT_BIAS - FP16_SIGNIFICAND) << FP32_SIGNIFICAND); // add the bias difference to xmm1 xmm1 = xmm1 | sign; // Combine with the sign mask auto res = static_cast(mantissa1); // Convert mantissa to float res *= static_cast(xmm1); return res; } int16_t Float32ToShort(float srcValue) { auto srcValueBit = static_cast(srcValue); int sign = srcValueBit >> (FP32_BIT_SIZE - 1); int mantissa = srcValueBit & 0x007FFFFF; // exponent int exp = ((srcValueBit & 0x7F800000) >> FP32_SIGNIFICAND) + FP16_EXPONENT_BIAS - FP32_EXPONENT_BIAS; int16_t res; if (exp > 0 && exp < FP16_EXPONENT_MAX) { // use rte rounding mode, round the significand, combine sign, exponent and significand into a short. res = (sign << (FP16_BIT_SIZE - 1)) | (exp << FP16_SIGNIFICAND) | ((mantissa + 0x00001000) >> (FP32_SIGNIFICAND - FP16_SIGNIFICAND)); } else if (srcValueBit == 0) { res = 0; } else { if (exp <= 0) { if (exp < FP16_EXPONENT_MIN) { // value is less than min half float point res = 0; } else { // normalized single, magnitude is less than min normal half float point. mantissa = (mantissa | 0x00800000) >> (1 - exp); // round to nearest if ((mantissa & 0x00001000) > 0) { mantissa = mantissa + 0x00002000; } // combine sign & mantissa (exp is zero to get denormalized number) res = (sign << FP16_EXPONENT_BIAS) | (mantissa >> (FP32_SIGNIFICAND - FP16_SIGNIFICAND)); } } else if (exp == (FP32_EXPONENT_MAX - FP32_EXPONENT_BIAS + FP16_EXPONENT_BIAS)) { if (mantissa == 0) { // input float is infinity, return infinity half res = (sign << FP16_EXPONENT_BIAS) | 0x7C00; } else { // input float is NaN, return half NaN res = (sign << FP16_EXPONENT_BIAS) | 0x7C00 | (mantissa >> (FP32_SIGNIFICAND - FP16_SIGNIFICAND)); } } else { // exp > 0, normalized single, round to nearest if ((mantissa & 0x00001000) > 0) { mantissa = mantissa + 0x00002000; if ((mantissa & 0x00800000) > 0) { mantissa = 0; exp = exp + 1; } } if (exp > FP16_EXPONENT_MAX) { // exponent overflow - return infinity half res = (sign << FP16_EXPONENT_BIAS) | 0x7C00; } else { // combine sign, exp and mantissa into normalized half res = (sign << FP16_EXPONENT_BIAS) | (exp << FP16_SIGNIFICAND) | (mantissa >> (FP32_SIGNIFICAND - FP16_SIGNIFICAND)); } } } return res; } std::string Remove(const std::string &from, const std::string &subStr, Mode mode) { std::string result = from; if (mode == PREFIX) { if (from.substr(0, subStr.length()) == subStr) { result = from.substr(subStr.size()); } } else if (mode == SUFFIX) { if (from.rfind(subStr) == from.size() - subStr.size()) { result = from.substr(0, from.size() - subStr.size()); } } else { size_t index; while ((index = result.find(subStr)) != std::string::npos) { result = result.erase(index, subStr.size()); } } return result; } std::vector StrSplit(const std::string &str, const std::string &pattern) { std::string::size_type pos; std::vector result; std::string tmpStr(str + pattern); std::string::size_type size = tmpStr.size(); for (std::string::size_type i = 0; i < size; i++) { pos = tmpStr.find(pattern, i); if (pos < size) { std::string s = tmpStr.substr(i, pos - i); result.push_back(s); i = pos + pattern.size() - 1; } } return result; } std::vector Tokenize(const std::string &src, const std::string &delimiters, const Option &maxTokenNum) { if (maxTokenNum.IsSome() && maxTokenNum.Get() == 0) { return {}; } std::vector tokens; size_t offset = 0; while (true) { size_t nonDelimiter = src.find_first_not_of(delimiters, offset); if (nonDelimiter == std::string::npos) { break; } size_t delimiter = src.find_first_of(delimiters, nonDelimiter); if (delimiter == std::string::npos || (maxTokenNum.IsSome() && tokens.size() == maxTokenNum.Get() - 1)) { tokens.push_back(src.substr(nonDelimiter)); break; } tokens.push_back(src.substr(nonDelimiter, delimiter - nonDelimiter)); offset = delimiter; } return tokens; } void ShortToFloat32(const int16_t *srcdata, float *dstdata, size_t elementSize) { MS_ASSERT(srcdata != nullptr); MS_ASSERT(dstdata != nullptr); for (size_t i = 0; i < elementSize; i++) { dstdata[i] = ShortToFloat32(srcdata[i]); } } void Float32ToShort(const float *srcdata, int16_t *dstdata, size_t elementSize) { MS_ASSERT(srcdata != nullptr); MS_ASSERT(dstdata != nullptr); for (size_t i = 0; i < elementSize; i++) { dstdata[i] = Float32ToShort(srcdata[i]); } } } // namespace predict } // namespace mindspore