| 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, |
| 137 | const int inputChannel, const int outputChannel, std::string method, float weightClampValue, bool mergeChannel) { |
| 138 | const int icXoc = inputChannel * outputChannel; |
| 139 | DCHECK(size % icXoc == 0) << "Input Data Size Error!"; |
| 140 | |
| 141 | std::vector<float> quantizedWeightScale(outputChannel); |
| 142 | |
| 143 | float inputScalexWeight = 1.0f; |
| 144 | if (mergeChannel) { |
| 145 | if (method == "MAX_ABS"){ |
| 146 | SymmetricQuantizeWeight(weight, size, quantizedWeight, quantizedWeightScale.data(), outputChannel, weightClampValue); |
| 147 | } |
| 148 | else if (method == "ADMM") { |
| 149 | QuantizeWeightADMM(weight, size, quantizedWeight, quantizedWeightScale.data(), outputChannel, weightClampValue); |
| 150 | } |
| 151 | inputScalexWeight = inputScale; |
| 152 | } else { |
| 153 | const int kernelSize = size / icXoc; |
| 154 | const int ocStride = size / outputChannel; |
| 155 | |
| 156 | std::vector<float> weightMultiByInputScale(size); |
| 157 | for (int oc = 0; oc < outputChannel; ++oc) { |
| 158 | for (int ic = 0; ic < inputChannel; ++ic) { |
| 159 | for (int i = 0; i < kernelSize; ++i) { |
| 160 | const int index = oc * ocStride + ic * kernelSize + i; |
| 161 | weightMultiByInputScale[index] = inputScale * weight[index]; |
| 162 | } |
| 163 | } |
| 164 | } |
| 165 | if (method == "MAX_ABS"){ |
| 166 | SymmetricQuantizeWeight(weightMultiByInputScale.data(), size, quantizedWeight, quantizedWeightScale.data(), outputChannel, weightClampValue); |
| 167 | } |
| 168 | else if (method == "ADMM") { |
| 169 | QuantizeWeightADMM(weightMultiByInputScale.data(), size, quantizedWeight, quantizedWeightScale.data(), outputChannel, weightClampValue); |
| 170 | } |
| 171 | } |
| 172 | |
| 173 | for (int i = 0; i < outputChannel; ++i) { |
| 174 | if (fabs(outputScale) <= 1e-6) { |
| 175 | scale[i] = 0.0f; |
| 176 | } else { |
| 177 | scale[i] = inputScalexWeight * quantizedWeightScale[i] / outputScale; |
| 178 | } |
| 179 | } |
| 180 | |
| 181 | if (bias) { |
| 182 | for (int i = 0; i < outputChannel; ++i) { |
| 183 | if (fabs(inputScalexWeight) <= 1e-6 || fabs(quantizedWeightScale[i]) <= 1e-6) { |
| 184 | quantizedBias[i] = 0; |
| 185 | } else { |
| 186 | quantizedBias[i] = static_cast<int32_t>(bias[i] / (inputScalexWeight * quantizedWeightScale[i])); |
| 187 | } |
| 188 | } |
| 189 | } |
| 190 | |
| 191 | return 0; |
| 192 | } |
nothing calls this directly
no test coverage detected