weight format is [co, ci, kh, kw]
| 103 | |
| 104 | // weight format is [co, ci, kh, kw] |
| 105 | int SymmetricQuantizeWeight(const float* weight, const int size, int8_t* quantizedWeight, float* scale, |
| 106 | const int channels, float weightClampValue) { |
| 107 | DCHECK((size % channels) == 0) << "weight size error!"; |
| 108 | const int channelStride = size / channels; |
| 109 | const int quantizedMaxValue = weightClampValue; |
| 110 | |
| 111 | for (int c = 0; c < channels; ++c) { |
| 112 | const auto weightChannelStart = weight + c * channelStride; |
| 113 | auto quantizedWeightChannelStart = quantizedWeight + c * channelStride; |
| 114 | auto minmaxValue = std::minmax_element(weightChannelStart, weightChannelStart + channelStride); |
| 115 | const float dataAbsMax = std::fmax(std::fabs(*minmaxValue.first), std::fabs(*minmaxValue.second)); |
| 116 | |
| 117 | float scaleDataToInt8 = 1.0f; |
| 118 | if (dataAbsMax == 0) { |
| 119 | scale[c] = 0.0f; |
| 120 | } else { |
| 121 | scale[c] = dataAbsMax / quantizedMaxValue; |
| 122 | scaleDataToInt8 = quantizedMaxValue / dataAbsMax; |
| 123 | } |
| 124 | |
| 125 | for (int i = 0; i < channelStride; ++i) { |
| 126 | const int32_t quantizedInt8Value = static_cast<int32_t>(roundf(weightChannelStart[i] * scaleDataToInt8)); |
| 127 | quantizedWeightChannelStart[i] = |
| 128 | std::min(quantizedMaxValue, std::max(-quantizedMaxValue, quantizedInt8Value)); |
| 129 | } |
| 130 | } |
| 131 | |
| 132 | return 0; |
| 133 | } |
| 134 | |
| 135 | int QuantizeConvPerChannel(const float* weight, const int size, const float* bias, int8_t* quantizedWeight, |
| 136 | int32_t* quantizedBias, float* scale, const float inputScale, const float outputScale, |
no test coverage detected