Fix MatMul SmartReshape in case of 1D input (#24701)
### Details: Handled a case when "Other" input to MatMul is 1D ### Tickets: - *CVS-141638*
This commit is contained in:
parent
65c3b1783c
commit
c5bd13a63c
|
|
@ -36,7 +36,12 @@ bool relax_hc_reshape_followed_by_matmul(const ov::pass::pattern::PatternValueMa
|
||||||
// avoiding loop creation
|
// avoiding loop creation
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const auto idx = reshape_is_A_input ? (matmul->get_transpose_b() ? -1 : -2) : (matmul->get_transpose_a() ? -2 : -1);
|
bool is_1d = ov::pass::pattern::rank_equals(1)(shape_source);
|
||||||
|
int64_t idx = -1;
|
||||||
|
if (!is_1d) {
|
||||||
|
idx = reshape_is_A_input ? (matmul->get_transpose_b() ? -1 : -2) : (matmul->get_transpose_a() ? -2 : -1);
|
||||||
|
}
|
||||||
|
|
||||||
const auto in_C_0 = std::make_shared<ov::op::v3::ShapeOf>(shape_source);
|
const auto in_C_0 = std::make_shared<ov::op::v3::ShapeOf>(shape_source);
|
||||||
const auto in_C_1 = ov::op::v0::Constant::create(ov::element::i64, {1}, {idx});
|
const auto in_C_1 = ov::op::v0::Constant::create(ov::element::i64, {1}, {idx});
|
||||||
const auto in_C_2 = ov::op::v0::Constant::create(ov::element::i64, {}, {0});
|
const auto in_C_2 = ov::op::v0::Constant::create(ov::element::i64, {}, {0});
|
||||||
|
|
@ -53,7 +58,6 @@ bool relax_hc_reshape_followed_by_matmul(const ov::pass::pattern::PatternValueMa
|
||||||
|
|
||||||
auto reshape_input = pattern_to_output.at(reshape_label).get_node_shared_ptr()->input(1);
|
auto reshape_input = pattern_to_output.at(reshape_label).get_node_shared_ptr()->input(1);
|
||||||
reshape_input.replace_source_output(new_reshape_pattern);
|
reshape_input.replace_source_output(new_reshape_pattern);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -61,7 +65,7 @@ bool relax_hc_reshape_followed_by_matmul(const ov::pass::pattern::PatternValueMa
|
||||||
|
|
||||||
ov::pass::ReshapeAMatMul::ReshapeAMatMul() {
|
ov::pass::ReshapeAMatMul::ReshapeAMatMul() {
|
||||||
MATCHER_SCOPE(ReshapeAMatMul);
|
MATCHER_SCOPE(ReshapeAMatMul);
|
||||||
auto other_input_label = pattern::any_input();
|
auto other_input_label = pattern::any_input(ov::pass::pattern::has_static_rank());
|
||||||
auto reshape_input_label = pattern::any_input();
|
auto reshape_input_label = pattern::any_input();
|
||||||
auto reshape_pattern_label = pattern::any_input();
|
auto reshape_pattern_label = pattern::any_input();
|
||||||
auto reshape_predicate = [](ov::Output<ov::Node> output) -> bool {
|
auto reshape_predicate = [](ov::Output<ov::Node> output) -> bool {
|
||||||
|
|
@ -86,7 +90,7 @@ ov::pass::ReshapeAMatMul::ReshapeAMatMul() {
|
||||||
|
|
||||||
ov::pass::ReshapeBMatMul::ReshapeBMatMul() {
|
ov::pass::ReshapeBMatMul::ReshapeBMatMul() {
|
||||||
MATCHER_SCOPE(ReshapeBMatMul);
|
MATCHER_SCOPE(ReshapeBMatMul);
|
||||||
auto other_input_label = pattern::any_input();
|
auto other_input_label = pattern::any_input(ov::pass::pattern::has_static_rank());
|
||||||
auto reshape_input_label = pattern::any_input();
|
auto reshape_input_label = pattern::any_input();
|
||||||
auto reshape_pattern_label = pattern::any_input();
|
auto reshape_pattern_label = pattern::any_input();
|
||||||
auto reshape_predicate = [](ov::Output<ov::Node> output) -> bool {
|
auto reshape_predicate = [](ov::Output<ov::Node> output) -> bool {
|
||||||
|
|
|
||||||
|
|
@ -378,6 +378,64 @@ TEST_F(TransformationTestsF, SmartReshapeReshapeAMatMulSeveralConsumers) {
|
||||||
manager.register_pass<ov::pass::ReshapeAMatMul>();
|
manager.register_pass<ov::pass::ReshapeAMatMul>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(TransformationTestsF, SmartReshapeReshapeA_1DOtherInput) {
|
||||||
|
{
|
||||||
|
auto input_to_reshape = std::make_shared<ov::op::v0::Parameter>(ov::element::f32, ov::Shape{3, 2, 3});
|
||||||
|
auto reshape_const = ov::op::v0::Constant::create(ov::element::i32, {2}, {3, 6});
|
||||||
|
auto reshape = std::make_shared<ov::op::v1::Reshape>(input_to_reshape, reshape_const, false);
|
||||||
|
|
||||||
|
auto other_input = std::make_shared<ov::op::v0::Parameter>(ov::element::f32, ov::Shape{6});
|
||||||
|
auto matmul = std::make_shared<ov::op::v0::MatMul>(reshape, other_input);
|
||||||
|
model = std::make_shared<ov::Model>(ov::NodeVector{matmul}, ov::ParameterVector{input_to_reshape, other_input});
|
||||||
|
manager.register_pass<ov::pass::ReshapeAMatMul>();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto input_to_reshape = std::make_shared<ov::op::v0::Parameter>(ov::element::f32, ov::Shape{3, 2, 3});
|
||||||
|
auto other_input = std::make_shared<ov::op::v0::Parameter>(ov::element::f32, ov::Shape{6});
|
||||||
|
const auto in_C_0 = std::make_shared<ov::op::v3::ShapeOf>(other_input);
|
||||||
|
const auto in_C_1 = ov::op::v0::Constant::create(ov::element::i64, {1}, {-1});
|
||||||
|
const auto in_C_2 = ov::op::v0::Constant::create(ov::element::i64, {}, {0});
|
||||||
|
const auto C = std::make_shared<ov::op::v8::Gather>(in_C_0, in_C_1, in_C_2);
|
||||||
|
|
||||||
|
const auto N = ov::op::v0::Constant::create(ov::element::i64, {1}, {-1});
|
||||||
|
const auto new_reshape_pattern = std::make_shared<ov::op::v0::Concat>(ov::OutputVector{N, C}, 0);
|
||||||
|
auto reshape = std::make_shared<ov::op::v1::Reshape>(input_to_reshape, new_reshape_pattern, false);
|
||||||
|
|
||||||
|
auto matmul = std::make_shared<ov::op::v0::MatMul>(reshape, other_input);
|
||||||
|
model_ref =
|
||||||
|
std::make_shared<ov::Model>(ov::NodeVector{matmul}, ov::ParameterVector{input_to_reshape, other_input});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TransformationTestsF, SmartReshapeReshapeB_1DOtherInput) {
|
||||||
|
{
|
||||||
|
auto input_to_reshape = std::make_shared<ov::op::v0::Parameter>(ov::element::f32, ov::Shape{3, 2, 3});
|
||||||
|
auto reshape_const = ov::op::v0::Constant::create(ov::element::i32, {2}, {3, 6});
|
||||||
|
auto reshape = std::make_shared<ov::op::v1::Reshape>(input_to_reshape, reshape_const, false);
|
||||||
|
|
||||||
|
auto other_input = std::make_shared<ov::op::v0::Parameter>(ov::element::f32, ov::Shape{3});
|
||||||
|
auto matmul = std::make_shared<ov::op::v0::MatMul>(other_input, reshape);
|
||||||
|
model = std::make_shared<ov::Model>(ov::NodeVector{matmul}, ov::ParameterVector{input_to_reshape, other_input});
|
||||||
|
manager.register_pass<ov::pass::ReshapeBMatMul>();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto input_to_reshape = std::make_shared<ov::op::v0::Parameter>(ov::element::f32, ov::Shape{3, 2, 3});
|
||||||
|
auto other_input = std::make_shared<ov::op::v0::Parameter>(ov::element::f32, ov::Shape{3});
|
||||||
|
const auto in_C_0 = std::make_shared<ov::op::v3::ShapeOf>(other_input);
|
||||||
|
const auto in_C_1 = ov::op::v0::Constant::create(ov::element::i64, {1}, {-1});
|
||||||
|
const auto in_C_2 = ov::op::v0::Constant::create(ov::element::i64, {}, {0});
|
||||||
|
const auto C = std::make_shared<ov::op::v8::Gather>(in_C_0, in_C_1, in_C_2);
|
||||||
|
|
||||||
|
const auto N = ov::op::v0::Constant::create(ov::element::i64, {1}, {-1});
|
||||||
|
const auto new_reshape_pattern = std::make_shared<ov::op::v0::Concat>(ov::OutputVector{C, N}, 0);
|
||||||
|
auto reshape = std::make_shared<ov::op::v1::Reshape>(input_to_reshape, new_reshape_pattern, false);
|
||||||
|
|
||||||
|
auto matmul = std::make_shared<ov::op::v0::MatMul>(other_input, reshape);
|
||||||
|
model_ref =
|
||||||
|
std::make_shared<ov::Model>(ov::NodeVector{matmul}, ov::ParameterVector{input_to_reshape, other_input});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(TransformationTestsF, SmartReshapeReshapeBMatMulSeveralConsumers) {
|
TEST_F(TransformationTestsF, SmartReshapeReshapeBMatMulSeveralConsumers) {
|
||||||
// Reshape has 2 consumers: matmul and reduce.
|
// Reshape has 2 consumers: matmul and reduce.
|
||||||
// Since reshape movement leads to loop creation (circular dependencies), the transformation can't be applied
|
// Since reshape movement leads to loop creation (circular dependencies), the transformation can't be applied
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue