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:
1 parent
3ee5bcaf4d
commit
3a61afa2d3
4 files changed
+69
-34
No files matched your search
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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} },
|
||||
|
||||
Reference in new issue
Block a user