diff --git a/inference-engine/src/gna_plugin/gna_plugin.cpp b/inference-engine/src/gna_plugin/gna_plugin.cpp index 8336095798a07f..77fb999d45f195 100644 --- a/inference-engine/src/gna_plugin/gna_plugin.cpp +++ b/inference-engine/src/gna_plugin/gna_plugin.cpp @@ -766,6 +766,7 @@ void GNAPlugin::LoadNetwork(CNNNetwork & _network) { passes->registerPass(); passes->registerPass(); passes->registerPass(); + passes->registerPass(); passes->registerPass(); passes->registerPass(); #if GNA_LIB_VER == 2 @@ -773,7 +774,6 @@ void GNAPlugin::LoadNetwork(CNNNetwork & _network) { #endif passes->registerPass(); passes->registerPass(); - passes->registerPass(); passIdx = passes->run(passIdx); }; diff --git a/inference-engine/src/gna_plugin/optimizer/gna_pass_manager.cpp b/inference-engine/src/gna_plugin/optimizer/gna_pass_manager.cpp index a0a49b8ab05a90..8c8ad61254a5f2 100644 --- a/inference-engine/src/gna_plugin/optimizer/gna_pass_manager.cpp +++ b/inference-engine/src/gna_plugin/optimizer/gna_pass_manager.cpp @@ -1609,46 +1609,53 @@ void SubstituteScaleShiftBroadCastPass::run() { } void BroadcastConstPass::run() { - for (auto& constLayer : *pLayers) { + for (auto constLayer : *pLayers) { if (!LayerInfo(constLayer).isConst()) { continue; } - auto isNonFunctional = [](CNNLayerPtr l) { - return LayerInfo(l).isNonFunctional(); + + auto isNonFunctional = [](CNNLayerPtr layer) { + return LayerInfo(layer).isNonFunctional(); }; - if (!CNNNetHasNextLayerSkipCertain(constLayer, 0, 0, isNonFunctional)) { + + auto nextLayer = CNNNetCheckNextLayerSkipCertain(constLayer, 0, 0, true, isNonFunctional).first; + if (!nextLayer || !LayerInfo(nextLayer).isEltwise() && !LayerInfo(nextLayer).isFakeQuantize()) { continue; } - auto nextLayer = CNNNetGetNextLayerSkipCertain(constLayer, 0, 0, isNonFunctional).first; + auto prevLayer = nextLayer; + if (LayerInfo(nextLayer).isFakeQuantize()) { + if (CNNNetPrevLayer(nextLayer, 0) != constLayer) { + continue; + } - if (!LayerInfo(nextLayer).isEltwise()) { - continue; + nextLayer = CNNNetCheckNextLayerSkipCertain(nextLayer, 0, 0, true, isNonFunctional).first; + if (!nextLayer || !LayerInfo(nextLayer).isEltwise()) { + continue; + } } auto constDims = constLayer->outData.front()->getTensorDesc().getDims(); auto constDimsSize = product(constDims.begin(), constDims.end()); auto eltwiseDims = nextLayer->outData.front()->getTensorDesc().getDims(); auto eltwiseDimsSize = product(eltwiseDims.begin(), eltwiseDims.end()); - - if (constDimsSize == eltwiseDimsSize) { - continue; - } - - if (eltwiseDimsSize % constDimsSize) { + if (constDimsSize == eltwiseDimsSize || eltwiseDimsSize % constDimsSize) { continue; } - if (constLayer->blobs.find("custom") == constLayer->blobs.end()) { + auto blobsIter = constLayer->blobs.find("custom"); + if (blobsIter == constLayer->blobs.end()) { THROW_GNA_LAYER_EXCEPTION(constLayer) << "Const layer " << constLayer->name << " is missing 'custom' parameter"; } - auto currentConstBlob = constLayer->blobs.find("custom")->second; - - constLayer->blobs.find("custom")->second = tileBlob(currentConstBlob, eltwiseDimsSize); - + auto currentConstBlob = blobsIter->second; + blobsIter->second = tileBlob(currentConstBlob, eltwiseDimsSize); constLayer->outData.front()->setDims(nextLayer->outData.front()->getDims()); constLayer->outData.front()->setLayout(nextLayer->outData.front()->getLayout()); + if (prevLayer != nextLayer) { + prevLayer->outData.front()->setDims(nextLayer->outData.front()->getDims()); + prevLayer->outData.front()->setLayout(nextLayer->outData.front()->getLayout()); + } gnalog() << "Const layer '" << constLayer->name << "' was changed to match output of '" << nextLayer->name << "'\n"; } } diff --git a/inference-engine/tests/functional/plugin/gna/pass_tests/broadcast_const_with_fq.cpp b/inference-engine/tests/functional/plugin/gna/pass_tests/broadcast_const_with_fq.cpp new file mode 100644 index 00000000000000..7c5f24cf3e84e9 --- /dev/null +++ b/inference-engine/tests/functional/plugin/gna/pass_tests/broadcast_const_with_fq.cpp @@ -0,0 +1,92 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// +// +#include +#include +#include + +#include + +#include "common_test_utils/common_utils.hpp" +#include "functional_test_utils/plugin_cache.hpp" +#include "shared_test_classes/base/layer_test_utils.hpp" +#include "functional_test_utils/blob_utils.hpp" +#include "ngraph_functions/utils/ngraph_helpers.hpp" +#include "ngraph_functions/builders.hpp" +#include "ngraph_functions/pass/convert_prc.hpp" + +using BroadcastConstWithFqParamsTuple = typename std::tuple< + InferenceEngine::Precision, // Network Precision + std::vector, // Input shapes for Params Layer + std::vector, // Input shapes for Constant Layer + size_t, // Quantization level + std::map, // Configuration + std::string>; // Device name + +namespace LayerTestsDefinitions { + +class BroadcastConstWithFq : public testing::WithParamInterface, + public LayerTestsUtils::LayerTestsCommon { +public: + static std::string getTestCaseName(testing::TestParamInfo obj) { + InferenceEngine::Precision netPrecision; + std::vector inputShape1; + std::vector inputShape2; + size_t level{0}; + std::map configuration; + std::string targetDevice; + std::tie(netPrecision, inputShape1, inputShape2, level, configuration, targetDevice) = obj.param; + std::ostringstream result; + result << "netPRC=" << netPrecision.name() << "_"; + result << "targetDevice=" << targetDevice << "_"; + for (auto const& configItem : configuration) { + result << "configItem=" << configItem.first << "_" << configItem.second << "_"; + } + result << "inputShape1=" << CommonTestUtils::vec2str(inputShape1) << "_"; + result << "inputShape2=" << CommonTestUtils::vec2str(inputShape2) << "_"; + result << "level=" << level; + return result.str(); + } + +protected: + void SetUp() override { + size_t level{0}; + InferenceEngine::Precision netPrecision; + std::vector inputShape1; + std::vector inputShape2; + std::tie(netPrecision, inputShape1, inputShape2, level, configuration, targetDevice) = this->GetParam(); + auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); + auto params = ngraph::builder::makeParams(ngPrc, {inputShape1}); + auto fakeQuantize1 = ngraph::builder::makeFakeQuantize(params[0], ngPrc, level, {}, {-0.5}, {0.5}, {-0.5}, {0.5}); + auto constant = ngraph::builder::makeConstant(ngPrc, inputShape2, {}, true); + auto fakeQuantize2 = ngraph::builder::makeFakeQuantize(constant, ngPrc, level, {}, {-0.5}, {0.5}, {-0.5}, {0.5}); + auto add = std::make_shared(fakeQuantize1, fakeQuantize2); + ngraph::ResultVector results{ std::make_shared(add)}; + function = std::make_shared(results, params, "BroadcastConstWithFq"); + } +}; + +TEST_P(BroadcastConstWithFq, CompareWithRefImpl) { + Run(); +}; + +std::vector> inputShapes1 = { {1, 1, 21, 160} }; +std::vector> inputShapes2 = { {1, 1, 1, 160} }; +const std::vector level = { 65535 }; +const std::vector netPrecisions = {InferenceEngine::Precision::FP32, InferenceEngine::Precision::FP16}; +const std::vector> configs = { + { {"GNA_DEVICE_MODE", "GNA_SW_FP32"} }, + { {"GNA_DEVICE_MODE", "GNA_SW_EXACT"} } +}; + +INSTANTIATE_TEST_CASE_P(smoke_broadcast_const_with_fq, BroadcastConstWithFq, + ::testing::Combine( + ::testing::ValuesIn(netPrecisions), + ::testing::ValuesIn(inputShapes1), + ::testing::ValuesIn(inputShapes2), + ::testing::ValuesIn(level), + ::testing::ValuesIn(configs), + ::testing::Values(CommonTestUtils::DEVICE_GNA)), + BroadcastConstWithFq::getTestCaseName); +} // namespace LayerTestsDefinitions