1 #ifndef CAFFE2_INT8_UTILS_H_ 2 #define CAFFE2_INT8_UTILS_H_ 4 #include <gemmlowp/public/gemmlowp.h> 6 #include "caffe2/utils/threadpool/ThreadPool.h" 7 #include "caffe2/utils/threadpool/WorkersPool.h" 38 inline int32_t MultiplyByQuantizedMultiplierSmallerThanOne(
40 int32_t quantized_multiplier,
42 using gemmlowp::RoundingDivideByPOT;
43 using gemmlowp::SaturatingRoundingDoublingHighMul;
44 return RoundingDivideByPOT(
45 SaturatingRoundingDoublingHighMul(x, quantized_multiplier), right_shift);
48 #if defined(__ANDROID__) && !defined(__NDK_MAJOR__) 50 inline float Round(
const float x) {
51 return ::nearbyintf(x);
53 inline double Round(
const double x) {
54 return ::nearbyint(x);
58 inline T Round(
const T x) {
59 return std::nearbyint(x);
63 inline uint8_t QuantizeUint8(
float scale, int32_t zero_point,
float value) {
64 const int32_t qmin = std::numeric_limits<uint8_t>::min();
65 const int32_t qmax = std::numeric_limits<uint8_t>::max();
67 auto r = zero_point +
static_cast<int32_t
>(Round(value / scale));
68 r = std::max(r, qmin);
69 r = std::min(r, qmax);
70 return static_cast<uint8_t
>(r);
73 inline void QuantizeMultiplierSmallerThanOne(
74 double double_multiplier,
75 int32_t* quantized_multiplier,
77 CHECK(double_multiplier >= 0.);
78 CHECK(double_multiplier < 1.);
79 if (double_multiplier == 0.) {
80 *quantized_multiplier = 0;
84 CHECK(double_multiplier > 0.);
85 const double q = std::frexp(double_multiplier, right_shift);
88 auto q_fixed =
static_cast<int64_t
>(Round(q * (1ll << 31)));
89 CHECK(q_fixed <= (1ll << 31));
90 if (q_fixed == (1ll << 31)) {
94 CHECK_GE(*right_shift, 0);
95 CHECK_LE(q_fixed, std::numeric_limits<int32_t>::max());
96 *quantized_multiplier =
static_cast<int32_t
>(q_fixed);
99 inline void QuantizeMultiplierGreaterThanOne(
100 double double_multiplier,
101 int32_t* quantized_multiplier,
103 CHECK(double_multiplier > 1.);
104 const double q = std::frexp(double_multiplier, left_shift);
105 auto q_fixed =
static_cast<int64_t
>(Round(q * (1ll << 31)));
106 CHECK(q_fixed <= (1ll << 31));
107 if (q_fixed == (1ll << 31)) {
111 CHECK_GE(*left_shift, 0);
112 CHECK_LE(q_fixed, std::numeric_limits<int32_t>::max());
113 *quantized_multiplier =
static_cast<int32_t
>(q_fixed);
116 inline int32_t MultiplyByQuantizedMultiplierGreaterThanOne(
118 int32_t quantized_multiplier,
120 using gemmlowp::SaturatingRoundingDoublingHighMul;
121 return SaturatingRoundingDoublingHighMul(
122 x * (1 << left_shift), quantized_multiplier);
125 inline int CalculateInputRadius(
int input_integer_bits,
int input_left_shift) {
126 const double max_input_rescaled = 1.0 * ((1 << input_integer_bits) - 1) *
127 (1ll << (31 - input_integer_bits)) / (1ll << input_left_shift);
131 return static_cast<int>(std::floor(max_input_rescaled));
134 enum class Activation : uint8_t { NONE = 0, RELU = 1 };
136 inline std::pair<uint8_t, uint8_t>
137 activationLimits(
float scale, int32_t zero_point, Activation Ac) {
139 case Activation::NONE:
140 return {std::numeric_limits<uint8_t>::min(),
141 std::numeric_limits<uint8_t>::max()};
142 case Activation::RELU:
143 return {QuantizeUint8(scale, zero_point, 0.0),
144 std::numeric_limits<uint8_t>::max()};
149 __builtin_unreachable();
157 #endif // CAFFE2_INT8_UTILS_H_
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...