diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_roi_align_node.cpp b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_roi_align_node.cpp index 045930139ad..bbd4d12ac5e 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_roi_align_node.cpp +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_roi_align_node.cpp @@ -25,11 +25,7 @@ using ngPoolingMode = ngraph::op::v3::ROIAlign::PoolingMode; bool MKLDNNROIAlignNode::isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept { try { - if (isDynamicNgraphNode(op)) { - errorMessage = "Doesn't support op with dynamic shapes"; - return false; - } - const auto roiAlign = std::dynamic_pointer_cast(op); + auto roiAlign = ngraph::as_type_ptr(op); if (!roiAlign) { errorMessage = "Only opset3 ROIAlign operation is supported"; return false; @@ -52,7 +48,7 @@ MKLDNNROIAlignNode::MKLDNNROIAlignNode(const std::shared_ptr& op, if (isSupportedOperation(op, errorMessage)) { errorPrefix = "ROIPooling layer with name '" + getName() + "' "; - const auto roiAlign = std::dynamic_pointer_cast(op); + auto roiAlign = ngraph::as_type_ptr(op); pooledH = roiAlign->get_pooled_h(); pooledW = roiAlign->get_pooled_w(); spatialScale = roiAlign->get_spatial_scale(); @@ -93,15 +89,15 @@ void MKLDNNROIAlignNode::getSupportedDescriptors() { IE_THROW() << errorPrefix << "doesn't support output with rank: " << getOutputShapeAtPort(0).getRank(); } - if (getInputShapeAtPort(1).getStaticDims()[1] != 4) { - IE_THROW() << errorPrefix << "has invalid shape on 1st input: [" - << getInputShapeAtPort(1).getStaticDims()[0] << "," << getInputShapeAtPort(1).getStaticDims()[1] << "]"; + const auto& proposalsDims = getInputShapeAtPort(1).getDims(); + if (proposalsDims[1] != 4) { + IE_THROW() << errorPrefix << "has invalid shape on 1st input: [" << proposalsDims[0] << "," << proposalsDims[1] << "]"; } - if (getInputShapeAtPort(1).getStaticDims()[0] != getInputShapeAtPort(2).getStaticDims()[0]) { + const auto& indexesDims = getInputShapeAtPort(2).getDims(); + if (!dimsEqualWeak(proposalsDims[0], indexesDims[0])) { IE_THROW() << errorPrefix << "has different sizes of inputs for proposals (" - << getInputShapeAtPort(1).getStaticDims()[0] << ") and indexes (" - << getInputShapeAtPort(2).getStaticDims()[0] << ")"; + << proposalsDims[0] << ") and indexes (" << indexesDims[0] << ")"; } } @@ -368,6 +364,18 @@ bool MKLDNNROIAlignNode::created() const { return getType() == ROIAlign; } -void MKLDNNROIAlignNode::createPrimitive() {} +bool MKLDNNROIAlignNode::needPrepareParams() const { + return false; +} + +void MKLDNNROIAlignNode::executeDynamicImpl(mkldnn::stream strm) { + return execute(strm); +} + +void MKLDNNROIAlignNode::createPrimitive() { + if (inputShapesDefined()) { + updateLastInputDims(); + } +} REG_MKLDNN_PRIM_FOR(MKLDNNROIAlignNode, ROIAlign) diff --git a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_roi_align_node.h b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_roi_align_node.h index 4e6b835c95f..31d470d4bca 100644 --- a/inference-engine/src/mkldnn_plugin/nodes/mkldnn_roi_align_node.h +++ b/inference-engine/src/mkldnn_plugin/nodes/mkldnn_roi_align_node.h @@ -23,6 +23,9 @@ public: void execute(mkldnn::stream strm) override; bool created() const override; + bool needPrepareParams() const override; + void executeDynamicImpl(mkldnn::stream strm) override; + static bool isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept; private: diff --git a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/roialign.cpp b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/roialign.cpp index 78a6fdcd0cb..cd7864c7fe8 100644 --- a/inference-engine/tests/functional/plugin/cpu/single_layer_tests/roialign.cpp +++ b/inference-engine/tests/functional/plugin/cpu/single_layer_tests/roialign.cpp @@ -3,70 +3,129 @@ // #include "test_utils/cpu_test_utils.hpp" +#include "functional_test_utils/ov_tensor_utils.hpp" +#include "shared_test_classes/base/ov_subgraph.hpp" #include "ngraph_functions/builders.hpp" #include "ngraph_functions/utils/ngraph_helpers.hpp" using namespace InferenceEngine; using namespace CPUTestUtils; +using namespace ov::test; namespace CPULayerTestsDefinitions { -namespace { - int pooledH; - int pooledW; - float spatialScale; - int samplingRatio; - std::pair, std::vector> proposal; - std::string mode; - std::vector inputShape; -} // namespace +using ROIAlignShapes = std::vector; -typedef std::tuple< +using ROIAlignSpecificParams = std::tuple< int, // bin's column count int, // bin's row count float, // scale for given region considering actual input size int, // pooling ratio - std::pair, std::vector>, // united proposal vector of coordinates and indexes std::string, // pooling mode - std::vector // feature map shape -> ROIAlignSpecificParams; + ROIAlignShapes +>; -typedef std::tuple< +using ROIAlignLayerTestParams = std::tuple< ROIAlignSpecificParams, - InferenceEngine::Precision, // Net precision + ElementType, // Net precision LayerTestsUtils::TargetDevice // Device name -> ROIAlignLayerTestParams; +>; -typedef std::tuple< +using ROIAlignLayerCPUTestParamsSet = std::tuple< CPULayerTestsDefinitions::ROIAlignLayerTestParams, - CPUSpecificParams> ROIAlignLayerCPUTestParamsSet; + CPUSpecificParams>; class ROIAlignLayerCPUTest : public testing::WithParamInterface, - virtual public LayerTestsUtils::LayerTestsCommon, public CPUTestsBase { + public SubgraphBaseTest, public CPUTestsBase { public: static std::string getTestCaseName(testing::TestParamInfo obj) { CPULayerTestsDefinitions::ROIAlignLayerTestParams basicParamsSet; CPUSpecificParams cpuParams; std::tie(basicParamsSet, cpuParams) = obj.param; std::string td; - Precision netPr; + ElementType netPrecision; ROIAlignSpecificParams roiPar; - std::tie(roiPar, netPr, td) = basicParamsSet; - std::tie(pooledH, pooledW, spatialScale, samplingRatio, - proposal, mode, inputShape) = roiPar; + std::tie(roiPar, netPrecision, td) = basicParamsSet; + + int pooledH; + int pooledW; + float spatialScale; + int samplingRatio; + std::string mode; + ROIAlignShapes inputShapes; + std::tie(pooledH, pooledW, spatialScale, samplingRatio, mode, inputShapes) = roiPar; std::ostringstream result; - result << "ROIAlignTest_"; - result << std::to_string(obj.index); + + result << netPrecision << "_IS="; + for (const auto& shape : inputShapes) { + result << CommonTestUtils::partialShape2str({ shape.first }) << "_"; + } + result << "TS="; + for (const auto& shape : inputShapes) { + result << "("; + for (const auto& targetShape : shape.second) { + result << CommonTestUtils::vec2str(targetShape) << "_"; + } + result << ")_"; + } + result << "pooledH=" << pooledH << "_"; result << "pooledW=" << pooledW << "_"; result << "spatialScale=" << spatialScale << "_"; result << "samplingRatio=" << samplingRatio << "_"; - result << (netPr == Precision::FP32 ? "FP32" : "BF16") << "_"; result << mode << "_"; result << CPUTestsBase::getTestCaseName(cpuParams); + return result.str(); } protected: + void generate_inputs(const std::vector& targetInputStaticShapes) override { + inputs.clear(); + const auto& funcInputs = function->inputs(); + + ov::runtime::Tensor data_tensor; + const auto& dataPrecision = funcInputs[0].get_element_type(); + const auto& dataShape = targetInputStaticShapes.front(); + data_tensor = ov::test::utils::create_and_fill_tensor(dataPrecision, dataShape, 10, 0, 1000); + + const auto& coordsET = funcInputs[1].get_element_type(); + auto coordsTensor = ov::runtime::Tensor{ coordsET, targetInputStaticShapes[1] }; + if (coordsET == ElementType::f32) { + auto coordsTensorData = static_cast(coordsTensor.data()); + for (size_t i = 0; i < coordsTensor.get_size(); i += 4) { + coordsTensorData[i] = 1.f; + coordsTensorData[i] = 1.f; + coordsTensorData[i] = 19.f; + coordsTensorData[i] = 19.f; + } + } else if (coordsET == ElementType::bf16) { + auto coordsTensorData = static_cast(coordsTensor.data()); + for (size_t i = 0; i < coordsTensor.get_size(); i += 4) { + coordsTensorData[i] = static_cast(ngraph::bfloat16(1.f).to_bits()); + coordsTensorData[i] = static_cast(ngraph::bfloat16(1.f).to_bits()); + coordsTensorData[i] = static_cast(ngraph::bfloat16(19.f).to_bits()); + coordsTensorData[i] = static_cast(ngraph::bfloat16(19.f).to_bits()); + } + } else { + IE_THROW() << "roi align. Unsupported precision: " << coordsET; + } + + auto roisIdxTensor = ov::runtime::Tensor{ funcInputs[2].get_element_type(), targetInputStaticShapes[2] }; + auto roisIdxTensorData = static_cast(roisIdxTensor.data()); + if (roisIdxTensor.get_size() == 1) { + roisIdxTensorData[0] = 1; + } else if (roisIdxTensor.get_size() == 2) { + roisIdxTensorData[0] = 0; + roisIdxTensorData[1] = 1; + } else { + IE_THROW() << "Unexpected roiIdx size: " << roisIdxTensor.get_size(); + } + + inputs.insert({ funcInputs[0].get_node_shared_ptr(), data_tensor }); + inputs.insert({ funcInputs[1].get_node_shared_ptr(), coordsTensor }); + inputs.insert({ funcInputs[2].get_node_shared_ptr(), roisIdxTensor }); + } + void SetUp() override { CPULayerTestsDefinitions::ROIAlignLayerTestParams basicParamsSet; CPUSpecificParams cpuParams; @@ -74,36 +133,38 @@ protected: std::tie(inFmts, outFmts, priority, selectedType) = cpuParams; CPULayerTestsDefinitions::ROIAlignSpecificParams roiAlignParams; - auto netPrecision = InferenceEngine::Precision::UNSPECIFIED; - std::tie(roiAlignParams, netPrecision, targetDevice) = basicParamsSet; - inPrc = outPrc = netPrecision; - std::tie(pooledH, pooledW, spatialScale, samplingRatio, - proposal, mode, inputShape) = roiAlignParams; + ElementType inputPrecision; + std::tie(roiAlignParams, inputPrecision, targetDevice) = basicParamsSet; - std::vector proposalVector = proposal.first; - std::vector roiIdxVector = proposal.second; + int pooledH; + int pooledW; + float spatialScale; + int samplingRatio; + std::string mode; + ROIAlignShapes inputShapes; + std::tie(pooledH, pooledW, spatialScale, samplingRatio, mode, inputShapes) = roiAlignParams; - ngraph::Shape coordsShape = { proposalVector.size() / 4, 4 }; - ngraph::Shape idxVectorShape = { roiIdxVector.size() }; + init_input_shapes(inputShapes); - auto roisIdx = ngraph::builder::makeConstant(ngraph::element::i32, idxVectorShape, roiIdxVector); - auto coords = ngraph::builder::makeConstant(ngraph::element::f32, coordsShape, proposalVector); - auto params = ngraph::builder::makeParams(ngraph::element::f32, {inputShape}); + auto float_params = ngraph::builder::makeDynamicParams(inputPrecision, { inputDynamicShapes[0], inputDynamicShapes[1] }); + auto int_params = ngraph::builder::makeDynamicParams(ngraph::element::i32, { inputDynamicShapes[2] }); - auto roialign = std::make_shared(params[0], coords, roisIdx, pooledH, pooledW, + auto roialign = std::make_shared(float_params[0], float_params[1], int_params[0], pooledH, pooledW, samplingRatio, spatialScale, mode); - roialign->get_rt_info() = getCPUInfo(); - selectedType = std::string("unknown_") + inPrc.name(); - threshold = 1e-2; - const ngraph::ResultVector results{std::make_shared(roialign)}; - function = std::make_shared(results, params, "ROIAlign"); + selectedType = makeSelectedTypeStr("unknown", inputPrecision); + if (inputPrecision == ElementType::bf16) { + rel_threshold = 1e-2; + } + + ngraph::ParameterVector params{ float_params[0], float_params[1], int_params[0] }; + function = makeNgraphFunction(inputPrecision, params, roialign, "ROIAlign"); } }; TEST_P(ROIAlignLayerCPUTest, CompareWithRefs) { SKIP_IF_CURRENT_TEST_IS_DISABLED() - Run(); + run(); CheckPluginRelatedResults(executableNetwork, "ROIAlign"); } @@ -122,9 +183,9 @@ std::vector filterCPUInfoForDevice() { return resCPUParams; } -const std::vector netPrecisions = { - InferenceEngine::Precision::FP32, - InferenceEngine::Precision::BF16 +const std::vector netPrecisions = { + ElementType::f32, + ElementType::bf16, }; const std::vector spatialBinXVector = { 2 }; @@ -140,17 +201,30 @@ const std::vector modeVector = { "max" }; -const std::vector> inputShapeVector = { - SizeVector({ 2, 18, 20, 20 }), - SizeVector({ 2, 4, 20, 20 }), - SizeVector({ 2, 4, 20, 40 }), - SizeVector({ 10, 1, 20, 20 }) -}; - - -const std::vector, std::vector>> propVector = { - {{ 1, 1, 19, 19, 1, 1, 19, 19, }, { 0, 1 }}, - {{ 1, 1, 19, 19 }, { 1 }} +const std::vector inputShapeVector = { + ROIAlignShapes{{{}, {{ 2, 18, 20, 20 }}}, {{}, {{2, 4}}}, {{}, {{2}}}}, + ROIAlignShapes{{{}, {{ 2, 4, 20, 20 }}}, {{}, {{2, 4}}}, {{}, {{2}}}}, + ROIAlignShapes{{{}, {{ 2, 4, 20, 40 }}}, {{}, {{2, 4}}}, {{}, {{2}}}}, + ROIAlignShapes{{{}, {{ 10, 1, 20, 20 }}}, {{}, {{2, 4}}}, {{}, {{2}}}}, + ROIAlignShapes{{{}, {{ 2, 18, 20, 20 }}}, {{}, {{1, 4}}}, {{}, {{1}}}}, + ROIAlignShapes{{{}, {{ 2, 4, 20, 20 }}}, {{}, {{1, 4}}}, {{}, {{1}}}}, + ROIAlignShapes{{{}, {{ 2, 4, 20, 40 }}}, {{}, {{1, 4}}}, {{}, {{1}}}}, + ROIAlignShapes{{{}, {{ 10, 1, 20, 20 }}}, {{}, {{1, 4}}}, {{}, {{1}}}}, + ROIAlignShapes{ + {{-1, -1, -1, -1}, {{ 10, 1, 20, 20 }, { 2, 4, 20, 20 }, { 2, 18, 20, 20 }}}, + {{-1, 4}, {{1, 4}, {2, 4}, {1, 4}}}, + {{-1}, {{1}, {2}, {1}}} + }, + ROIAlignShapes{ + {{{2, 10}, { 1, 5 }, -1, -1}, {{ 2, 1, 20, 20 }, { 10, 5, 30, 20 }, { 4, 4, 40, 40 }}}, + {{-1, 4}, {{2, 4}, {2, 4}, {1, 4}}}, + {{-1}, {{2}, {2}, {1}}} + }, + ROIAlignShapes{ + {{{2, 10}, {1, 18}, {10, 30}, {15, 25}}, {{ 10, 1, 10, 15 }, { 2, 4, 20, 20 }, { 7, 18, 30, 25 }}}, + {{{1, 2}, 4}, {{1, 4}, {2, 4}, {1, 4}}}, + {{{1, 2}}, {{1}, {2}, {1}}} + }, }; const auto roiAlignParams = ::testing::Combine( @@ -158,7 +232,6 @@ const auto roiAlignParams = ::testing::Combine( ::testing::ValuesIn(spatialBinYVector), // bin's row count ::testing::ValuesIn(spatialScaleVector), // scale for given region considering actual input size ::testing::ValuesIn(poolingRatioVector), // pooling ratio for bin - ::testing::ValuesIn(propVector), // united vector of coordinates and batch id's ::testing::ValuesIn(modeVector), // pooling mode ::testing::ValuesIn(inputShapeVector) // feature map shape );