[CPU][Snippets]fix candidate merged node's subgraph inputs have common subgraph input (#16249)

This commit is contained in:
Chenhu Wang authored and GitHub committed 2023-04-19 11:12:52 +04:00
1 parent 1525f6cc16
commit 34b3abc0e2
6 files changed
+162 -1

No files matched your search

@@ -389,7 +389,11 @@ TokenizeSnippets::TokenizeSnippets() {
size_t current_input_index = body_parameters.size();
for (size_t p_ind = 0; p_ind < body_parameters.size(); p_ind++) {
const auto & p = body_parameters[p_ind];
if (p->get_friendly_name() == found->get_node_shared_ptr()->get_friendly_name()) {
// unite two body parameters from two input subgraphs only if:
// 1. two input subgraphs are connected to the same parent node/subgraph,
// 2. and connected to the same output port of this parent node/subgraph.
if (p->get_friendly_name() == found->get_node_shared_ptr()->get_friendly_name() &&
external_inputs[p_ind] == *found) {
current_input_index = p_ind;
break;
}
@@ -0,0 +1,28 @@
// Copyright (C) 2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "snippets/edge_replace.hpp"
#include "common_test_utils/test_constants.hpp"
namespace ov {
namespace test {
namespace snippets {
namespace {
std::vector<ov::PartialShape> input_shapes{{4}};
INSTANTIATE_TEST_SUITE_P(smoke_Snippets_edge_replace, EdgeReplace,
::testing::Combine(
::testing::ValuesIn(input_shapes),
::testing::Values(ov::element::f32),
::testing::Values(3),
::testing::Values(1),
::testing::Values(CommonTestUtils::DEVICE_CPU)),
EdgeReplace::getTestCaseName);
} // namespace
} // namespace snippets
} // namespace test
} // namespace ov
@@ -0,0 +1,32 @@
// Copyright (C) 2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include "shared_test_classes/base/snippets_test_utils.hpp"
namespace ov {
namespace test {
namespace snippets {
typedef std::tuple<
ov::PartialShape, // Input Shape
ov::element::Type, // Element type
size_t, // Expected num nodes
size_t, // Expected num subgraphs
std::string // Target Device
> EdgeReplaceParams;
class EdgeReplace : public testing::WithParamInterface<ov::test::snippets::EdgeReplaceParams>,
virtual public ov::test::SnippetsTestsCommon {
public:
static std::string getTestCaseName(testing::TestParamInfo<ov::test::snippets::EdgeReplaceParams> obj);
protected:
void SetUp() override;
};
} // namespace snippets
} // namespace test
} // namespace ov
@@ -0,0 +1,49 @@
// Copyright (C) 2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "common_test_utils/common_utils.hpp"
#include "snippets/edge_replace.hpp"
#include "subgraph_simple.hpp"
#include "ngraph_functions/builders.hpp"
#include "functional_test_utils/skip_tests_config.hpp"
namespace ov {
namespace test {
namespace snippets {
std::string EdgeReplace::getTestCaseName(testing::TestParamInfo<ov::test::snippets::EdgeReplaceParams> obj) {
ov::PartialShape inputShape;
ov::element::Type type;
std::string targetDevice;
size_t num_nodes, num_subgraphs;
std::tie(inputShape, type, num_nodes, num_subgraphs, targetDevice) = obj.param;
std::ostringstream result;
result << "IS=" << CommonTestUtils::partialShape2str({inputShape}) << "_";
result << "T=" << type << "_";
result << "#N=" << num_nodes << "_";
result << "#S=" << num_subgraphs << "_";
result << "targetDevice=" << targetDevice;
return result.str();
}
void EdgeReplace::SetUp() {
ov::PartialShape inputShape;
ov::element::Type type;
std::tie(inputShape, type, ref_num_nodes, ref_num_subgraphs, targetDevice) = this->GetParam();
init_input_shapes({{{inputShape}, {inputShape.get_shape()}}});
auto f = ov::test::snippets::EdgeReplaceFunction({inputShape});
function = f.getOriginal();
setInferenceType(type);
}
TEST_P(EdgeReplace, CompareWithRefImpl) {
run();
validateNumSubgraphs();
}
} // namespace snippets
} // namespace test
} // namespace ov
@@ -243,6 +243,21 @@ protected:
PartialShape m_target_shape;
};
/// graph use case to cover duplicated subgraphs edge elimination in such as in yolo-v3
// subgraph/node
// / |
// subgraph subgraph
// \ /
// eltwise node
class EdgeReplaceFunction : public SnippetsFunctionBase {
public:
explicit EdgeReplaceFunction(const std::vector<PartialShape>& inputShapes) : SnippetsFunctionBase(inputShapes) {
NGRAPH_CHECK(input_shapes.size() == 1, "Got invalid number of input shapes");
}
protected:
std::shared_ptr<ov::Model> initOriginal() const override;
};
} // namespace snippets
} // namespace test
} // namespace ov
@@ -318,6 +318,39 @@ std::shared_ptr<ov::Model> BroadcastSelectFunction::initOriginal() const {
return std::make_shared<Model>(NodeVector{select}, ParameterVector{data0, data1, data2});
}
std::shared_ptr<ov::Model> EdgeReplaceFunction::initOriginal() const {
auto input = std::make_shared<op::v0::Parameter>(ov::element::f32, input_shapes[0]);
const auto axis = ngraph::op::Constant::create(element::i64, Shape{}, {0});
// first parent and second parent have common inputs from output of split
auto split = std::make_shared<ov::op::v1::Split>(input, axis, 2);
auto mul_lhs = split->output(0);
auto mul_rhs = split->output(1);
// first parent subgraph in tokenization stage
const auto data0 = std::make_shared<ov::opset8::Constant>(ov::element::Type_t::f32, ov::Shape({1, 1, 1, 3, 2}),
std::vector<float>{0.0, 0.2, 0.4, 0.6, 0.8, 1.0});
const auto const_a4 = std::make_shared<ov::opset8::Constant>(ov::element::Type_t::f32, ov::Shape({2}), std::vector<float>{0.2, 0.1});
auto mul_a4 = std::make_shared<op::v1::Multiply>(mul_rhs, const_a4);
auto add_a1 = std::make_shared<op::v1::Add>(mul_a4, data0);
auto mul_a5 = std::make_shared<op::v1::Multiply>(add_a1, mul_lhs);
// second parent subgraph in tokenization stage
const auto data1 = std::make_shared<ov::opset8::Constant>(ov::element::Type_t::f32, ov::Shape({1, 1, 1, 3, 2}),
std::vector<float>{0.1, 0.3, 0.5, 0.7, 0.9, 1.0});
auto mul_a1 = std::make_shared<op::v1::Multiply>(data1, mul_lhs);
const auto const_a2 = std::make_shared<ov::opset8::Constant>(ov::element::Type_t::f32, ov::Shape({2}), std::vector<float>{0.2, 0.4});
auto mul_a2 = std::make_shared<op::v1::Multiply>(mul_a1, const_a2);
const auto const_a3 = std::make_shared<ov::opset8::Constant>(ov::element::Type_t::f32, ov::Shape({2}), std::vector<float>{0.3, 0.1});
auto mul_a3 = std::make_shared<op::v1::Multiply>(mul_a2, const_a3);
auto add_a3 = std::make_shared<op::v1::Add>(mul_a5, mul_a3);
auto add_a2 = std::make_shared<op::v1::Add>(mul_a5, mul_a2);
auto concat = std::make_shared<op::v0::Concat>(ngraph::OutputVector{add_a3, add_a2}, 0);
return std::make_shared<Model>(NodeVector{concat}, ParameterVector{input});
}
} // namespace snippets
} // namespace test
} // namespace ov