Shape as i32 value (#9343)

* Shape as value propagation in i32

* Comments adressed

* code style

* Modifies test to cover both Numpy and Bidirectional broadcasting

* MYR dynamic tests: made cases truly dynamic. Due to better shape inference it turned out that test cases were actually static.

* Deleting static shape test cases
This commit is contained in:
Evgenya Stepyreva authored and GitHub committed 2021-12-23 16:17:34 +03:00
1 parent 3ee5bcaf4d
commit 3a61afa2d3
4 files changed
+69 -34

No files matched your search

+25 -19
View File
@@ -68,17 +68,16 @@ std::pair<bool, AxisSet> op::v3::Broadcast::get_broadcast_axes() const {
namespace {
ov::PartialShape get_result_shape_bidirectional(const Node* this_ptr,
const ov::PartialShape& arg_shape,
ov::Shape& target_shape) {
if (arg_shape.rank().is_dynamic()) {
ov::PartialShape arg_shape,
ov::PartialShape target_shape) {
if (arg_shape.rank().is_dynamic() || target_shape.rank().is_dynamic()) {
return ov::PartialShape::dynamic();
}
auto arg_shape_vec = static_cast<std::vector<Dimension>>(arg_shape);
ov::PartialShape result_shape;
// Add left padding to shorter target or argument shape
const auto target_padded_rank = std::max(arg_shape_vec.size(), target_shape.size());
while (arg_shape_vec.size() < target_padded_rank) {
arg_shape_vec.insert(arg_shape_vec.begin(), 1);
const auto target_padded_rank = std::max(arg_shape.size(), target_shape.size());
while (arg_shape.size() < target_padded_rank) {
arg_shape.insert(arg_shape.begin(), 1);
}
while (target_shape.size() < target_padded_rank) {
target_shape.insert(target_shape.begin(), 1);
@@ -86,23 +85,30 @@ ov::PartialShape get_result_shape_bidirectional(const Node* this_ptr,
result_shape = target_shape;
for (size_t i = 0; i < target_shape.size(); ++i) {
if (arg_shape_vec[i].is_dynamic()) {
if (target_shape[i] == 1) {
result_shape[i] = Dimension::dynamic();
const auto& arg_dim = arg_shape[i];
const auto& target_dim = target_shape[i];
if (arg_dim.is_dynamic() || target_dim.is_dynamic()) {
if (target_dim == 1 || (arg_dim.is_static() && arg_dim != 1)) {
result_shape[i] = arg_dim;
} else if (arg_dim == 1 || (target_dim.is_static() && target_dim != 1)) {
result_shape[i] = target_dim;
} else {
result_shape[i] = target_shape[i];
result_shape[i] = Dimension(std::min(arg_dim.get_min_length(), target_dim.get_min_length()),
std::max(arg_dim.get_max_length(), target_dim.get_max_length()));
}
continue;
}
const size_t arg_shape_dim = arg_shape_vec[i].get_length();
const auto& arg_shape_dim = arg_shape[i].get_length();
const auto& target_shape_dim = target_shape[i].get_length();
NODE_VALIDATION_CHECK(this_ptr,
arg_shape_dim == 1 || target_shape[i] == 1 || arg_shape_dim == target_shape[i],
arg_shape_dim == 1 || target_shape[i] == 1 || arg_shape_dim == target_shape_dim,
"Broadcast incorrect target shape. Expecting either 1 or ",
arg_shape_dim,
". Got ",
target_shape[i]);
result_shape[i] = std::max(arg_shape_dim, target_shape[i]);
result_shape[i] = std::max(arg_shape_dim, target_shape_dim);
}
return result_shape;
}
@@ -112,7 +118,8 @@ bool op::v3::Broadcast::broadcast_evaluate(const HostTensorVector& outputs, cons
if (get_broadcast_spec().m_type == op::BroadcastType::BIDIRECTIONAL) {
auto arg_shape = inputs[0]->get_shape();
ov::Shape target_shape = op::util::BroadcastBase::get_target_shape(inputs[1]);
ov::PartialShape result_shape = get_result_shape_bidirectional(this, ov::PartialShape{arg_shape}, target_shape);
ov::PartialShape result_shape =
get_result_shape_bidirectional(this, ov::PartialShape{arg_shape}, ov::PartialShape{target_shape});
auto pair_broadcast_axes = get_broadcast_axes_bidirectional(arg_shape, result_shape.to_shape());
return op::util::BroadcastBase::evaluate_broadcast(inputs[0],
outputs[0],
@@ -141,9 +148,8 @@ void op::v3::Broadcast::validate_and_infer_types() {
if (get_input_partial_shape(0).rank().is_static() && get_input_partial_shape(1).is_static()) {
auto arg_shape = get_input_partial_shape(0);
const auto shape_constant = get_constant_from_source(input_value(1));
if (shape_constant) {
auto target_shape = shape_constant->get_shape_val();
PartialShape target_shape;
if (evaluate_as_partial_shape(input_value(1), target_shape)) {
result_shape = get_result_shape_bidirectional(this, arg_shape, target_shape);
}
}
+11 -4
View File
@@ -1287,13 +1287,20 @@ bool ov::evaluate_as_partial_shape(const Output<Node>& output, PartialShape& psh
std::tie(lb, ub) = evaluate_both_bounds(output);
bool shape_defined = false;
if (lb && ub) {
const auto lower_bound = std::make_shared<op::v0::Constant>(lb)->cast_vector<int64_t>();
const auto upper_bound = std::make_shared<op::v0::Constant>(ub)->cast_vector<int64_t>();
auto lower_bound = std::make_shared<op::v0::Constant>(lb)->cast_vector<int64_t>();
auto upper_bound = std::make_shared<op::v0::Constant>(ub)->cast_vector<int64_t>();
NGRAPH_CHECK(lower_bound.size() == upper_bound.size());
vector<Dimension> resulting_pshape(lower_bound.size());
for (size_t i = 0; i < lower_bound.size(); ++i) {
NGRAPH_CHECK(lower_bound[i] >= 0 && upper_bound[i] >= 0);
resulting_pshape[i] = {lower_bound[i], upper_bound[i]};
auto low = lower_bound[i], up = upper_bound[i];
NGRAPH_CHECK(low >= 0 && up >= 0);
if (output.get_element_type() == element::i32 && low != up) {
if (up == std::numeric_limits<std::int32_t>::max())
up = std::numeric_limits<std::int64_t>::max();
if (low == std::numeric_limits<std::int32_t>::max())
low = std::numeric_limits<std::int64_t>::max();
}
resulting_pshape[i] = {low, up};
}
pshape = PartialShape(resulting_pshape);
shape_defined = true;
+33 -7
View File
@@ -51,9 +51,9 @@ TYPED_TEST_P(BroadcastTests, broadcast_target_shape_as_concat_with_constants) {
auto axes_mapping = op::Constant::create<int64_t>(element::i64, Shape{1}, {1});
auto bc = make_shared<TypeParam>(param, target_shape, axes_mapping, "NONE");
ASSERT_TRUE(bc->get_output_partial_shape(0).rank().is_static());
ASSERT_TRUE(bc->get_output_partial_shape(0).rank().same_scheme(Rank{4}));
ASSERT_EQ(bc->get_output_partial_shape(0).rank(), (Rank{4}));
ASSERT_TRUE(bc->get_output_partial_shape(0).is_static());
ASSERT_TRUE(bc->get_output_partial_shape(0).same_scheme(PartialShape{1, 16, 50, 50}));
ASSERT_EQ(bc->get_output_partial_shape(0), (PartialShape{1, 16, 50, 50}));
}
TYPED_TEST_P(BroadcastTests, broadcast_target_shape_as_concat_with_node) {
@@ -71,7 +71,7 @@ TYPED_TEST_P(BroadcastTests, broadcast_target_shape_as_concat_with_node) {
auto axes_mapping = op::Constant::create<int64_t>(element::i64, Shape{1}, {1});
auto bc = make_shared<TypeParam>(param, target_shape, axes_mapping, "NONE");
ASSERT_TRUE(bc->get_output_partial_shape(0).rank().is_static());
ASSERT_TRUE(bc->get_output_partial_shape(0).rank().same_scheme(Rank{4}));
ASSERT_EQ(bc->get_output_partial_shape(0).rank(), (Rank{4}));
ASSERT_TRUE(bc->get_output_partial_shape(0).is_dynamic());
ASSERT_EQ(bc->get_output_partial_shape(0), PartialShape({Dimension::dynamic(), 16, 50, 50}));
}
@@ -738,7 +738,7 @@ TEST(type_prop, broadcast_v3_output_rank_not_deduced) {
const auto broadcast_v3 = make_shared<op::v3::Broadcast>(arg, shape, broadcast_spec);
ASSERT_TRUE(broadcast_v3->get_output_partial_shape(0).same_scheme(PartialShape::dynamic()));
ASSERT_EQ(broadcast_v3->get_output_partial_shape(0), (PartialShape::dynamic()));
}
TEST(type_prop, broadcast_v3_output_rank_deduced_from_arg) {
@@ -747,7 +747,7 @@ TEST(type_prop, broadcast_v3_output_rank_deduced_from_arg) {
const auto broadcast_spec = op::BroadcastType::BIDIRECTIONAL;
const auto broadcast_v3 = make_shared<op::v3::Broadcast>(arg, shape, broadcast_spec);
ASSERT_TRUE(broadcast_v3->get_output_partial_shape(0).same_scheme(PartialShape{Dimension::dynamic(), 8, 6, 4}));
ASSERT_EQ(broadcast_v3->get_output_partial_shape(0), (PartialShape{Dimension::dynamic(), 8, 6, 4}));
}
TEST(type_prop, broadcast_v3_output_rank_deduced_from_new_shape_input) {
@@ -758,8 +758,8 @@ TEST(type_prop, broadcast_v3_output_rank_deduced_from_new_shape_input) {
const auto broadcast_v3 = make_shared<op::v3::Broadcast>(arg, shape, broadcast_spec);
ASSERT_TRUE(broadcast_v3->get_output_partial_shape(0).rank().is_static());
ASSERT_EQ(broadcast_v3->get_output_partial_shape(0).rank().get_length(), 5);
ASSERT_TRUE(broadcast_v3->get_output_partial_shape(0).same_scheme(
PartialShape{8, 6, Dimension::dynamic(), 5, Dimension::dynamic()}));
ASSERT_EQ(broadcast_v3->get_output_partial_shape(0),
(PartialShape{8, 6, Dimension::dynamic(), 5, Dimension::dynamic()}));
}
TEST(type_prop, broadcast_v3_bidirectional_dynamic_input) {
@@ -859,3 +859,29 @@ TEST(type_prop, broadcast_v3_bidirectional_partially_dynamic_input) {
ASSERT_EQ(bc->get_output_partial_shape(0).rank().get_length(), 4);
ASSERT_EQ(bc->get_output_partial_shape(0), (PartialShape{1, Dimension::dynamic(), 50, 50}));
}
TEST(type_prop, broadcast_i32_shape_value) {
const auto arg = make_shared<op::Parameter>(element::f32, PartialShape({5, -1}));
const auto shape = make_shared<op::v3::ShapeOf>(arg, element::i64);
const auto broadcast_spec = op::BroadcastType::BIDIRECTIONAL;
const auto broadcast_v3 = make_shared<op::v3::Broadcast>(arg, shape, broadcast_spec);
ASSERT_EQ(broadcast_v3->get_output_partial_shape(0), PartialShape({5, -1}));
// shape type resetting
shape->set_output_type(element::i32);
arg->revalidate_and_infer_types();
shape->revalidate_and_infer_types();
broadcast_v3->revalidate_and_infer_types();
ASSERT_EQ(broadcast_v3->get_output_partial_shape(0), PartialShape({5, -1}));
// broadcast type resetting
broadcast_v3->set_broadcast_spec(op::BroadcastType::NUMPY);
arg->revalidate_and_infer_types();
shape->revalidate_and_infer_types();
broadcast_v3->revalidate_and_infer_types();
ASSERT_EQ(broadcast_v3->get_output_partial_shape(0), PartialShape({5, -1}));
}
@@ -125,11 +125,7 @@ TEST_P(NonZero_Broadcast, CompareWithReference) {
std::vector<BroadcastInputParams> broadcastTestParams = {
{ DataShapeWithUpperBound{ {1, 1, 4}, {} }, DataShapeWithUpperBound{ {200, 2, 4}, {300, 2, 4} }, {} },
{ DataShapeWithUpperBound{ {15, 14}, {} }, DataShapeWithUpperBound{ {2, 16, 1, 14}, {2, 16, 15, 14} }, {} },
{ DataShapeWithUpperBound{ {15, 1}, {} }, DataShapeWithUpperBound{ {1, 16, 15, 14}, {2, 16, 15, 14} }, {} },
{ DataShapeWithUpperBound{ {2, 16, 15, 14}, {} }, DataShapeWithUpperBound{ {1, 15, 14}, {16, 15, 14} }, {} },
{ DataShapeWithUpperBound{ {2, 16, 15, 14}, {} }, DataShapeWithUpperBound{ {16, 1, 1}, {16, 1, 14}}, {} },
{ DataShapeWithUpperBound{ {16, 15, 1}, {} }, DataShapeWithUpperBound{ {2, 1, 15, 14}, {2, 16, 15, 14} }, {} },
{ DataShapeWithUpperBound{ {142, 1, 1, 64}, {300, 1, 1, 64} }, DataShapeWithUpperBound { {142, 3, 64, 64}, {300, 3, 64, 64} }, {} },
{ DataShapeWithUpperBound{ {1}, {} }, DataShapeWithUpperBound{ {1, 800}, {1, 1000} }, {0} },
{ DataShapeWithUpperBound{ {4}, {} }, DataShapeWithUpperBound{ {100, 4}, {1000, 4} }, {1} },