--- /dev/null
+// Copyright (C) 2020 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#pragma once
+
+#include "ngraph/op/util/attr_types.hpp"
+#include "ngraph/node.hpp"
+#include <ngraph/opsets/opset3.hpp>
+
+#include <memory>
+#include <vector>
+
+namespace ngraph { namespace vpu { namespace op {
+
+class StaticShapeReshape : public ngraph::opset3::Reshape {
+public:
+ StaticShapeReshape(const Output<Node>& arg, const Output<Node>& pattern, bool special_zero);
+ explicit StaticShapeReshape(const std::shared_ptr<ngraph::opset3::Reshape>& reshape);
+
+ static constexpr NodeTypeInfo type_info{"StaticShapeReshape", 0};
+ const NodeTypeInfo& get_type_info() const override { return type_info; }
+
+ void validate_and_infer_types() override;
+};
+
+} // namespace op
+} // namespace vpu
+} // namespace ngraph
namespace vpu {
-class DynamicToStaticShapeShapeOf : public ngraph::pass::GraphRewrite {
+class EliminateShapeOfAfterDSR : public ngraph::pass::GraphRewrite {
public:
- DynamicToStaticShapeShapeOf();
+ EliminateShapeOfAfterDSR();
};
} //namespace vpu
--- /dev/null
+// Copyright (C) 2020 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#pragma once
+
+#include "ngraph/node.hpp"
+
+std::vector<std::int64_t> evaluateTargetShape(const ngraph::Output<ngraph::Node>& value);
//
#include "vpu/ngraph/operations/static_shape_broadcast.hpp"
+#include "vpu/ngraph/utilities.hpp"
#include "vpu/utils/error.hpp"
namespace ngraph { namespace vpu { namespace op {
-namespace {
-
-HostTensorVector evaluateShapeOf(Node* node, const HostTensorVector&) {
- auto shapeOf = as_type<opset3::ShapeOf>(node);
- const auto inputValue = shapeOf->input_value(0);
- const auto outputValue = shapeOf->output(0);
- const auto inputTensors =
- HostTensorVector{std::make_shared<runtime::HostTensor>(inputValue)};
- const auto outputTensors =
- HostTensorVector{std::make_shared<runtime::HostTensor>(outputValue)};
-
- shapeOf->evaluate(outputTensors, inputTensors);
- return outputTensors;
-}
-
-HostTensorVector evaluateConstant(Node* node, const HostTensorVector&) {
- const auto constantNode = as_type<opset3::Constant>(node);
- const auto constant = std::make_shared<opset3::Constant>(*constantNode);
-
- const auto outputTensor = std::make_shared<runtime::HostTensor>(constant);
-
- return {outputTensor};
-}
-
-HostTensorVector evaluateOp(Node* node, const HostTensorVector& inputTensors) {
- HostTensorVector outputTensors;
- for (const auto& output : node->outputs()) {
- outputTensors.push_back(std::make_shared<HostTensor>(output));
- }
-
- node->evaluate(outputTensors, inputTensors);
- return outputTensors;
-}
-
-PartialShape evaluateTargetShape(const Output<Node>& value) {
- static Evaluator<HostTensorPtr>::op_handler_map handlers = {
- {opset3::ShapeOf::type_info, evaluateShapeOf},
- {opset3::Constant::type_info, evaluateConstant},
- {opset3::Gather::type_info, evaluateOp},
- {opset3::Concat::type_info, evaluateOp}};
- Evaluator<HostTensorPtr>::value_map value_map;
- Evaluator<HostTensorPtr> evaluator(handlers, value_map);
-
- const auto shapeTensor = evaluator.evaluate(value);
- if (!shapeTensor || !shapeTensor->get_is_allocated()) {
- return PartialShape::dynamic();
- }
- const auto shapeConstNode = std::make_shared<opset3::Constant>(shapeTensor);
- const auto resultShape = Shape{shapeConstNode->cast_vector<size_t>()};
-
- return resultShape;
-}
-
-} // namespace
-
constexpr NodeTypeInfo StaticShapeBroadcast::type_info;
StaticShapeBroadcast::StaticShapeBroadcast(const Output<Node>& arg,
::ngraph::op::util::BroadcastBase::validate_and_infer_types();
// Try to evaluate output shape. After some transformations further, we may not be able
// to evaluate the target shape again, then we will leave the evaluated shape unchanged.
- // For example, DynamicToStaticShapeShapeOf remove ShapeOf and pass the second input of DSR.
- const auto evaluatedTargetShape = evaluateTargetShape(input_value(1));
+ // For example, EliminateShapeOfAfterDSR remove ShapeOf and pass the second input of DSR.
+ const auto evaluatedDimensionValues = evaluateTargetShape(input_value(1));
+ NODE_VALIDATION_CHECK(this, !evaluatedDimensionValues.empty(), "StaticShapeBroadcast (", get_friendly_name(), ") can't evaluate output shape");
+
+ const auto evaluatedTargetShape = ngraph::PartialShape(evaluatedDimensionValues);
if (evaluatedTargetShape.is_static()) {
m_evaluatedOutputShape = evaluatedTargetShape;
}
NODE_VALIDATION_CHECK(this, m_evaluatedOutputShape.is_static(),
"StaticShapeBroadcast (", get_friendly_name(), ") ",
"can't evaluate output shape, got: ", m_evaluatedOutputShape);
+ NODE_VALIDATION_CHECK(this, m_evaluatedOutputShape.all_non_negative(),
+ "StaticShapeBroadcast (", get_friendly_name(), ") ",
+ "expects non-negative shape, got: ", m_evaluatedOutputShape);
set_output_type(0, get_input_element_type(0), m_evaluatedOutputShape);
}
}
--- /dev/null
+// Copyright (C) 2020 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#include <numeric>
+#include "vpu/ngraph/operations/static_shape_reshape.hpp"
+#include "vpu/ngraph/utilities.hpp"
+
+namespace ngraph { namespace vpu { namespace op {
+
+constexpr NodeTypeInfo StaticShapeReshape::type_info;
+
+StaticShapeReshape::StaticShapeReshape(const Output<Node>& arg, const Output<Node>& pattern, bool special_zero)
+ : ::ngraph::opset3::Reshape(arg, pattern, special_zero) {
+ constructor_validate_and_infer_types();
+}
+
+StaticShapeReshape::StaticShapeReshape(const std::shared_ptr<ngraph::opset3::Reshape>& reshape)
+ : StaticShapeReshape(reshape->get_argument(0), reshape->get_argument(1), reshape->get_special_zero()) {
+}
+
+void StaticShapeReshape::validate_and_infer_types() {
+ const auto& targetShape = input_value(1);
+ if (as_type_ptr<opset3::Constant>(targetShape.get_node_shared_ptr())) {
+ opset3::Reshape::validate_and_infer_types();
+ return;
+ }
+
+ NODE_VALIDATION_CHECK(this, get_input_element_type(1).is_integral_number(), "Pattern must be an integral number.");
+ NODE_VALIDATION_CHECK(this, get_input_partial_shape(1).rank().compatible(1), "Pattern must have rank 1, got ", get_input_partial_shape(1).rank(), ".");
+
+ set_input_is_relevant_to_shape(1);
+
+ NODE_VALIDATION_CHECK(this, get_input_partial_shape(0).is_static(), "StaticShapeReshape (", get_friendly_name(), ") ",
+ "input#0 is expected to be of static shape, got: ", get_input_partial_shape(0));
+
+ if (get_output_partial_shape(0).is_static()) {
+ return;
+ }
+
+ const auto& inputShape = get_input_shape(0);
+
+ auto outputDimensionsValues = evaluateTargetShape(targetShape);
+ NODE_VALIDATION_CHECK(this, !outputDimensionsValues.empty(), "StaticShapeReshape (", get_friendly_name(), ") can't evaluate output shape");
+
+ for (std::size_t i = 0; i < outputDimensionsValues.size(); ++i) {
+ if (outputDimensionsValues[i] == 0 && m_special_zero) {
+ NODE_VALIDATION_CHECK(this, inputShape[i] <= static_cast<std::size_t>(std::numeric_limits<std::int64_t>::max()),
+ "StaticShapeReshape (", get_friendly_name(), ") out of range input shape dimension value: ", inputShape[i]);
+ outputDimensionsValues[i] = static_cast<std::int64_t>(inputShape[i]);
+ }
+ }
+
+ NODE_VALIDATION_CHECK(this, std::none_of(outputDimensionsValues.cbegin(), outputDimensionsValues.cend(),
+ [](std::int64_t dimension) { return dimension < -1; }), "Dim size cannot be less than -1, got ", ngraph::PartialShape(outputDimensionsValues));
+ const auto negativeDimsCount = std::count_if(outputDimensionsValues.cbegin(), outputDimensionsValues.cend(),
+ [](std::int64_t dimension) { return dimension == -1; });
+ NODE_VALIDATION_CHECK(this, negativeDimsCount <= 1, "More than one dimension has size of -1 (", negativeDimsCount, ")");
+
+ const auto& inputShapeVolume = shape_size(inputShape);
+ if (negativeDimsCount == 1) {
+ const auto& outputShapeVolume = std::abs(std::accumulate(
+ outputDimensionsValues.cbegin(),
+ outputDimensionsValues.cend(),
+ static_cast<std::int64_t>(1),
+ std::multiplies<std::int64_t>())); //shape_size(outputDimensionsValues);
+ NODE_VALIDATION_CHECK(this, inputShapeVolume % outputShapeVolume == 0, "StaticShapeReshape (", get_friendly_name(), ") ",
+ "output shape volume does not evenly divide the input shape volume: input shape volume = ", inputShapeVolume, " output shape ",
+ "volume = ", outputShapeVolume);
+ NODE_VALIDATION_CHECK(this, outputShapeVolume != 0, "StaticShapeReshape (", get_friendly_name(), ") ",
+ "output shape volume is equal to 0");
+
+ const auto actualValue = inputShapeVolume / outputShapeVolume;
+ NODE_VALIDATION_CHECK(this, actualValue <= static_cast<std::size_t>(std::numeric_limits<std::int64_t>::max()),
+ "StaticShapeReshape (", get_friendly_name(), ") out of range output shape dimension value: ", actualValue);
+ std::replace(outputDimensionsValues.begin(), outputDimensionsValues.end(),
+ static_cast<std::int64_t>(-1), static_cast<std::int64_t>(actualValue));
+ }
+
+ const auto& outputShape = ngraph::PartialShape(outputDimensionsValues);
+ NODE_VALIDATION_CHECK(this, inputShapeVolume == shape_size(outputDimensionsValues), "Requested output shape (upper-bound) ", outputShape,
+ " is incompatible with input shape ", get_input_shape(0), " (upper-bound)");
+
+ set_output_type(0, get_input_element_type(0), outputShape);
+}
+
+} // namespace op
+} // namespace vpu
+} // namespace ngraph
#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_shapeof.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"
transformation->second(operation);
}
- // Should be executed after all dynamic-to-static transformations
- DynamicToStaticShapeShapeOf().run_on_function(function);
-
function->validate_nodes_and_infer_types();
validateStaticShapes(*function);
}
#include "ngraph/opsets/opset3.hpp"
#include <memory>
+#include <vpu/ngraph/operations/static_shape_reshape.hpp>
namespace vpu {
"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 outShapeDescriptor = target->get_argument(1);
- VPU_THROW_UNLESS(ngraph::as_type_ptr<ngraph::opset3::Constant>(outShapeDescriptor),
- "DynamicToStaticShape transformation for {} of type {} expects {} as input with index {}",
- target->get_friendly_name(), target->get_type_info(), ngraph::opset3::Constant::type_info, 1);
-
const auto reshape = std::dynamic_pointer_cast<ngraph::opset3::Reshape>(target);
- const auto copied = reshape->clone_with_new_inputs(target->input_values());
- const auto inDataShape = dsr->input(1).get_source_output();
+ const auto outShapeDescriptor = reshape->get_argument(1);
- const auto outShapeOfReshape = std::make_shared<ngraph::vpu::op::OutShapeOfReshape>(
- inDataShape, outShapeDescriptor, reshape->get_special_zero());
+ const auto replacement = ngraph::as_type_ptr<ngraph::opset3::Constant>(outShapeDescriptor)
+ ? reshape->clone_with_new_inputs(reshape->input_values())
+ : std::make_shared<ngraph::vpu::op::StaticShapeReshape>(reshape);
+
+ const auto inDataShape = dsr->input(1).get_source_output();
+ const auto outShapeOfReshape = std::make_shared<ngraph::vpu::op::OutShapeOfReshape>(inDataShape, outShapeDescriptor, reshape->get_special_zero());
- auto outDSR = std::make_shared<ngraph::vpu::op::DynamicShapeResolver>(copied, outShapeOfReshape);
+ auto outDSR = std::make_shared<ngraph::vpu::op::DynamicShapeResolver>(replacement, outShapeOfReshape);
outDSR->set_friendly_name(reshape->get_friendly_name());
ngraph::replace_node(std::move(target), std::move(outDSR));
}
// SPDX-License-Identifier: Apache-2.0
//
-#include "vpu/ngraph/transformations/dynamic_to_static_shape_shapeof.hpp"
+#include "vpu/ngraph/transformations/eliminate_shapeof_after_dsr.hpp"
#include <vpu/ngraph/operations/dynamic_shape_resolver.hpp>
#include <vpu/utils/error.hpp>
namespace vpu {
-DynamicToStaticShapeShapeOf::DynamicToStaticShapeShapeOf() : GraphRewrite() {
+EliminateShapeOfAfterDSR::EliminateShapeOfAfterDSR() : GraphRewrite() {
// We don't set strict_mode when use pattern Matcher,
// so we can set any type and shape for input.
auto inputWithAnyTypeAndShape = std::make_shared<ngraph::pattern::op::Label>(
return true;
};
- auto m = std::make_shared<ngraph::pattern::Matcher>(shapeOfPattern, "DynamicToStaticShapeShapeOf");
+ auto m = std::make_shared<ngraph::pattern::Matcher>(shapeOfPattern, "EliminateShapeOfAfterDSR");
this->add_matcher(m, callback, ngraph::pass::PassProperty::CHANGE_DYNAMIC_STATE);
}
--- /dev/null
+// Copyright (C) 2020 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#include "vpu/ngraph/utilities.hpp"
+
+#include "ngraph/opsets/opset3.hpp"
+#include "ngraph/evaluator.hpp"
+
+ngraph::HostTensorVector evaluateShapeOf(ngraph::Node* node, const ngraph::HostTensorVector&) {
+ auto shapeOf = ngraph::as_type<ngraph::opset3::ShapeOf>(node);
+ const auto inputValue = shapeOf->input_value(0);
+ const auto outputValue = shapeOf->output(0);
+ const auto inputTensors =
+ ngraph::HostTensorVector{std::make_shared<ngraph::runtime::HostTensor>(inputValue)};
+ const auto outputTensors =
+ ngraph::HostTensorVector{std::make_shared<ngraph::runtime::HostTensor>(outputValue)};
+
+ shapeOf->evaluate(outputTensors, inputTensors);
+ return outputTensors;
+}
+
+ngraph::HostTensorVector evaluateConstant(ngraph::Node* node, const ngraph::HostTensorVector&) {
+ const auto constantNode = ngraph::as_type<ngraph::opset3::Constant>(node);
+ const auto constant = std::make_shared<ngraph::opset3::Constant>(*constantNode);
+
+ const auto outputTensor = std::make_shared<ngraph::runtime::HostTensor>(constant);
+
+ return {outputTensor};
+}
+
+ngraph::HostTensorVector evaluateOp(ngraph::Node* node, const ngraph::HostTensorVector& inputTensors) {
+ ngraph::HostTensorVector outputTensors;
+ for (const auto& output : node->outputs()) {
+ outputTensors.push_back(std::make_shared<ngraph::HostTensor>(output));
+ }
+
+ node->evaluate(outputTensors, inputTensors);
+ return outputTensors;
+}
+
+std::vector<std::int64_t> evaluateTargetShape(const ngraph::Output<ngraph::Node>& value) {
+ static ngraph::Evaluator<ngraph::HostTensorPtr>::op_handler_map handlers = {
+ {ngraph::opset3::ShapeOf::type_info, evaluateShapeOf},
+ {ngraph::opset3::Constant::type_info, evaluateConstant},
+ {ngraph::opset3::Gather::type_info, evaluateOp},
+ {ngraph::opset3::Concat::type_info, evaluateOp},
+ {ngraph::opset3::Reshape::type_info, evaluateOp},
+ {ngraph::opset3::Multiply::type_info, evaluateOp},
+ {ngraph::opset3::Squeeze::type_info, evaluateOp},
+ };
+ ngraph::Evaluator<ngraph::HostTensorPtr>::value_map value_map;
+ ngraph::Evaluator<ngraph::HostTensorPtr> evaluator(handlers, value_map);
+
+ const auto shapeTensor = evaluator.evaluate(value);
+ if (!shapeTensor || !shapeTensor->get_is_allocated()) {
+ return {};
+ }
+
+ const auto shapeConstNode = std::make_shared<ngraph::opset3::Constant>(shapeTensor);
+ return {shapeConstNode->cast_vector<std::int64_t>()};
+}
{"OutShapeOfReshape", LAYER_PARSER(parseOutShapeOfReshape)},
{"StaticShapeBroadcast", LAYER_PARSER(parseBroadcast)},
{"StaticShapeNonMaxSuppression", LAYER_PARSER(parseStaticShapeNMS)},
+ {"StaticShapeReshape", LAYER_PARSER(parseReshape)},
}} {}
ModelPtr FrontEnd::buildInitialModel(ie::ICNNNetwork& network) {
} // namespace
void FrontEnd::parseReshape(const Model& model, const ie::CNNLayerPtr& layer, const DataVector& inputs, const DataVector& outputs) const {
- VPU_THROW_UNLESS(inputs.size() == 1 || (inputs.size() == 2 && inputs[1]->usage() == DataUsage::Const),
+ VPU_THROW_UNLESS(inputs.size() == 1 || inputs.size() == 2,
"%v of type %v is not supported with dynamic shape", layer->name, layer->type);
- IE_ASSERT((inputs.size() == 1) || (inputs.size() == 2 && inputs[1]->usage() == DataUsage::Const));
IE_ASSERT(outputs.size() == 1);
_stageBuilder->addReshapeStage(model, layer->name, layer, inputs[0], outputs[0]);
}
#include <transformations/common_optimizations/common_optimizations.hpp>
#include "vpu/ngraph/transformations/dynamic_to_static_shape.hpp"
+#include "vpu/ngraph/transformations/eliminate_shapeof_after_dsr.hpp"
+
#include "generic_ie.hpp"
#include "myriad_plugin.h"
ngraph::op::GenericIE::DisableReshape noReshape(function);
ngraph::pass::CommonOptimizations().run_on_function(function);
vpu::DynamicToStaticShape().transform(function);
+ vpu::EliminateShapeOfAfterDSR().run_on_function(function);
}
return std::make_shared<ExecutableNetwork>(*clonedNetwork, _mvnc, _devicePool, parsedConfigCopy);
//
#include "vpu/ngraph/transformations/dynamic_to_static_shape_reshape.hpp"
+#include "vpu/ngraph/transformations/dynamic_to_static_shape.hpp"
#include "vpu/ngraph/operations/out_shape_of_reshape.hpp"
#include "vpu/ngraph/operations/dynamic_shape_resolver.hpp"
-#include <ngraph_functions/utils/ngraph_helpers.hpp>
-#include <ngraph/function.hpp>
-#include <ngraph/opsets/opset1.hpp>
+#include "ngraph_functions/utils/ngraph_helpers.hpp"
+#include "ngraph/opsets/opset3.hpp"
+#include "ngraph/function.hpp"
-#include <common_test_utils/test_common.hpp>
-#include <gtest/gtest.h>
+#include "common_test_utils/test_common.hpp"
+#include "gtest/gtest.h"
#include <string>
#include <memory>
#include <map>
#include <vector>
-#include <vpu/ngraph/transformations/dynamic_to_static_shape.hpp>
+#include <vpu/ngraph/operations/static_shape_reshape.hpp>
namespace {
-using DataType = ngraph::element::Type;
using DataShape = ngraph::Shape;
-using TestParams = std::tuple<DataShape, DataType>;
+using DataType = ngraph::element::Type;
+using ReshapePatternGenerator = std::function<std::shared_ptr<ngraph::op::Op>(std::shared_ptr<ngraph::vpu::op::DynamicShapeResolver>)>;
-class DynamicToStaticShapeReshapeTests
- : public CommonTestUtils::TestsCommon,
- public testing::WithParamInterface<TestParams> {
+using TestParams = std::tuple<DataShape, DataType, ReshapePatternGenerator>;
+
+class DynamicToStaticShapeReshapeTests : public CommonTestUtils::TestsCommon, public testing::WithParamInterface<TestParams> {
public:
void SetUp() override {
const auto& parameters = GetParam();
- const auto& inDataShape = std::get<0>(parameters);
- const auto& inDataType = std::get<1>(parameters);
+ m_inDataShape = std::get<0>(parameters);
+ m_inDataType = std::get<1>(parameters);
+ m_patternGenerator = std::get<2>(parameters);
- ngraph::helpers::CompareFunctions(
- *transform(inDataType, inDataShape),
- *reference(inDataType, inDataShape));
+ const auto& actual = transform();
+ const auto& expected = reference();
+ ngraph::helpers::CompareFunctions(*actual, *expected);
}
protected:
- std::shared_ptr<const ngraph::Function> transform(
- const ngraph::element::Type& inDataType,
- const ngraph::Shape& inDataShape) const {
- const auto inDataParam = std::make_shared<ngraph::op::Parameter>(
- inDataType, inDataShape);
- const auto inDataDimsParam = std::make_shared<ngraph::op::Parameter>(
- ngraph::element::i64, ngraph::Shape{inDataShape.size()});
- const auto outShapeDescriptorParam = std::make_shared<ngraph::op::Constant>(
- ngraph::element::i64, ngraph::Shape{inDataShape.size()}, inDataShape);
-
- const auto dsr = std::make_shared<ngraph::vpu::op::DynamicShapeResolver>(
- inDataParam, inDataDimsParam);
- const auto reshape = std::make_shared<ngraph::op::v1::Reshape>(
- dsr, outShapeDescriptorParam, true);
-
- auto function = std::make_shared<ngraph::Function>(
- ngraph::NodeVector{reshape},
- ngraph::ParameterVector{inDataParam, inDataDimsParam},
- "Actual");
- reshape->set_output_type(0, dsr->get_input_element_type(0), ngraph::PartialShape::dynamic(
- outShapeDescriptorParam->get_output_partial_shape(0).rank()));
-
- const auto transformations = vpu::Transformations{{
- ngraph::op::v1::Reshape::type_info, vpu::dynamicToStaticShapeReshape}};
+ std::shared_ptr<const ngraph::Function> transform() const {
+ const auto dsr = generateInputSubgraph();
+
+ const auto outShapeDescriptorParam = m_patternGenerator(dsr);
+ const auto reshape = std::make_shared<ngraph::op::v1::Reshape>(dsr, outShapeDescriptorParam, true);
+
+ const auto function = generateFunction(reshape, *dsr, "Actual");
+ reshape->set_output_type(
+ 0,
+ dsr->get_input_element_type(0),
+ ngraph::PartialShape::dynamic(outShapeDescriptorParam->get_output_partial_shape(0).rank()));
+
+ const auto transformations = vpu::Transformations{{ngraph::op::v1::Reshape::type_info, vpu::dynamicToStaticShapeReshape}};
vpu::DynamicToStaticShape(transformations).transform(function);
return function;
}
- std::shared_ptr<const ngraph::Function> reference(
- const ngraph::element::Type& inDataType,
- const ngraph::Shape& inDataShape) const {
- const auto inDataParam = std::make_shared<ngraph::op::Parameter>(
- inDataType, inDataShape);
- const auto inDataDimsParam = std::make_shared<ngraph::op::Parameter>(
- ngraph::element::i64, ngraph::Shape{inDataShape.size()});
- const auto outShapeDescriptorParam = std::make_shared<ngraph::op::Constant>(
- ngraph::element::i64, ngraph::Shape{inDataShape.size()}, inDataShape);
-
- const auto dsr0 = std::make_shared<ngraph::vpu::op::DynamicShapeResolver>(
- inDataParam, inDataDimsParam);
- const auto reshape = std::make_shared<ngraph::op::v1::Reshape>(
- dsr0, outShapeDescriptorParam, true);
-
- const auto outShapeOfReshape = std::make_shared<ngraph::vpu::op::OutShapeOfReshape>(
- inDataDimsParam, outShapeDescriptorParam, true);
- const auto dsr1 = std::make_shared<ngraph::vpu::op::DynamicShapeResolver>(
- reshape, outShapeOfReshape);
+ std::shared_ptr<const ngraph::Function> reference() const {
+ const auto dsr0 = generateInputSubgraph();
+
+ const auto outShapeDescriptorParam = m_patternGenerator(dsr0);
+ const auto reshape = ngraph::as_type_ptr<ngraph::opset3::Constant>(outShapeDescriptorParam)
+ ? std::make_shared<ngraph::opset3::Reshape>(dsr0, outShapeDescriptorParam, true)
+ : std::make_shared<ngraph::vpu::op::StaticShapeReshape>(dsr0, outShapeDescriptorParam, true);
+
+ const auto outShapeOfReshape = std::make_shared<ngraph::vpu::op::OutShapeOfReshape>(dsr0->input_value(1), outShapeDescriptorParam, true);
+ const auto dsr1 = std::make_shared<ngraph::vpu::op::DynamicShapeResolver>(reshape, outShapeOfReshape);
+ return generateFunction(dsr1, *dsr0, "Expected");
+ }
+
+private:
+ std::shared_ptr<ngraph::vpu::op::DynamicShapeResolver> generateInputSubgraph() const {
+ const auto inDataParam = std::make_shared<ngraph::op::Parameter>(m_inDataType, m_inDataShape);
+ const auto inDataDimsParam = std::make_shared<ngraph::op::Parameter>(ngraph::element::i64, ngraph::Shape{m_inDataShape.size()});
+ return std::make_shared<ngraph::vpu::op::DynamicShapeResolver>(inDataParam, inDataDimsParam);
+ }
+
+ static std::shared_ptr<ngraph::Function> generateFunction(std::shared_ptr<ngraph::op::Op> result, const ngraph::op::Op& input, const std::string& name) {
return std::make_shared<ngraph::Function>(
- ngraph::NodeVector{dsr1},
- ngraph::ParameterVector{inDataParam, inDataDimsParam},
- "Expected");
+ ngraph::NodeVector{std::move(result)},
+ ngraph::ParameterVector{
+ std::dynamic_pointer_cast<ngraph::opset3::Parameter>(input.get_input_node_shared_ptr(0)),
+ std::dynamic_pointer_cast<ngraph::opset3::Parameter>(input.get_input_node_shared_ptr(1))
+ },
+ name);
}
+
+private:
+ DataShape m_inDataShape;
+ DataType m_inDataType;
+ ReshapePatternGenerator m_patternGenerator;
};
-TEST_P(DynamicToStaticShapeReshapeTests, compareFunctions) {
+TEST_P(DynamicToStaticShapeReshapeTests, compareFunctions) {}
+
+std::shared_ptr<ngraph::op::Op> generateStaticReshapePattern(std::shared_ptr<ngraph::vpu::op::DynamicShapeResolver> dsr) {
+ const auto& inDataShape = dsr->input_value(0).get_shape();
+ std::vector<std::int64_t> pattern(inDataShape.rbegin(), inDataShape.rend());
+ return std::make_shared<ngraph::op::Constant>(ngraph::element::i64, ngraph::Shape{pattern.size()}, pattern);
+}
+
+std::shared_ptr<ngraph::op::Op> generateDynamicReshapePattern(std::shared_ptr<ngraph::vpu::op::DynamicShapeResolver> dsr) {
+ const auto shapeOf = std::make_shared<ngraph::opset3::ShapeOf>(std::move(dsr));
+ const auto axis = ngraph::opset3::Constant::create(ngraph::element::i64, {1}, {0});
+ const auto indices = ngraph::opset3::Constant::create(ngraph::element::i64, {1}, {0});
+ return std::make_shared<ngraph::opset3::Concat>(
+ ngraph::OutputVector{
+ std::make_shared<ngraph::opset3::Gather>(shapeOf, indices, axis),
+ ngraph::opset3::Constant::create(ngraph::element::i64, {1}, {-1})},
+ 0);
}
INSTANTIATE_TEST_CASE_P(NGraph, DynamicToStaticShapeReshapeTests, testing::Combine(
- testing::Values(
- DataShape{4, 1000},
- DataShape{3, 128, 256},
- DataShape{2, 3, 128, 256}),
- testing::Values(
- ngraph::element::f16,
- ngraph::element::f32,
- ngraph::element::i32,
- ngraph::element::i64,
- ngraph::element::u8)
+ testing::Values(
+ DataShape{4, 1000},
+ DataShape{3, 128, 256},
+ DataShape{2, 3, 128, 256},
+ DataShape{1000, 256, 7, 7}),
+ testing::Values(
+ ngraph::element::f16,
+ ngraph::element::f32,
+ ngraph::element::i32,
+ ngraph::element::i64,
+ ngraph::element::u8),
+ testing::Values(
+ generateStaticReshapePattern,
+ generateDynamicReshapePattern)
));
} // namespace
// SPDX-License-Identifier: Apache-2.0
//
-#include "vpu/ngraph/transformations/dynamic_to_static_shape_shapeof.hpp"
+#include "vpu/ngraph/transformations/eliminate_shapeof_after_dsr.hpp"
#include <vpu/ngraph/operations/dynamic_shape_resolver.hpp>
#include <vpu/ngraph/transformations/dynamic_to_static_shape.hpp>
using TensorType = ngraph::element::Type_t;
using TensorShape = ngraph::Shape;
-class DynamicToStaticShapeShapeOfRemoveDSR : public CommonTestUtils::TestsCommon,
- public testing::WithParamInterface<std::tuple<TensorType, TensorShape>> {
+class EliminateShapeOfAfterDSRTest : public CommonTestUtils::TestsCommon,
+ public testing::WithParamInterface<std::tuple<TensorType, TensorShape>> {
public:
void SetUp() override {
const auto& parameters = GetParam();
ngraph::ParameterVector{data, shape},
"Actual");
- vpu::DynamicToStaticShapeShapeOf().run_on_function(function);
+ vpu::EliminateShapeOfAfterDSR().run_on_function(function);
return function;
}
}
};
-TEST_P(DynamicToStaticShapeShapeOfRemoveDSR, CompareFunctions) {
+TEST_P(EliminateShapeOfAfterDSRTest, CompareFunctions) {
}
-INSTANTIATE_TEST_CASE_P(NGraph, DynamicToStaticShapeShapeOfRemoveDSR, testing::Combine(
+INSTANTIATE_TEST_CASE_P(NGraph, EliminateShapeOfAfterDSRTest, testing::Combine(
testing::Values(
ngraph::element::f16,
ngraph::element::f32,
TensorShape{2, 3, 128, 256})
));
-class DynamicToStaticShapeShapeOfWithOutRemoveDSR : public CommonTestUtils::TestsCommon,
- public testing::WithParamInterface<std::tuple<TensorType, TensorShape>> {
+class EliminateShapeOfAfterDSRWithoutOutputDSR : public CommonTestUtils::TestsCommon,
+ public testing::WithParamInterface<std::tuple<TensorType, TensorShape>> {
public:
void SetUp() override {
const auto& parameters = GetParam();
ngraph::ParameterVector{data, shape},
"Actual");
- vpu::DynamicToStaticShapeShapeOf().run_on_function(function);
+ vpu::EliminateShapeOfAfterDSR().run_on_function(function);
return function;
}
}
};
-TEST_P(DynamicToStaticShapeShapeOfWithOutRemoveDSR, CompareFunctions) {
+TEST_P(EliminateShapeOfAfterDSRWithoutOutputDSR, CompareFunctions) {
}
-INSTANTIATE_TEST_CASE_P(NGraph, DynamicToStaticShapeShapeOfWithOutRemoveDSR, testing::Combine(
+INSTANTIATE_TEST_CASE_P(NGraph, EliminateShapeOfAfterDSRWithoutOutputDSR, testing::Combine(
testing::Values(
ngraph::element::f16,
ngraph::element::f32,
TensorShape{2, 3, 128, 256})
));
-class DynamicToStaticShapeShapeOfKeepDSR : public CommonTestUtils::TestsCommon,
- public testing::WithParamInterface<std::tuple<TensorType, TensorShape>> {
+class EliminateShapeOfAfterDSRKeepDSR : public CommonTestUtils::TestsCommon,
+ public testing::WithParamInterface<std::tuple<TensorType, TensorShape>> {
public:
void SetUp() override {
const auto& parameters = GetParam();
ngraph::ParameterVector{data, shape},
"Actual");
- vpu::DynamicToStaticShapeShapeOf().run_on_function(function);
+ vpu::EliminateShapeOfAfterDSR().run_on_function(function);
return function;
}
}
};
-TEST_P(DynamicToStaticShapeShapeOfKeepDSR, CompareFunctions) {
+TEST_P(EliminateShapeOfAfterDSRKeepDSR, CompareFunctions) {
}
-INSTANTIATE_TEST_CASE_P(NGraph, DynamicToStaticShapeShapeOfKeepDSR, testing::Combine(
+INSTANTIATE_TEST_CASE_P(NGraph, EliminateShapeOfAfterDSRKeepDSR, testing::Combine(
testing::Values(
ngraph::element::f16,
ngraph::element::f32,
bool evaluate(const HostTensorVector& outputs,
const HostTensorVector& inputs) override;
- private:
+ protected:
bool m_special_zero;
};
}
using namespace ngraph;
+PartialShape::PartialShape(const std::vector<Dimension::value_type>& dimensions)
+ : m_rank_is_static(true)
+{
+ std::transform(dimensions.cbegin(),
+ dimensions.cend(),
+ std::back_inserter(m_dimensions),
+ [](const Dimension::value_type& dimension) { return dimension; });
+}
+
PartialShape::PartialShape(const Shape& shape)
: PartialShape(true, {})
{
{
}
+ /// \brief Constructs a PartialShape with static rank from a vector of dimensions values.
+ /// \param dimensions The Dimension values for the constructed shape.
+ PartialShape(const std::vector<Dimension::value_type>& dimensions);
+
/// \brief Constructs a static PartialShape with zero rank (the shape of a scalar).
PartialShape()
: PartialShape(std::initializer_list<Dimension>{})