[Core] Assure TensorVector comparison uniqueness (#16232)

* Assure TensorVector comparison uniqueness

* Add test

* Make the flow clear
This commit is contained in:
Tomasz Jankowski
2023-03-21 13:58:34 +01:00
committed by GitHub
parent d402b6ed3e
commit 0893efe073
2 changed files with 49 additions and 12 deletions

View File

@@ -179,14 +179,26 @@ ov::Tensor or_tensor(const ov::Tensor& lhs, const ov::Tensor& rhs) {
}
struct TensorVectorCmp {
// Comparing Tensor vectors as numbers composed with pointers as digits.
// Indexed loop used to preserve order of comparison.
bool operator()(const ov::TensorVector& lhs, const ov::TensorVector& rhs) const {
auto rhs_it = rhs.begin();
return std::any_of(lhs.begin(), lhs.end(), [&rhs_it](const ov::Tensor& lhs) {
bool is_less =
(lhs && *rhs_it) ? lhs.data() < rhs_it->data() : static_cast<bool>(lhs) < static_cast<bool>(*rhs_it);
++rhs_it;
return is_less;
});
const auto lhs_size = lhs.size();
const auto rhs_size = rhs.size();
if (lhs_size < rhs_size)
return true;
if (lhs_size > rhs_size)
return false;
for (size_t i = 0; i < lhs_size; ++i) {
if (lhs[i].data() < rhs[i].data())
return true;
if (lhs[i].data() > rhs[i].data())
return false;
}
// if all equals
return false;
}
};
@@ -281,17 +293,14 @@ bool ov::interval_bound_evaluator(const Node* node,
auto low_1 = ov::evaluate_lower_bound(node->get_input_source_output(1));
auto up_0 = ov::evaluate_upper_bound(node->get_input_source_output(0));
auto up_1 = ov::evaluate_upper_bound(node->get_input_source_output(1));
if (!low_0 || !low_1 || !up_0 || !up_1)
return false;
std::set<TensorVector, TensorVectorCmp> input_variants = {{low_0, low_1},
{low_0, up_1},
{up_0, low_1},
{up_0, up_1}};
for (const auto& variant_of_input_vector : input_variants)
for (const auto& input_tensor : variant_of_input_vector)
if (!input_tensor)
return false;
if (input_variants.size() == 1)
return node->evaluate(upper_output_values, *input_variants.begin()) &&
node->evaluate(lower_output_values, *input_variants.begin());

View File

@@ -51,3 +51,31 @@ TEST_F(EvaluateBoundTest, no_exception_when_node_has_output_with_dynamic_element
EXPECT_NO_THROW(evaluate_both_bounds(fn_op));
}
using BoundEvaluatorTest = ::testing::Test;
TEST(BoundEvaluatorTest, no_exception_on_single_bound) {
constexpr auto et = element::i32;
const auto s = Shape{1, 1};
const auto a = std::make_shared<Parameter>(et, PartialShape{s});
const auto b = Constant::create(et, s, {1});
const auto sub = std::make_shared<Subtract>(a, b);
int32_t a_l[1] = {1};
a->get_output_tensor(0).set_lower_value(Tensor{et, s, a_l});
int32_t o_[1] = {INT32_MIN}; // initial value of output tensor is not needed, it's set to check whether changed
TensorVector output{{et, s, o_}};
// evaluations won't be performed due to missing upper bound tensor of parameter a
ASSERT_NO_THROW(sub->evaluate_lower(output));
EXPECT_EQ(o_[0], INT32_MIN);
ASSERT_NO_THROW(sub->evaluate_upper(output));
EXPECT_EQ(o_[0], INT32_MIN);
int32_t a_u[1] = {11};
a->get_output_tensor(0).set_upper_value(Tensor{et, s, a_u});
// now both bounds of sub node can be calculated
ASSERT_NO_THROW(sub->evaluate_lower(output));
EXPECT_EQ(o_[0], 0);
ASSERT_NO_THROW(sub->evaluate_upper(output));
EXPECT_EQ(o_[0], 10);
}