diff --git a/inference-engine/cmake/vpu_dependencies.cmake b/inference-engine/cmake/vpu_dependencies.cmake index f8d21c034be..626a819112d 100644 --- a/inference-engine/cmake/vpu_dependencies.cmake +++ b/inference-engine/cmake/vpu_dependencies.cmake @@ -19,7 +19,7 @@ set(VPU_SUPPORTED_FIRMWARES usb-ma2450 usb-ma2x8x pcie-ma248x) # Default packages # -set(FIRMWARE_PACKAGE_VERSION 1219) +set(FIRMWARE_PACKAGE_VERSION 1237) set(VPU_CLC_MA2X8X_VERSION "movi-cltools-20.02.0") # diff --git a/inference-engine/src/vpu/graph_transformer/include/vpu/model/stage.hpp b/inference-engine/src/vpu/graph_transformer/include/vpu/model/stage.hpp index 76b5aa07f38..1f434d01f11 100644 --- a/inference-engine/src/vpu/graph_transformer/include/vpu/model/stage.hpp +++ b/inference-engine/src/vpu/graph_transformer/include/vpu/model/stage.hpp @@ -104,7 +104,6 @@ VPU_DECLARE_ENUM(StageType, HwFcRelayout = 56, Clamp = 57, RefConvolution = 58, - GlobalAvgPool = 59, GlobalMaxPool = 60, GRN = 61, MVN = 62, diff --git a/inference-engine/src/vpu/graph_transformer/src/middleend/pass_manager.cpp b/inference-engine/src/vpu/graph_transformer/src/middleend/pass_manager.cpp index 3d05bbc8179..c279c980b1f 100644 --- a/inference-engine/src/vpu/graph_transformer/src/middleend/pass_manager.cpp +++ b/inference-engine/src/vpu/graph_transformer/src/middleend/pass_manager.cpp @@ -93,16 +93,6 @@ PassSet::Ptr PassManager::buildMiddleEnd() { ADD_PASS(convertShapeNotation); ADD_DUMP_PASS("convertShapeNotation"); - // - // Replace Global AvgPooling with ReduceMean - // - - if (env.config.enableReplaceWithReduceMean) { - ADD_PASS(replaceWithReduceMean); - ADD_DUMP_PASS("replaceWithReduceMean"); - } - - if (!env.config.disableReorder && !env.config.hwOptimization) { ADD_PASS(reorderInputsToChannelMinor); ADD_DUMP_PASS("reorderInputsToChannelMinor"); @@ -241,7 +231,18 @@ PassSet::Ptr PassManager::buildMiddleEnd() { ADD_PASS(swConvAdaptation); ADD_PASS(swDeconvAdaptation); + + // + // Replace Global AvgPooling with ReduceMean + // + // this stage should be executed after "hwPoolTiling" + // and before "swPoolAdaptation" + if (env.config.enableReplaceWithReduceMean) { + ADD_PASS(replaceWithReduceMean); + ADD_DUMP_PASS("replaceWithReduceMean"); + } ADD_PASS(swPoolAdaptation); + ADD_PASS(swFullyConnectedAdaptation); ADD_DUMP_PASS("swAdaptation"); diff --git a/inference-engine/src/vpu/graph_transformer/src/middleend/passes/replace_with_reduce_mean.cpp b/inference-engine/src/vpu/graph_transformer/src/middleend/passes/replace_with_reduce_mean.cpp index 675fad4babd..9e796256d63 100644 --- a/inference-engine/src/vpu/graph_transformer/src/middleend/passes/replace_with_reduce_mean.cpp +++ b/inference-engine/src/vpu/graph_transformer/src/middleend/passes/replace_with_reduce_mean.cpp @@ -36,39 +36,39 @@ void PassImpl::run(const Model& model) { continue; } - auto stageInput = stage->input(0); - const auto& dimValues = stageInput->desc().dims(); + const auto stageInput = stage->input(0); + const auto stageOutput = stage->output(0); const auto kernelSizeX = stage->attrs().get("kernelSizeX"); const auto kernelSizeY = stage->attrs().get("kernelSizeY"); + const bool excludePad = stage->attrs().get("excludePad"); - const auto kernelStrideX = stage->attrs().get("kernelStrideX"); - const auto kernelStrideY = stage->attrs().get("kernelStrideY"); + const auto padLeft = stage->attrs().get("padLeft"); + const auto padRight = stage->attrs().get("padRight"); + const auto padTop = stage->attrs().get("padTop"); + const auto padBottom = stage->attrs().get("padBottom"); VPU_THROW_UNLESS( kernelSizeX > 0 && kernelSizeY > 0, "[ReplaceWithReduceMean] Stage %v with type AvgPool has non-positive kernel size", stage->name()); - if (dimValues[Dim::W] == kernelSizeX && dimValues[Dim::H] == kernelSizeY) { // GlobalPooling - if (kernelStrideX != 1 && kernelStrideY != 1) { - continue; - } - - // TODO: since ReduceMean currently is not fully optimized, we need to discard some common cases - if (kernelSizeX * kernelSizeY < 2050) { - continue; - } + const bool isOverlapByX = kernelSizeX - padLeft >= stageInput->desc().dim(Dim::W); + const bool isOverlapByY = kernelSizeY - padTop >= stageInput->desc().dim(Dim::H); + const bool isOverlapByKernel = isOverlapByX && isOverlapByY; + const bool paddingsNotExist = padLeft == 0 && padRight == 0 && padTop == 0 && padBottom == 0; + const bool isGlobalPoolingOutputFormat = stageOutput->desc().dim(Dim::W) == 1 && stageOutput->desc().dim(Dim::H) == 1; + const bool isGlobalAvgPooling = (isGlobalPoolingOutputFormat && (isOverlapByKernel && (paddingsNotExist || excludePad))); + if (isGlobalAvgPooling) { auto origLayer = stage->origLayer(); - auto stageOutput = stage->output(0); model->removeStage(stage); const auto generator = [&stageInput](const ie::Blob::Ptr& blob) { auto buffer = blob->buffer().as(); - auto numInputDims = stageInput->desc().numDims(); + // H and W are always come last in IE notation buffer[0] = numInputDims - 1; buffer[1] = numInputDims - 2; diff --git a/inference-engine/src/vpu/graph_transformer/src/middleend/passes/sw_pooling_adaptation.cpp b/inference-engine/src/vpu/graph_transformer/src/middleend/passes/sw_pooling_adaptation.cpp index bc4ecbecf82..c75bd71e8bc 100644 --- a/inference-engine/src/vpu/graph_transformer/src/middleend/passes/sw_pooling_adaptation.cpp +++ b/inference-engine/src/vpu/graph_transformer/src/middleend/passes/sw_pooling_adaptation.cpp @@ -116,9 +116,7 @@ void PassImpl::run(const Model& model) { const bool isOverlapByX = kernelSizeX - padLeft >= input->desc().dim(Dim::W); const bool isOverlapByY = kernelSizeY - padTop >= input->desc().dim(Dim::H); const bool isOverlapByKernel = isOverlapByX && isOverlapByY; - const bool paddingsNotExist = padLeft == 0 && padRight == 0 && padTop == 0 && padBottom == 0; - const bool isGlobalPoolingOutputFormat = - output->desc().dim(Dim::W) == 1 && output->desc().dim(Dim::H) == 1; + const bool isGlobalPoolingOutputFormat = output->desc().dim(Dim::W) == 1 && output->desc().dim(Dim::H) == 1; auto stageType = StageType::None; if (stage->type() == StageType::StubMaxPool) { if (isGlobalPoolingOutputFormat && isOverlapByKernel) { @@ -127,11 +125,7 @@ void PassImpl::run(const Model& model) { stageType = StageType::MaxPool; } } else { - if (isGlobalPoolingOutputFormat && (isOverlapByKernel && (paddingsNotExist || excludePad))) { - stageType = StageType::GlobalAvgPool; - } else { - stageType = StageType::AvgPool; - } + stageType = StageType::AvgPool; } auto swStage = model->addNewStage( diff --git a/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/single_layer_tests/pooling.cpp b/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/single_layer_tests/pooling.cpp index 9f0e4877d32..474b63b6c9e 100644 --- a/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/single_layer_tests/pooling.cpp +++ b/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/single_layer_tests/pooling.cpp @@ -142,4 +142,27 @@ INSTANTIATE_TEST_CASE_P(MAX_and_AVGPool_ValidPad, PoolingLayerTest, ::testing::Values(CommonTestUtils::DEVICE_MYRIAD)), PoolingLayerTest::getTestCaseName ); -} // namespace \ No newline at end of file + +////* ========== Global Avg Pooling ========== */ +const std::vector> global_pool_kernels = {{3, 3}, {5, 5}, {7, 7}, {30, 30}, {100, 100}, {300, 300}}; +const auto avgGlobalPoolParams = ::testing::Combine( + ::testing::Values(PoolingTypes::AVG), + ::testing::ValuesIn(global_pool_kernels), + ::testing::Values(std::vector({1, 1})), + ::testing::Values(std::vector({0, 0})), + ::testing::Values(std::vector({0, 0})), + ::testing::Values(ngraph::op::RoundingType::CEIL), + ::testing::Values(ngraph::op::PadType::EXPLICIT), + ::testing::Values(false) +); + +INSTANTIATE_TEST_CASE_P(GlobalAvgPool, GlobalPoolingLayerTest, + ::testing::Combine( + avgGlobalPoolParams, + ::testing::ValuesIn(netPrecisions), + ::testing::Values(3, 101), + ::testing::Values(CommonTestUtils::DEVICE_MYRIAD)), + GlobalPoolingLayerTest::getTestCaseName +); + +} // namespace diff --git a/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/pooling.hpp b/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/pooling.hpp index d9c3bc5ec6d..8c7edc0f602 100644 --- a/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/pooling.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/pooling.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2019 Intel Corporation +// Copyright (C) 2019-2020 Intel Corporation // // SPDX-License-Identifier: Apache-2.0 // @@ -34,6 +34,13 @@ typedef std::tuple< std::string // Device name > poolLayerTestParamsSet; +typedef std::tuple< + poolSpecificParams, + InferenceEngine::Precision, // Net precision + size_t, // Channel number + std::string // Device name +> globalPoolLayerTestParamsSet; + class PoolingLayerTest : public testing::WithParamInterface, public LayerTestsUtils::LayerTestsCommon { public: @@ -43,4 +50,13 @@ protected: void SetUp() override; }; -} // namespace LayerTestsDefinitions \ No newline at end of file +class GlobalPoolingLayerTest : public testing::WithParamInterface, + public LayerTestsUtils::LayerTestsCommon { +public: + static std::string getTestCaseName(testing::TestParamInfo obj); + +protected: + void SetUp() override; +}; + +} // namespace LayerTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/shared/src/single_layer_tests/pooling.cpp b/inference-engine/tests/functional/plugin/shared/src/single_layer_tests/pooling.cpp index 078efe89318..2e2f6fc94b7 100644 --- a/inference-engine/tests/functional/plugin/shared/src/single_layer_tests/pooling.cpp +++ b/inference-engine/tests/functional/plugin/shared/src/single_layer_tests/pooling.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2019 Intel Corporation +// Copyright (C) 2019-2020 Intel Corporation // // SPDX-License-Identifier: Apache-2.0 // @@ -25,7 +25,7 @@ namespace LayerTestsDefinitions { std::string PoolingLayerTest::getTestCaseName(testing::TestParamInfo obj) { poolSpecificParams poolParams; InferenceEngine::Precision netPrecision; - std::vector inputShapes, newInputShapes; + std::vector inputShapes; std::string targetDevice; std::tie(poolParams, netPrecision, inputShapes, targetDevice) = obj.param; ngraph::helpers::PoolingTypes poolType; @@ -60,6 +60,46 @@ std::string PoolingLayerTest::getTestCaseName(testing::TestParamInfo obj) { + poolSpecificParams poolParams; + InferenceEngine::Precision netPrecision; + std::string targetDevice; + size_t channels; + std::tie(poolParams, netPrecision, channels, targetDevice) = obj.param; + ngraph::helpers::PoolingTypes poolType; + std::vector kernel, stride; + std::vector padBegin, padEnd; + ngraph::op::PadType padType; + ngraph::op::RoundingType roundingType; + bool excludePad; + std::tie(poolType, kernel, stride, padBegin, padEnd, roundingType, padType, excludePad) = poolParams; + + std::vector inputShapes = {1, channels, kernel[0], kernel[1]}; + + std::ostringstream result; + result << "IS=" << CommonTestUtils::vec2str(inputShapes) << "_"; + switch (poolType) { + case ngraph::helpers::PoolingTypes::MAX: + result << "MaxPool_"; + break; + case ngraph::helpers::PoolingTypes::AVG: + result << "AvgPool_"; + result << "ExcludePad=" << excludePad << "_"; + break; + } + result << "K" << CommonTestUtils::vec2str(kernel) << "_"; + result << "S" << CommonTestUtils::vec2str(stride) << "_"; + result << "PB" << CommonTestUtils::vec2str(padBegin) << "_"; + result << "PE" << CommonTestUtils::vec2str(padEnd) << "_"; + if (padType == ngraph::op::PadType::EXPLICIT) { + result << "Rounding=" << roundingType << "_"; + } + result << "AutoPad=" << padType << "_"; + result << "netPRC=" << netPrecision.name() << "_"; + result << "targetDevice=" << targetDevice; + return result.str(); +} + void PoolingLayerTest::SetUp() { poolSpecificParams poolParams; std::vector inputShape; @@ -77,25 +117,64 @@ void PoolingLayerTest::SetUp() { auto params = ngraph::builder::makeParams(ngPrc, {inputShape}); auto paramOuts = ngraph::helpers::convert2OutputVector( ngraph::helpers::castOps2Nodes(params)); - std::shared_ptr pooling; - switch (poolType) { - case ngraph::helpers::PoolingTypes::MAX: - pooling = std::make_shared(paramOuts[0], stride, padBegin, padEnd, kernel, - roundingType, - padType); - break; - case ngraph::helpers::PoolingTypes::AVG: - pooling = std::make_shared(paramOuts[0], stride, padBegin, padEnd, kernel, - excludePad, - roundingType, padType); - break; - } - ngraph::ResultVector results{std::make_shared(pooling)}; + std::shared_ptr pooling = ngraph::builder::makePooling(paramOuts[0], + stride, + padBegin, + padEnd, + kernel, + roundingType, + padType, + excludePad, + poolType); + + ngraph::ResultVector results{std::make_shared(pooling)}; + function = std::make_shared(results, params, "pooling"); +} + +void GlobalPoolingLayerTest::SetUp() { + poolSpecificParams poolParams; + InferenceEngine::Precision netPrecision; + size_t channels; + std::tie(poolParams, netPrecision, channels, targetDevice) = this->GetParam(); + ngraph::helpers::PoolingTypes poolType; + std::vector kernel, stride; + std::vector padBegin, padEnd; + ngraph::op::PadType padType; + ngraph::op::RoundingType roundingType; + bool excludePad; + std::tie(poolType, kernel, stride, padBegin, padEnd, roundingType, padType, excludePad) = poolParams; + + std::vector inputShape = {1, channels, kernel[1], kernel[0]}; + + auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); + auto params = ngraph::builder::makeParams(ngPrc, {inputShape}); + auto paramOuts = ngraph::helpers::convert2OutputVector( + ngraph::helpers::castOps2Nodes(params)); + + std::shared_ptr pooling = ngraph::builder::makePooling(paramOuts[0], + stride, + padBegin, + padEnd, + kernel, + roundingType, + padType, + excludePad, + poolType); + + ngraph::ResultVector results{std::make_shared(pooling)}; function = std::make_shared(results, params, "pooling"); } TEST_P(PoolingLayerTest, CompareWithRefs) { Run(); } -} // namespace LayerTestsDefinitions \ No newline at end of file + +TEST_P(GlobalPoolingLayerTest, CompareWithRefs) { + Run(); + + if (targetDevice == std::string{CommonTestUtils::DEVICE_GPU}) { + PluginCache::get().reset(); + } +} +} // namespace LayerTestsDefinitions diff --git a/inference-engine/tests/ngraph_functions/include/ngraph_functions/builders.hpp b/inference-engine/tests/ngraph_functions/include/ngraph_functions/builders.hpp index 83feb3499ad..1e121a5db0f 100644 --- a/inference-engine/tests/ngraph_functions/include/ngraph_functions/builders.hpp +++ b/inference-engine/tests/ngraph_functions/include/ngraph_functions/builders.hpp @@ -249,5 +249,15 @@ std::shared_ptr makeReduce(std::vector> &in, bool keepDims, ngraph::helpers::ReductionType reductionType); +std::shared_ptr makePooling(const ngraph::Output &in, + const std::vector &strides, + const std::vector &padsBegin, + const std::vector &padsEnd, + const std::vector &kernel, + const op::RoundingType &roundingType, + const op::PadType &padType, + bool excludePad, + const ngraph::helpers::PoolingTypes &poolType); + } // namespace builder } // namespace ngraph diff --git a/inference-engine/tests/ngraph_functions/src/pooling.cpp b/inference-engine/tests/ngraph_functions/src/pooling.cpp new file mode 100644 index 00000000000..c79b85dfe4a --- /dev/null +++ b/inference-engine/tests/ngraph_functions/src/pooling.cpp @@ -0,0 +1,40 @@ +// Copyright (C) 2020 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// +// + +#include +#include + +#include "ngraph_functions/builders.hpp" + +namespace ngraph { +namespace builder { + +std::shared_ptr makePooling(const ngraph::Output &in, + const std::vector &strides, + const std::vector &padsBegin, + const std::vector &padsEnd, + const std::vector &kernel, + const op::RoundingType &roundingType, + const op::PadType &padType, + bool excludePad, + const ngraph::helpers::PoolingTypes &poolType) { + std::shared_ptr pooling; + switch (poolType) { + case ngraph::helpers::PoolingTypes::MAX: + pooling = std::make_shared(in, strides, padsBegin, padsEnd, kernel, roundingType, + padType); + + break; + case ngraph::helpers::PoolingTypes::AVG: + pooling = std::make_shared(in, strides, padsBegin, padsEnd, kernel, + excludePad, + roundingType, padType); + break; + } + return pooling; +} + +} // namespace builder +} // namespace ngraph