From 0f2a4b18243d1d3f6b1dca715285332c28aaff35 Mon Sep 17 00:00:00 2001 From: Andrew Bakalin Date: Wed, 14 Oct 2020 11:02:21 +0300 Subject: [PATCH] [IE][VPU]: Support DTS for Split (#2576) * [IE Tests] Remove unnecessary cout * [VPU] Add DTS for split * [VPU][Tests] Add tests --- .../dynamic_to_static_shape_split.hpp | 13 +++ .../transformations/dynamic_to_static_shape.cpp | 3 + .../dynamic_to_static_shape_split.cpp | 64 +++++++++++ .../dynamic_to_static_shape_split.cpp | 126 +++++++++++++++++++++ .../plugin/myriad/subgraph_tests/dsr_split.cpp | 61 ++++++++++ .../functional_test_utils/layer_test_utils.hpp | 1 - 6 files changed, 267 insertions(+), 1 deletion(-) create mode 100644 inference-engine/src/vpu/common/include/vpu/ngraph/transformations/dynamic_to_static_shape_split.hpp create mode 100644 inference-engine/src/vpu/common/src/ngraph/transformations/dynamic_to_static_shape_split.cpp create mode 100644 inference-engine/tests/functional/plugin/myriad/ngraph/transformations/dynamic_to_static_shape_split.cpp create mode 100644 inference-engine/tests/functional/plugin/myriad/subgraph_tests/dsr_split.cpp diff --git a/inference-engine/src/vpu/common/include/vpu/ngraph/transformations/dynamic_to_static_shape_split.hpp b/inference-engine/src/vpu/common/include/vpu/ngraph/transformations/dynamic_to_static_shape_split.hpp new file mode 100644 index 0000000..54e6c57 --- /dev/null +++ b/inference-engine/src/vpu/common/include/vpu/ngraph/transformations/dynamic_to_static_shape_split.hpp @@ -0,0 +1,13 @@ +// Copyright (C) 2020 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include "ngraph/node.hpp" + +namespace vpu { + +void dynamicToStaticShapeSplit(std::shared_ptr target); + +} // namespace vpu diff --git a/inference-engine/src/vpu/common/src/ngraph/transformations/dynamic_to_static_shape.cpp b/inference-engine/src/vpu/common/src/ngraph/transformations/dynamic_to_static_shape.cpp index 1241838..9dbdc4a 100644 --- a/inference-engine/src/vpu/common/src/ngraph/transformations/dynamic_to_static_shape.cpp +++ b/inference-engine/src/vpu/common/src/ngraph/transformations/dynamic_to_static_shape.cpp @@ -14,6 +14,7 @@ #include "vpu/ngraph/transformations/dynamic_to_static_shape_reduce.hpp" #include "vpu/ngraph/transformations/dynamic_to_static_shape_reshape.hpp" #include "vpu/ngraph/transformations/dynamic_to_static_shape_roialign.hpp" +#include "vpu/ngraph/transformations/dynamic_to_static_shape_split.hpp" #include "vpu/ngraph/transformations/dynamic_to_static_shape_squeeze.hpp" #include "vpu/ngraph/transformations/dynamic_to_static_shape_strided_slice.hpp" #include "vpu/ngraph/transformations/dynamic_to_static_shape_topk.hpp" @@ -26,6 +27,7 @@ #include "vpu/utils/error.hpp" #include "ngraph/opsets/opset3.hpp" +#include "ngraph/opsets/opset5.hpp" #include "vpu/ngraph/operations/dynamic_non_max_suppression.hpp" namespace vpu { @@ -104,6 +106,7 @@ const Transformations& getDefaultTransformations() { {ngraph::opset3::Reshape::type_info, dynamicToStaticShapeReshape}, {ngraph::opset3::Broadcast::type_info, dynamicToStaticShapeBroadcast}, {ngraph::opset3::MatMul::type_info, dynamicToStaticShapeMatMul}, + {ngraph::opset5::Split::type_info, dynamicToStaticShapeSplit}, // reduction {ngraph::opset3::ReduceLogicalAnd::type_info, dynamicToStaticShapeReduce}, diff --git a/inference-engine/src/vpu/common/src/ngraph/transformations/dynamic_to_static_shape_split.cpp b/inference-engine/src/vpu/common/src/ngraph/transformations/dynamic_to_static_shape_split.cpp new file mode 100644 index 0000000..a74dc25 --- /dev/null +++ b/inference-engine/src/vpu/common/src/ngraph/transformations/dynamic_to_static_shape_split.cpp @@ -0,0 +1,64 @@ +// Copyright (C) 2020 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "vpu/ngraph/transformations/dynamic_to_static_shape_broadcast.hpp" + +#include "vpu/ngraph/operations/dynamic_shape_resolver.hpp" +#include "vpu/ngraph/utilities.hpp" +#include "vpu/utils/error.hpp" + +#include "ngraph/graph_util.hpp" +#include "ngraph/opsets/opset5.hpp" +#include "ngraph/validation_util.hpp" + +namespace vpu { + +void dynamicToStaticShapeSplit(std::shared_ptr target) { + const auto split = ngraph::as_type_ptr(target); + VPU_THROW_UNLESS(split, + "dynamicToStaticShapeSplit transformation is not applicable for {}, " + "it should be {} instead", + target, ngraph::opset5::Split::type_info); + + const auto numSplits = split->get_num_splits(); + + const auto dsr = ngraph::as_type_ptr(target->input_value(0).get_node_shared_ptr()); + VPU_THROW_UNLESS(dsr, "DynamicToStaticShape transformation for {} of type {} expects {} as input with index {}", + target->get_friendly_name(), target->get_type_info(), ngraph::vpu::op::DynamicShapeResolver::type_info, 0); + + const auto dataShape = dsr->input_value(1).get_node_shared_ptr(); + const auto dataShapeType = dataShape->get_element_type(); + const auto axisNode = ngraph::as_type_ptr(target->input_value(1).get_node_shared_ptr()); + VPU_THROW_UNLESS(axisNode, "dynamicToStaticShapeSplit transformation is not applicable for {}, dynamic axis is not supported", target); + + const auto dataRank = target->get_input_partial_shape(0).rank(); + VPU_THROW_UNLESS(dataRank.is_static(), "dynamicToStaticShapeSplit transformation for {} doesn't support dynamic rank", target); + const auto srcAxis = axisNode->cast_vector(); + VPU_THROW_UNLESS(srcAxis.size() == 1, + "dynamicToStaticShapeSplit transformation for {} failed: axis node is represented as {} values while 1 is expected", + target, srcAxis.size()); + const auto resultAxis = ngraph::normalize_axis(target->description(), axisNode->cast_vector()[0], dataRank); + + const auto axisVector = ngraph::opset5::Constant::create(dataShapeType, {1}, {resultAxis}); + + const auto dimToSplitBy = std::make_shared(dataShape, + axisVector, + ngraph::opset5::Constant::create(dataShapeType, {1}, {0})); + const auto splittedDim = std::make_shared(dimToSplitBy, + ngraph::opset5::Constant::create(dataShapeType, {1}, {numSplits})); + const auto resultShape = std::make_shared(dataShape, + axisVector, + splittedDim, + ngraph::opset5::Constant::create(dataShapeType, {1}, {0})); + + const auto copied = target->clone_with_new_inputs(target->input_values()); + + for (size_t i = 0; i < copied->get_output_size(); i++) { + const auto outDSR = std::make_shared(copied->output(i), resultShape); + outDSR->set_friendly_name(target->get_friendly_name() + "." + std::to_string(i)); + target->output(i).replace(outDSR); + } +} + +} // namespace vpu diff --git a/inference-engine/tests/functional/plugin/myriad/ngraph/transformations/dynamic_to_static_shape_split.cpp b/inference-engine/tests/functional/plugin/myriad/ngraph/transformations/dynamic_to_static_shape_split.cpp new file mode 100644 index 0000000..7079e72 --- /dev/null +++ b/inference-engine/tests/functional/plugin/myriad/ngraph/transformations/dynamic_to_static_shape_split.cpp @@ -0,0 +1,126 @@ +// Copyright (C) 2020 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include +#include +#include + +#include +#include + +namespace { + +using DataType = ngraph::element::Type_t; +using DataDims = ngraph::Shape; + +struct SplitTestCase { + ngraph::Shape dataShape; + int64_t axis, numSplits; +}; + +const auto combinations = testing::Combine( + testing::Values( + ngraph::element::f16, + ngraph::element::f32, + ngraph::element::i32, + ngraph::element::i64, + ngraph::element::u8), + testing::Values( + ngraph::element::i32, + ngraph::element::i64), + testing::Values( + SplitTestCase{{6}, 0, 2}, + SplitTestCase{{6, 12, 10, 24}, 1, 4}, + SplitTestCase{{6, 12}, 1, 6}, + SplitTestCase{{6, 12, 10, 24}, 3, 4}, + SplitTestCase{{6, 12, 10, 24}, -1, 4})); + + +class DynamicToStaticShapeSplit : public CommonTestUtils::TestsCommon, + public testing::WithParamInterface> { +public: + void SetUp() override { + const auto& parameters = GetParam(); + const auto& dataType = std::get<0>(parameters); + const auto& idxType = std::get<1>(parameters); + const auto& splitSetup = std::get<2>(parameters); + + ngraph::helpers::CompareFunctions(*transform(dataType, idxType, splitSetup), + *reference(dataType, idxType, splitSetup)); + } + +protected: +std::shared_ptr transform( + const ngraph::element::Type_t& dataType, + const ngraph::element::Type_t& idxType, + const SplitTestCase& splitSetup) const { + const auto data = std::make_shared(dataType, splitSetup.dataShape); + const auto axis = ngraph::opset5::Constant::create(idxType, {}, {splitSetup.axis}); + + const auto dims = std::make_shared(ngraph::element::i64, ngraph::Shape{splitSetup.dataShape.size()}); + + const auto dsr = std::make_shared(data, dims); + const auto node = std::make_shared(dsr, axis, splitSetup.numSplits); + + // tests are capable to compare functions with one result only + const auto testsWa = std::make_shared(node->outputs(), splitSetup.axis); + + auto outputShape = node->get_output_partial_shape(0); + const auto function = std::make_shared( + ngraph::NodeVector{testsWa}, + ngraph::ParameterVector{data, dims}, + "Actual"); + node->set_output_type(0, dsr->get_input_element_type(0), ngraph::PartialShape::dynamic(splitSetup.dataShape.size())); + + const auto transformations = vpu::Transformations{{node->type_info, vpu::dynamicToStaticShapeSplit}}; + vpu::DynamicToStaticShape(transformations).run_on_function(function); + return function; +} + +std::shared_ptr reference( + const ngraph::element::Type_t& dataType, + const ngraph::element::Type_t& idxType, + const SplitTestCase& splitSetup) const { + const auto data = std::make_shared(dataType, splitSetup.dataShape); + const auto axisScalar = ngraph::opset5::Constant::create(idxType, {}, std::vector{splitSetup.axis}); + const auto axisVec = ngraph::opset5::Constant::create(idxType, {1}, std::vector{splitSetup.axis}); + + const auto dims = std::make_shared(ngraph::element::i64, ngraph::Shape{splitSetup.dataShape.size()}); + + const auto dsr = std::make_shared(data, dims); + const auto node = std::make_shared(dsr, axisScalar, splitSetup.numSplits); + + const auto dimToSplitBy = std::make_shared(dims, + axisVec, + ngraph::opset5::Constant::create(dims->get_element_type(), {1}, {0})); + const auto splittedDim = std::make_shared(dimToSplitBy, + ngraph::opset5::Constant::create(dims->get_element_type(), {1}, {splitSetup.numSplits})); + const auto newShape = std::make_shared(dims, + axisVec, + splittedDim, + ngraph::opset5::Constant::create(dims->get_element_type(), {1}, {0})); + + ngraph::NodeVector results; + for (size_t i = 0; i < node->get_output_size(); i++) { + results.push_back(std::make_shared(node->output(i), newShape)); + } + + // tests are capable to compare functions with one result only + const auto testsWa = std::make_shared(results, splitSetup.axis); + + return std::make_shared( + testsWa, + ngraph::ParameterVector{data, dims}, + "Expected"); +} +}; + +TEST_P(DynamicToStaticShapeSplit, CompareFunctions) { +} + +INSTANTIATE_TEST_CASE_P(smoke_NGraph, DynamicToStaticShapeSplit, combinations); + +} // namespace diff --git a/inference-engine/tests/functional/plugin/myriad/subgraph_tests/dsr_split.cpp b/inference-engine/tests/functional/plugin/myriad/subgraph_tests/dsr_split.cpp new file mode 100644 index 0000000..103a032 --- /dev/null +++ b/inference-engine/tests/functional/plugin/myriad/subgraph_tests/dsr_split.cpp @@ -0,0 +1,61 @@ +// Copyright (C) 2020 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "dsr_tests_common.hpp" + +namespace { + +using namespace LayerTestsUtils::vpu; + +struct SplitTestCase { + DataShapeWithUpperBound dataShapes; + int64_t axis, numSplits; +}; + +const auto combinations = testing::Combine( + testing::Values( + ngraph::element::f16), + testing::Values( + ngraph::element::i32), + testing::Values( + SplitTestCase{{{6, 12, 10}, {6, 12, 15}}, 1, 3}, + SplitTestCase{{{6, 12, 10}, {9, 12, 10}}, 1, 3}, + SplitTestCase{{{6, 12}, {10, 12}}, 1, 4}, + SplitTestCase{{{6, 12, 10, 24}, {6, 12, 10, 50}}, 0, 6}, + SplitTestCase{{{6, 12, 10, 24}, {6, 12, 10, 50}}, -3, 2}, + SplitTestCase{{{1, 128, 4}, {1, 256, 4}}, 2, 4}), + testing::Values(CommonTestUtils::DEVICE_MYRIAD)); + + +using Parameters = std::tuple< + DataType, + DataType, + SplitTestCase, + LayerTestsUtils::TargetDevice +>; + +class DSR_Split : public testing::WithParamInterface, public DSR_TestsCommon { +protected: + std::shared_ptr createTestedOp() override { + const auto& parameters = GetParam(); + const auto& dataType = std::get<0>(parameters); + const auto& idxType = std::get<1>(parameters); + const auto& splitSetup = std::get<2>(parameters); + targetDevice = std::get<3>(parameters); + + const auto inputSubgraph = createInputSubgraphWithDSR(dataType, splitSetup.dataShapes); + + const auto axis = ngraph::opset5::Constant::create(idxType, {}, {splitSetup.axis}); + + return std::make_shared(inputSubgraph, axis, splitSetup.numSplits); + } +}; + +TEST_P(DSR_Split, CompareWithReference) { + Run(); +} + +INSTANTIATE_TEST_CASE_P(smoke_DynamicSplit, DSR_Split, combinations); + +} // namespace diff --git a/inference-engine/tests/ie_test_utils/functional_test_utils/layer_test_utils.hpp b/inference-engine/tests/ie_test_utils/functional_test_utils/layer_test_utils.hpp index 0962d0e..813c531 100644 --- a/inference-engine/tests/ie_test_utils/functional_test_utils/layer_test_utils.hpp +++ b/inference-engine/tests/ie_test_utils/functional_test_utils/layer_test_utils.hpp @@ -66,7 +66,6 @@ protected: template void Compare(const T *expected, const T *actual, std::size_t size, T threshold) { - std::cout << std::endl; for (std::size_t i = 0; i < size; ++i) { const auto &ref = expected[i]; const auto &res = actual[i]; -- 2.7.4