[LPT][Transformations] Dynamic shapes support: functional issues fixes (#7159)

* [LPT] ReshapeTransformation fix

* [LPT] FQDequantization::empty() fix

* [LPT] ConcatTransformation fix

* [LPT] MVNTransformation quick refactoring

* [TESTS] AddTransformation functional tests: removed unused param

* [nGraph] TypeRelaxed::evaluate

* [nGraph] Tile fix

* [nGraph] Intervals addition: overflow handling

* [LPT] MultiplyTransformation: canBeTransformed fix

* [TESTS] TypeRelaxed::evaluate: added test

* [LPT] MVNTransformation compilation error fix

* TypeRelaxed: evaluate fix

* macos fix

* TypeRelaxed::evaluate: postreview fixes

* ConcatTransformation: postreview fix
This commit is contained in:
Vladislav Golubev authored and GitHub committed 2021-09-09 13:05:32 +03:00
1 parent f5089912e4
commit f5767d4a5b
12 files changed
+231 -51

No files matched your search

@@ -182,18 +182,36 @@ bool ConcatTransformation::canBeTransformed(const TransformationContext& context
return false;
}
const auto axis = concat->get_axis();
const auto outPShape = concat->get_output_partial_shape(0);
const size_t normalizedAxis = ngraph::normalize_axis(concat->get_friendly_name(), axis, outPShape.rank());
const auto& axis = concat->get_axis();
const auto& outPShape = concat->get_output_partial_shape(0);
const auto& outRank = outPShape.rank();
if (outRank.is_dynamic()) {
return false;
}
const size_t normalizedAxis = ngraph::normalize_axis(concat->get_friendly_name(), axis, outRank);
if (normalizedAxis != 1ul) {
return false;
}
if (outPShape.rank().is_dynamic() || outPShape[normalizedAxis].is_dynamic()) {
if (outPShape[normalizedAxis].is_dynamic()) {
return false;
}
auto checkConstShape = [&normalizedAxis, &outRank](const std::shared_ptr<opset1::Constant>& constant) {
const size_t rankValue = outRank.get_length();
Shape constantShape = constant->get_shape();
while (constantShape.size() < rankValue) {
constantShape.insert(constantShape.begin(), 1ul);
}
const auto dqDimensionsCount = std::count_if(constantShape.begin(), constantShape.end(), [](size_t elem) { return elem > 1; });
const bool dqOnlyByConcatAxis = (dqDimensionsCount == 0) || (dqDimensionsCount == 1 && constantShape[normalizedAxis] != 1ul);
return dqOnlyByConcatAxis;
};
element::Type precision;
for (size_t i = 0ul; i < concat->get_input_size(); i++) {
const FakeQuantizeDequantization dequantization = NetworkHelper::getDequantization(concat, i);
@@ -201,6 +219,11 @@ bool ConcatTransformation::canBeTransformed(const TransformationContext& context
return false;
}
if (((dequantization.subtract != nullptr) && (!checkConstShape(dequantization.subtractConstant))) ||
((dequantization.multiply != nullptr) && (!checkConstShape(dequantization.multiplyConstant)))) {
return false;
}
if (precision == element::undefined) {
precision = dequantization.data.get_element_type();
} else if (precision != dequantization.data.get_element_type()) {
@@ -34,7 +34,7 @@ FakeQuantizeDequantization::FakeQuantizeDequantization(
}
bool FakeQuantizeDequantization::empty() const {
return (convert == nullptr) && (subtract == nullptr) && (multiply == nullptr);
return (subtract == nullptr) && (multiply == nullptr);
}
bool FakeQuantizeDequantization::multiplyHasZeroOrDenormal() const {
@@ -159,17 +159,17 @@ bool MultiplyTransformation::canBeTransformed(const TransformationContext& conte
FakeQuantizeDequantization dequantization1 = pass::low_precision::NetworkHelper::getDequantization(layer, 0ul);
FakeQuantizeDequantization dequantization2 = pass::low_precision::NetworkHelper::getDequantization(layer, 1ul);
if ((dequantization1.data.get_node() == nullptr) ||
(dequantization1.empty() && !ov::is_type<opset1::Constant>(dequantization1.data.get_node_shared_ptr()) &&
!ov::is_type<opset1::Constant>(dequantization2.data.get_node_shared_ptr()))) {
if (dequantization1.data.get_node() == nullptr || dequantization2.data.get_node() == nullptr) {
return false;
}
if ((dequantization2.data.get_node() == nullptr) ||
(dequantization2.empty() && !ov::is_type<opset1::Constant>(dequantization2.data.get_node_shared_ptr()) &&
!ov::is_type<opset1::Constant>(dequantization1.data.get_node_shared_ptr()))) {
const bool nonConstantData = !ov::is_type<opset1::Constant>(dequantization1.data.get_node_shared_ptr()) &&
!ov::is_type<opset1::Constant>(dequantization2.data.get_node_shared_ptr());
if (((dequantization1.empty() || dequantization2.empty()) && nonConstantData)) {
return false;
}
return EltwiseBaseTransformation::canBeTransformed(context, layer);
}
@@ -78,8 +78,6 @@ bool MVNTransformation::canBeTransformed(const TransformationContext& context, s
}
}
bool isScalarScales = NetworkHelper::isScalarLike(dequantization.multiplyConstant);
AxisSet reduction_axes;
if (ov::is_type<op::MVN>(mvn)) {
reduction_axes = ov::as_type_ptr<op::MVN>(mvn)->get_reduction_axes();
@@ -104,6 +102,7 @@ bool MVNTransformation::canBeTransformed(const TransformationContext& context, s
}
}
bool isScalarScales = NetworkHelper::isScalarLike(dequantization.multiplyConstant);
return perTensor && isScalarScales;
}
@@ -127,9 +126,9 @@ bool MVNTransformation::transform(TransformationContext &context, ngraph::patter
FakeQuantizeDequantization dequantization = NetworkHelper::getDequantization(mvn);
const auto scalesConst = dequantization.multiplyConstant;
const auto type = scalesConst->get_element_type();
auto newScalesConst = dequantization.multiplyConstant;
const auto type = scalesConst->get_output_element_type(0);
auto newScalesConst = scalesConst;
if (normalizeVariance) {
switch (type) {
case ngraph::element::Type_t::f16: {
@@ -145,6 +144,7 @@ bool MVNTransformation::transform(TransformationContext &context, ngraph::patter
}
}
}
std::shared_ptr<Node> newMVN;
if (ov::is_type<op::MVN>(mvn)) {
newMVN = mvn->copy_with_new_inputs({dequantization.data});
@@ -83,7 +83,7 @@ void reshapeDequantizationConstant(const std::shared_ptr<opset1::Reshape>& resha
Shape newOperationConstantBroadcastedShape = constant->get_shape();
// add dimensions to broadcast values
if (newOperationConstantBroadcastedShape.size() == 2ul) {
newOperationConstantBroadcastedShape.push_back(dimensionsToBroadcast);
newOperationConstantBroadcastedShape[0] = dimensionsToBroadcast;
} else {
newOperationConstantBroadcastedShape[2] = dimensionsToBroadcast;
}
@@ -11,6 +11,7 @@
#include <transformations_visibility.hpp>
#include <ngraph/op/convert.hpp>
#include "ngraph/op/op.hpp"
namespace ngraph {
@@ -84,6 +85,7 @@ protected:
// to infer output data types
element::TypeVector m_input_data_types;
element::TypeVector m_output_data_types;
element::TypeVector m_original_output_data_types;
};
/// Set another type for a specified output for the period of time when an instance of the class exists.
@@ -161,6 +163,7 @@ public:
}
void validate_and_infer_types() override;
bool evaluate(const HostTensorVector& outputs, const HostTensorVector& inputs) const override;
std::shared_ptr<Node> clone_with_new_inputs(const OutputVector& new_args) const override;
@@ -170,6 +173,61 @@ private:
}
};
template <typename BaseOp>
bool TypeRelaxed<BaseOp>::evaluate(const HostTensorVector& outputs, const HostTensorVector& inputs) const {
std::shared_ptr<ngraph::op::v0::Convert> convert;
HostTensorVector casted_inputs(BaseOp::get_input_size());
for (size_t i = 0; i < BaseOp::get_input_size(); ++i) {
const auto expected_input_type = get_origin_input_type(i);
if (inputs[i]->get_element_type() == expected_input_type || expected_input_type == element::undefined) {
casted_inputs[i] = inputs[i];
} else {
if (convert == nullptr) {
convert = std::make_shared<ngraph::op::v0::Convert>();
}
convert->set_destination_type(expected_input_type);
casted_inputs[i] = std::make_shared<HostTensor>(expected_input_type, inputs[i]->get_shape());
if (!convert->evaluate({ casted_inputs[i] }, { inputs[i] })) {
return false;
}
}
}
HostTensorVector original_outputs(BaseOp::get_output_size());
for (size_t i = 0; i < BaseOp::get_output_size(); ++i) {
const auto expected_output_type = get_overridden_output_type(i);
if (expected_output_type == element::undefined || expected_output_type == m_original_output_data_types[i]) {
original_outputs[i] = outputs[i];
} else {
original_outputs[i] = std::make_shared<HostTensor>(m_original_output_data_types[i], BaseOp::get_output_partial_shape(i));
}
}
if (!BaseOp::evaluate(original_outputs, casted_inputs)) {
return false;
}
for (size_t i = 0; i < BaseOp::get_output_size(); ++i) {
const auto expected_output_type = get_overridden_output_type(i);
if (expected_output_type != element::undefined && original_outputs[i]->get_element_type() != expected_output_type) {
if (convert == nullptr) {
convert = std::make_shared<ngraph::op::v0::Convert>();
}
convert->set_destination_type(expected_output_type);
const auto casted_output = std::make_shared<HostTensor>(expected_output_type, original_outputs[i]->get_shape());
if (!convert->evaluate({ outputs[i] }, { original_outputs[i] })) {
return false;
}
}
}
return true;
}
template <typename BaseOp>
void TypeRelaxed<BaseOp>::validate_and_infer_types() {
// Remember all input data types
@@ -195,6 +253,14 @@ void TypeRelaxed<BaseOp>::validate_and_infer_types() {
BaseOp::get_input_tensor(i).set_tensor_type(old_input_types[i], BaseOp::get_input_partial_shape(i));
}
if (m_original_output_data_types.empty()) {
m_original_output_data_types = element::TypeVector(BaseOp::get_output_size());
}
// Save inferred output types
for (size_t i = 0; i < BaseOp::get_output_size(); ++i) {
m_original_output_data_types[i] = BaseOp::get_output_element_type(i);
}
// Override (some) output types
for (size_t i = 0; i < BaseOp::get_output_size(); ++i) {
@@ -62,7 +62,6 @@ public:
operationType(std::move(operationType)) {}
};
ngraph::element::Type precision;
bool broadcast;
int constInput;
TestTransformationParams params;
@@ -169,7 +168,6 @@ const std::vector<std::pair<ngraph::PartialShape, ngraph::PartialShape>> inputSh
const std::vector<AddTransformationTestValues> testValuesWithoutConstantBranches = {
// Multiply with zero on the first branch
{
ngraph::element::f32,
false,
-1,
LayerTransformation::createParamsU8I8(),
@@ -192,7 +190,6 @@ const std::vector<AddTransformationTestValues> testValuesWithoutConstantBranches
},
// Multiply with zero on the second branch
{
ngraph::element::f32,
false,
-1,
LayerTransformation::createParamsU8I8(),
@@ -245,7 +242,6 @@ const std::vector<AddTransformationTestValues> testValuesWithoutConstantBranches
// \ /
// Add
{
ngraph::element::f32,
false,
-1,
LayerTransformation::createParamsU8I8(),
@@ -298,7 +294,6 @@ const std::vector<AddTransformationTestValues> testValuesWithoutConstantBranches
// \ /
// Add
{
ngraph::element::f32,
false,
-1,
LayerTransformation::createParamsU8I8(),
@@ -328,7 +323,6 @@ const std::vector<AddTransformationTestValues> testValuesWithoutConstantBranches
""
},
{
ngraph::element::f32,
false,
-1,
LayerTransformation::createParamsU8I8(),
@@ -350,7 +344,6 @@ const std::vector<AddTransformationTestValues> testValuesWithoutConstantBranches
""
},
{
ngraph::element::f32,
false,
-1,
LayerTransformation::createParamsU8I8(),
@@ -372,7 +365,6 @@ const std::vector<AddTransformationTestValues> testValuesWithoutConstantBranches
""
},
{
ngraph::element::f32,
false,
-1,
LayerTransformation::createParamsU8I8(),
@@ -394,7 +386,6 @@ const std::vector<AddTransformationTestValues> testValuesWithoutConstantBranches
""
},
{
ngraph::element::f32,
false,
-1,
LayerTransformation::createParamsU8I8(),
@@ -419,7 +410,6 @@ const std::vector<AddTransformationTestValues> testValuesWithoutConstantBranches
// I8 + broadcast
{
ngraph::element::f32,
true,
-1,
LayerTransformation::createParamsU8I8(),
@@ -441,7 +431,6 @@ const std::vector<AddTransformationTestValues> testValuesWithoutConstantBranches
""
},
{
ngraph::element::f32,
true,
-1,
LayerTransformation::createParamsU8I8(),
@@ -463,7 +452,6 @@ const std::vector<AddTransformationTestValues> testValuesWithoutConstantBranches
""
},
{
ngraph::element::f32,
true,
-1,
LayerTransformation::createParamsU8I8(),
@@ -485,7 +473,6 @@ const std::vector<AddTransformationTestValues> testValuesWithoutConstantBranches
""
},
{
ngraph::element::f32,
true,
-1,
LayerTransformation::createParamsU8I8(),
@@ -507,7 +494,6 @@ const std::vector<AddTransformationTestValues> testValuesWithoutConstantBranches
""
},
{
ngraph::element::f32,
true,
-1,
LayerTransformation::createParamsU8I8(),
@@ -531,7 +517,6 @@ const std::vector<AddTransformationTestValues> testValuesWithoutConstantBranches
// convolution before FQ (choose that branch)
{
ngraph::element::f32,
false,
-1,
LayerTransformation::createParamsU8I8(),
@@ -554,7 +539,6 @@ const std::vector<AddTransformationTestValues> testValuesWithoutConstantBranches
},
// convolution with multiple consumers before FQ ( FP32 on other branch due to possible quantize fusing )
{
ngraph::element::f32,
false,
-1,
LayerTransformation::createParamsU8I8(),
@@ -577,7 +561,6 @@ const std::vector<AddTransformationTestValues> testValuesWithoutConstantBranches
},
// group convolution before FQ (choose that branch)
{
ngraph::element::f32,
false,
-1,
LayerTransformation::createParamsU8I8(),
@@ -645,7 +628,6 @@ const std::vector<AddTransformationTestValues> testValuesWithFirstConstantBranch
// \ /
// Multiply
{
ngraph::element::f32,
false,
0,
LayerTransformation::createParamsU8I8(),
@@ -722,7 +704,6 @@ const std::vector<AddTransformationTestValues> testValuesWithSecondConstantBranc
// \ /
// Multiply
{
ngraph::element::f32,
false,
1,
LayerTransformation::createParamsU8I8(),
@@ -772,7 +753,6 @@ const std::vector<std::pair<ngraph::PartialShape, ngraph::PartialShape>> inputSh
const std::vector<AddTransformationTestValues> specialTestValues = {
// constant input: Add -> Subtract
{
ngraph::element::f32,
false,
1,
LayerTransformation::createParamsU8I8(),
@@ -797,7 +777,6 @@ const std::vector<AddTransformationTestValues> specialTestValues = {
// constant input: Add -> Subtract
{
ngraph::element::f32,
false,
0,
LayerTransformation::createParamsU8I8(),
@@ -839,7 +818,6 @@ const std::vector<std::pair<ngraph::PartialShape, ngraph::PartialShape>> inputSh
const std::vector<AddTransformationTestValues> specialTestValues = {
{
ngraph::element::f32,
false,
-1,
LayerTransformation::createParamsU8I8(),
@@ -888,7 +866,6 @@ const std::vector<std::pair<ngraph::PartialShape, ngraph::PartialShape>> inputSh
const std::vector<AddTransformationTestValues> testValues = {
{
ngraph::element::f32,
false,
-1,
LayerTransformation::createParamsU8I8(),
@@ -910,7 +887,6 @@ const std::vector<AddTransformationTestValues> testValues = {
""
},
{
ngraph::element::f32,
false,
-1,
LayerTransformation::createParamsU8I8(),
@@ -933,7 +909,6 @@ const std::vector<AddTransformationTestValues> testValues = {
},
// multiply with zero
{
ngraph::element::f32,
false,
-1,
LayerTransformation::createParamsU8I8(),
@@ -982,7 +957,6 @@ const std::vector<std::pair<ngraph::PartialShape, ngraph::PartialShape>> inputSh
const std::vector<AddTransformationTestValues> testValues = {
{
ngraph::element::f32,
false,
-1,
LayerTransformation::createParamsU8I8(),
@@ -1004,7 +978,6 @@ const std::vector<AddTransformationTestValues> testValues = {
""
},
{
ngraph::element::f32,
false,
-1,
LayerTransformation::createParamsU8I8(),
@@ -1027,7 +1000,6 @@ const std::vector<AddTransformationTestValues> testValues = {
},
// multiply with zero
{
ngraph::element::f32,
false,
-1,
LayerTransformation::createParamsU8I8(),
@@ -1077,7 +1049,6 @@ const std::vector<std::pair<ngraph::PartialShape, ngraph::PartialShape>> inputSh
const std::vector<AddTransformationTestValues> testValues = {
// FP32 model, quantized branch: 1
{
ngraph::element::f32,
false,
-1,
LayerTransformation::createParamsU8I8().setUpdatePrecisions(false),
@@ -1100,7 +1071,6 @@ const std::vector<AddTransformationTestValues> testValues = {
},
// FP32 model, quantized branch: 0
{
ngraph::element::f32,
false,
-1,
LayerTransformation::createParamsU8I8().setUpdatePrecisions(false),
@@ -1123,7 +1093,6 @@ const std::vector<AddTransformationTestValues> testValues = {
},
// INT8 model (FQ decomposition before LPT), quantized branch: 1
{
ngraph::element::f32,
false,
-1,
LayerTransformation::createParamsU8I8().setUpdatePrecisions(false),
@@ -1146,7 +1115,6 @@ const std::vector<AddTransformationTestValues> testValues = {
},
// INT8 model (FQ decomposition before LPT), quantized branch: 0
{
ngraph::element::f32,
false,
-1,
LayerTransformation::createParamsU8I8().setUpdatePrecisions(false),
@@ -931,6 +931,30 @@ const std::vector<ReshapeTransformationTestValues> testValues = {
{{0.1f, 0.01f, 0.1f}, ngraph::element::f32, {1, 3}}
}
}
},
// U8: without subtract 2D -> 2D
{
{ Dimension::dynamic(), 2 },
{ -1, 6 },
LayerTransformation::createParamsU8I8(),
{
ngraph::element::u8,
{
{ngraph::element::f32},
{},
{{0.1f, 0.02f}, ngraph::element::f32, {1, 2}}
}
},
{
ngraph::element::u8,
{{}, {}, {}},
ngraph::element::u8,
{
{ngraph::element::f32},
{},
{{0.1f, 0.02f, 0.1f, 0.02f, 0.1f, 0.02f}, ngraph::element::f32, {1, 6}}
}
}
}
};
@@ -5,6 +5,7 @@
#include <gtest/gtest.h>
#include "common_test_utils/test_common.hpp"
#include <ngraph/opsets/opset1.hpp>
#include <ngraph/pass/constant_folding.hpp>
#include <ngraph_ops/type_relaxed.hpp>
@@ -295,4 +296,75 @@ TEST_F(TypeRelaxedTests, OneOutputMultipleInputPorts) {
relaxed_op->validate_and_infer_types();
ASSERT_EQ(param1->output(0).get_element_type(), element::i64);
}
}
}
TEST_F(TypeRelaxedTests, ConstantFoldingCheck) {
std::shared_ptr<ngraph::Function> f;
{
auto const1 = ngraph::opset1::Constant::create(element::i32, ngraph::Shape{}, { 2 });
auto const2 = ngraph::opset1::Constant::create(element::i32, ngraph::Shape{}, { 2 });
auto equal = ngraph::opset1::Equal(const1, const2);
auto relaxed_equal = make_shared<ngraph::op::TypeRelaxed<ngraph::opset1::Equal>>(equal, TypeVector{}, TypeVector{ element::u8 });
f = make_shared<ngraph::Function>(ngraph::OutputVector{ relaxed_equal }, ngraph::ParameterVector{});
ASSERT_NO_THROW(ngraph::pass::ConstantFolding().run_on_function(f));
auto layer_before_result = f->get_result()->get_input_node_shared_ptr(0);
ASSERT_TRUE(ngraph::is_type<ngraph::opset1::Constant>(layer_before_result));
}
}
TEST_F(TypeRelaxedTests, ConstantFoldingCheck1) {
std::shared_ptr<ngraph::Function> f;
{
auto const1 = ngraph::opset1::Constant::create(element::i32, ngraph::Shape{}, { 2 });
auto const2 = ngraph::opset1::Constant::create(element::i32, ngraph::Shape{}, { 2 });
auto equal = ngraph::opset1::Equal(const1, const2);
auto relaxed_equal = make_shared<ngraph::op::TypeRelaxed<ngraph::opset1::Equal>>(equal, TypeVector{}, TypeVector{ element::boolean });
f = make_shared<ngraph::Function>(ngraph::OutputVector{ relaxed_equal }, ngraph::ParameterVector{});
ASSERT_NO_THROW(ngraph::pass::ConstantFolding().run_on_function(f));
auto layer_before_result = f->get_result()->get_input_node_shared_ptr(0);
ASSERT_TRUE(ngraph::is_type<ngraph::opset1::Constant>(layer_before_result));
}
}
TEST_F(TypeRelaxedTests, ConstantFoldingCheck2) {
std::shared_ptr<ngraph::Function> f;
{
auto const1 = ngraph::opset1::Constant::create(element::u8, ngraph::Shape{}, { 2 });
auto const2 = ngraph::opset1::Constant::create(element::i8, ngraph::Shape{}, { 2 });
auto original_input_types = TypeVector{ element::i32, element::i32 };
auto relaxed_equal = std::make_shared<ngraph::op::TypeRelaxed<ngraph::opset1::Equal>>(
ngraph::element::TypeVector{ element::i32, element::i32 },
ngraph::element::TypeVector{ element::u8 },
ngraph::op::TemporaryReplaceOutputType(const1, element::i32).get(),
ngraph::op::TemporaryReplaceOutputType(const2, element::i32).get());
f = make_shared<ngraph::Function>(ngraph::OutputVector{ relaxed_equal }, ngraph::ParameterVector{});
ASSERT_NO_THROW(ngraph::pass::ConstantFolding().run_on_function(f));
auto layer_before_result = f->get_result()->get_input_node_shared_ptr(0);
ASSERT_TRUE(ngraph::is_type<ngraph::opset1::Constant>(layer_before_result));
}
}
TEST_F(TypeRelaxedTests, ConstantFoldingCheck3) {
std::shared_ptr<ngraph::Function> f;
{
auto const1 = ngraph::opset1::Constant::create(element::i32, ngraph::Shape{}, { 2 });
auto const2 = ngraph::opset1::Constant::create(element::i32, ngraph::Shape{}, { 2 });
auto equal = ngraph::opset1::Equal(const1, const2);
auto original_input_types = TypeVector{ element::f32, element::f32 };
auto relaxed_equal = make_shared<ngraph::op::TypeRelaxed<ngraph::opset1::Equal>>(equal, original_input_types, TypeVector{ element::u8 });
f = make_shared<ngraph::Function>(ngraph::OutputVector{ relaxed_equal }, ngraph::ParameterVector{});
ASSERT_NO_THROW(ngraph::pass::ConstantFolding().run_on_function(f));
auto layer_before_result = f->get_result()->get_input_node_shared_ptr(0);
ASSERT_TRUE(ngraph::is_type<ngraph::opset1::Constant>(layer_before_result));
}
}
+11 -1
View File
@@ -21,7 +21,17 @@ Interval::value_type clip_times(Interval::value_type a, Interval::value_type b)
}
}
Interval::value_type clip_add(Interval::value_type a, Interval::value_type b) {
return (a == Interval::s_max || b == Interval::s_max) ? Interval::s_max : a + b;
if (a == Interval::s_max || b == Interval::s_max) {
return Interval::s_max;
}
// check overflow without undefined behavior: a + b <= max
const static auto max = std::numeric_limits<Interval::value_type>::max();
if (b > (max - a)) {
return Interval::s_max;
}
return a + b;
}
Interval::value_type clip_minus(Interval::value_type a, Interval::value_type b) {
if (a <= b) {
+1 -1
View File
@@ -73,7 +73,7 @@ bool op::v0::Tile::evaluate_tile(const HostTensorVector& outputs, const HostTens
const auto& data = inputs[0];
const auto& axis = inputs[1];
auto& output = outputs[0];
auto repeats_val = read_vector<int64_t>(axis);
auto repeats_val = read_index_vector(axis);
auto repeats_rank = repeats_val.size();
ov::StaticShape data_shape = data->get_shape();
auto data_rank = data_shape.size();
+17
View File
@@ -143,3 +143,20 @@ TEST(intervals, sets) {
}
EXPECT_TRUE(Interval(min_int, max_int) == a_int_b);
}
TEST(intervals, corner_cases) {
Interval::value_type max = numeric_limits<Interval::value_type>::max();
Interval almost_max(0, max - 10);
Interval dynamic(0, max);
Interval zero(0, 0);
EXPECT_TRUE(almost_max + almost_max == dynamic);
EXPECT_TRUE(dynamic + almost_max == dynamic);
EXPECT_TRUE(almost_max + dynamic == dynamic);
EXPECT_TRUE(dynamic - almost_max == dynamic);
EXPECT_TRUE(dynamic * almost_max == dynamic);
EXPECT_TRUE(almost_max * dynamic == dynamic);
EXPECT_TRUE(zero * almost_max == zero);
EXPECT_TRUE(almost_max * zero == zero);
}