• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright 2021 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 "schema/inner/model_generated.h"
18 #include "src/common/quant_utils.h"
19 #include "src/lite_kernel.h"
20 
21 namespace mindspore {
22 namespace lite {
GetMaxMinPerChannel(int channels,int one_filter_size,int i,int elem_count,const float * raw_datas,bool channel_at_first,float * desired_max,float * desired_min)23 STATUS GetMaxMinPerChannel(int channels, int one_filter_size, int i, int elem_count, const float *raw_datas,
24                            bool channel_at_first, float *desired_max, float *desired_min) {
25   float min = FLT_MAX;
26   float max = -FLT_MAX;
27   // find min and max
28   for (int j = 0; j < one_filter_size; j++) {
29     auto index = j + i * one_filter_size;
30     if (!channel_at_first) {
31       index = j * channels + i;
32     }
33     if (index >= elem_count) {
34       MS_LOG(ERROR) << "over flow!";
35       return RET_ERROR;
36     }
37     min = std::min(min, raw_datas[index]);
38     max = std::max(max, raw_datas[index]);
39   }
40   *desired_max = max;
41   *desired_min = min;
42   return RET_OK;
43 }
44 
CalQuantizationParams(schema::QuantParamT * quant_param,double real_min,double real_max,bool narrow_range,int quant_max,int quant_min,int num_bits)45 STATUS CalQuantizationParams(schema::QuantParamT *quant_param, double real_min, double real_max, bool narrow_range,
46                              int quant_max, int quant_min, int num_bits) {
47   MS_ASSERT(quant_param != nullptr);
48   if (real_min > 0.0f) {
49     MS_LOG(DEBUG) << "min " << real_min << " is bigger then 0, set to 0, this may course low precision";
50     real_min = 0.0f;
51   }
52   if (real_max < 0.0f) {
53     MS_LOG(DEBUG) << "real_max " << real_max << " is smaller than 0, set to 0, this may course low precision";
54     real_max = 0.0f;
55   }
56   if (real_min > real_max) {
57     MS_LOG(ERROR) << "cal error while min" << real_min << ">" << real_max;
58     return RET_PARAM_INVALID;
59   }
60   if (real_min == real_max) {
61     if (real_min != 0.0f) {
62       MS_LOG(ERROR) << "min and max should both be zero if they are equal to each other";
63       return RET_ERROR;
64     }
65     MS_LOG(WARNING) << "The maximum and minimum values are equal to 0.";
66     quant_param->inited = true;
67     quant_param->min = real_min;
68     quant_param->max = real_max;
69     quant_param->scale = 1;
70     quant_param->zeroPoint = 0;
71     quant_param->narrowRange = narrow_range;
72     quant_param->numBits = num_bits;
73     return RET_OK;
74   }
75 
76   auto quantMinFloat = static_cast<double>(quant_min);
77   auto quantMaxFloat = static_cast<double>(quant_max);
78   if (fabs(quantMaxFloat - quantMinFloat) <= 0.0f) {
79     MS_LOG(ERROR) << "divisor cannot be 0";
80     return RET_ERROR;
81   }
82   double scale = (real_max - real_min) / (quantMaxFloat - quantMinFloat);
83   if (fabs(scale) <= 0.0f) {
84     MS_LOG(ERROR) << "divisor 'scale' cannot be 0";
85     return RET_ERROR;
86   }
87   const double zeroPointFromMin = quantMinFloat - real_min / scale;
88   int zeroPoint = static_cast<int32_t>(std::round(zeroPointFromMin));
89 
90   // The zero point should always be in the range of quantized value,
91   // [qmin, qmax].
92   MS_ASSERT(zeroPoint >= quant_min);
93   MS_ASSERT(zeroPoint <= quant_max);
94   quant_param->inited = true;
95   quant_param->min = real_min;
96   quant_param->max = real_max;
97   quant_param->scale = scale;
98   quant_param->zeroPoint = zeroPoint;
99   quant_param->narrowRange = narrow_range;
100   quant_param->numBits = num_bits;
101 
102   return RET_OK;
103 }
104 }  // namespace lite
105 }  // namespace mindspore
106