diff --git a/inference-engine/src/gna_plugin/frontend/scale_factor_calc.hpp b/inference-engine/src/gna_plugin/frontend/scale_factor_calc.hpp index a986a4b60e2..8f905c89293 100644 --- a/inference-engine/src/gna_plugin/frontend/scale_factor_calc.hpp +++ b/inference-engine/src/gna_plugin/frontend/scale_factor_calc.hpp @@ -36,6 +36,17 @@ struct ScaleFactorUpdateResult { } }; +/** +* @brief Calculates a scale factor from FakeQuantize statistics according to the formula: +* scale factor = max representable value / max absolute input value +* @param levels Number of integer quants +* @param minValue Minimum value to be quantized +* @param maxValue Maximum value to be quantized +*/ +inline float CalculateScaleFactorFromStats(size_t levels, float minValue, float maxValue) { + return maxValue == minValue ? 1.0f : (levels - 1) / (maxValue - minValue); +} + /** * @brief Compares two float values and returns if they are equal * @param p1 First float value @@ -372,7 +383,7 @@ class ScaleFactorPerLayer { auto maxOutValue = quantizedParams->_dst_quant.GetMaxValues().front(); auto absMax = std::max(std::abs(minOutValue), std::abs(maxOutValue)); - result = (quantizedParams->_dst_quant.GetLevels() - 1) / (maxOutValue - minOutValue); + result = CalculateScaleFactorFromStats(quantizedParams->_dst_quant.GetLevels(), minOutValue, maxOutValue); if (std::isinf(result) || fp32eq(absMax, 0.0f)) { result = max_activation_scale_factor; } @@ -452,7 +463,7 @@ class ScaleFactorPerLayer { if (CNNNetHasPrevLayer(cnnLayer) && quant->_dst_quant.IsStatsSet() && !quant->_dst_quant.IsScaleSet()) { auto minOutValue = quant->_dst_quant.GetMinValues().front(); auto maxOutValue = quant->_dst_quant.GetMaxValues().front(); - auto scale = (quant->_dst_quant.GetLevels() - 1) / (maxOutValue - minOutValue); + auto scale = CalculateScaleFactorFromStats(quant->_dst_quant.GetLevels(), minOutValue, maxOutValue); quant->_dst_quant.SetScale(scale); quant->_src_quant = quant->_dst_quant; } @@ -1068,8 +1079,8 @@ class ScaleFactorPerLayer { quant->_src_quant = quantDataForInputLayer->_dst_quant; if (quant->_weights_quant.IsStatsSet() && !quant->_weights_quant.IsScaleSet()) { auto getScale = [&quant](size_t i) { - auto valuesDiff = quant->_weights_quant.GetMaxValues(false)[i] - quant->_weights_quant.GetMinValues(false)[i]; - return valuesDiff == 0 ? 1.0f : (quant->_weights_quant.GetLevels() - 1) / valuesDiff; + return CalculateScaleFactorFromStats(quant->_weights_quant.GetLevels(), + quant->_weights_quant.GetMinValues(false)[i], quant->_weights_quant.GetMaxValues(false)[i]); }; float min_channel_scale = getScale(0); @@ -1222,9 +1233,8 @@ public: quantData->_weights_quant.SetScale(quantParams1->_dst_quant.GetScale()); if (quantData->_src_quant.IsStatsSet()) { auto getScale = [&quantParams0](size_t i) { - return (quantParams0->_dst_quant.GetLevels() - 1) / - (quantParams0->_dst_quant.GetMaxValues(false)[i] - - quantParams0->_dst_quant.GetMinValues(false)[i]); + return CalculateScaleFactorFromStats(quantParams0->_dst_quant.GetLevels(), + quantParams0->_dst_quant.GetMinValues(false)[i], quantParams0->_dst_quant.GetMaxValues(false)[i]); }; float min_channel_scale = getScale(0); quantParams0->_dst_quant.SetScale(min_channel_scale); diff --git a/inference-engine/src/gna_plugin/gna_plugin.cpp b/inference-engine/src/gna_plugin/gna_plugin.cpp index bc566df0f09..2f257ba4fb0 100644 --- a/inference-engine/src/gna_plugin/gna_plugin.cpp +++ b/inference-engine/src/gna_plugin/gna_plugin.cpp @@ -489,13 +489,9 @@ void GNAPlugin::UpdateInputScaleFromNetwork(InferenceEngine::CNNNetwork & networ return (std::abs(p1 - p2) <= 0.00001f * std::min(std::abs(p1), std::abs(p2))); }; // GNA input is always quantized to int16, so number of levels can't be greater than max uint16 - size_t levels = std::min(fqLayer.getLevels(), static_cast(std::numeric_limits::max())); - float scaleInput = (levels - 1) / (inputRange.second[0] - inputRange.first[0]); - auto minAbsVal = std::min(std::abs(inputRange.second[0]), std::abs(inputRange.first[0])); - auto maxAbsVal = std::max(std::abs(inputRange.second[0]), std::abs(inputRange.first[0])); - if (fp32eq(minAbsVal, 0.0f) && !fp32eq(maxAbsVal, 0.0f)) { - scaleInput = (fqLayer.getLevels() - 1) / (2 * maxAbsVal); - } + // todo: should be solved in POT (issue 63330) + size_t levels = std::min(fqLayer.getLevels(), static_cast(std::numeric_limits::max() + 1)); + auto scaleInput = frontend::CalculateScaleFactorFromStats(levels, inputRange.first[0], inputRange.second[0]); IE_ASSERT(config.inputScaleFactors.size() > inputIdx); IE_ASSERT(inputsDesc->inputScaleFactors.size() > inputIdx); diff --git a/inference-engine/tests/functional/plugin/gna/pass_tests/fq_maxpool_reordering.cpp b/inference-engine/tests/functional/plugin/gna/pass_tests/fq_maxpool_reordering.cpp index 948ec611720..af6d0c1a19b 100644 --- a/inference-engine/tests/functional/plugin/gna/pass_tests/fq_maxpool_reordering.cpp +++ b/inference-engine/tests/functional/plugin/gna/pass_tests/fq_maxpool_reordering.cpp @@ -73,8 +73,9 @@ protected: std::tie(netPrecision, targetDevice, configuration, inputShape, inputMinMax, levels) = this->GetParam(); auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); - auto inputLowNode = ngraph::builder::makeConstant(ngPrc, {1}, { inputMinMax.first }); - auto inputHighNode = ngraph::builder::makeConstant(ngPrc, {1}, { inputMinMax.second }); + std::tie(inputDataMin, inputDataMax) = inputMinMax; + auto inputLowNode = ngraph::builder::makeConstant(ngPrc, {1}, { inputDataMin }); + auto inputHighNode = ngraph::builder::makeConstant(ngPrc, {1}, { inputDataMax }); auto inputVector = ngraph::builder::makeParams(ngPrc, {inputShape});