From 3f309048dc3f4b17b1a8cd1856f43522495d899c Mon Sep 17 00:00:00 2001 From: Pavel Esir Date: Tue, 19 Sep 2023 22:31:45 +0200 Subject: [PATCH] fix f16/f32 el type mismatch for shape subgraphs: Parameter type should not be fused for precision sensitive nodes --- .../src/transformations/convert_precision.cpp | 2 + .../tests/utils/convert_precision.cpp | 91 +++++++++++++++++++ 2 files changed, 93 insertions(+) diff --git a/src/common/transformations/src/transformations/convert_precision.cpp b/src/common/transformations/src/transformations/convert_precision.cpp index d9d506bbd0660e..65387086310830 100644 --- a/src/common/transformations/src/transformations/convert_precision.cpp +++ b/src/common/transformations/src/transformations/convert_precision.cpp @@ -201,6 +201,8 @@ bool convert_function_precision(const std::shared_ptr& f, } for (const auto& param : f->get_parameters()) { + if (skip_precision_sensitive && fp16_compression_is_disabled(param) && has_fp16_compression) + continue; is_changed |= fuse_type_to_parameter(param, precisions, convert_input_output_precision); } diff --git a/src/common/transformations/tests/utils/convert_precision.cpp b/src/common/transformations/tests/utils/convert_precision.cpp index cab235a94591af..1b96c68a32dfe1 100644 --- a/src/common/transformations/tests/utils/convert_precision.cpp +++ b/src/common/transformations/tests/utils/convert_precision.cpp @@ -15,6 +15,7 @@ #include "openvino/core/model.hpp" #include "openvino/opsets/opset1.hpp" #include "openvino/opsets/opset10.hpp" +#include "openvino/pass/visualize_tree.hpp" #include "openvino/opsets/opset3.hpp" #include "openvino/opsets/opset4.hpp" #include "openvino/opsets/opset5.hpp" @@ -2136,3 +2137,93 @@ TEST(TransformationTests, ConvertPrecisionExplicitConvertsMultiSubgraphs) { const auto& results = model->get_results(); ASSERT_EQ("if_result", results[0]->get_input_node_ptr(0)->get_friendly_name()); } + +TEST(TransformationTests, align_mixed_fp16_fp32_with_parameter_for_shape_1) { + shared_ptr model, model_ref; + pass::Manager manager; + { + auto input_1 = make_shared(element::f32, Shape{1, 3, 224, 224}); + auto shape_input = make_shared(element::f32, Shape{2}); + + auto upscale_const = ov::op::v0::Constant::create(element::f32, Shape{1}, {2.0f}); + auto mul_1 = make_shared(shape_input, upscale_const); + auto axis_const = ov::op::v0::Constant::create(element::i64, Shape{1}, {0}); + auto final_float_shape = make_shared(mul_1, axis_const); + auto final_int_shape = make_shared(final_float_shape, element::i64); + auto reshape_1 = make_shared(input_1, final_int_shape, false); + + model = make_shared(NodeVector{reshape_1}, ParameterVector{input_1, shape_input}); + + type_to_fuse_map empty_type_to_fuse_map = {}; + bool keep_precision_sensitive_in_fp32 = true; + manager.register_pass(precisions_map{{element::f32, element::f16}}, + empty_type_to_fuse_map, + keep_precision_sensitive_in_fp32); + manager.run_passes(model); + } + + { + auto input_1 = make_shared(element::f16, Shape{1, 3, 224, 224}); + auto shape_input = make_shared(element::f32, Shape{2}); + + // even for FP16 compressed model shape subgraph should be kept in fp32 + auto upscale_const = ov::op::v0::Constant::create(element::f32, Shape{1}, {2.0f}); + auto mul_1 = make_shared(shape_input, upscale_const); + auto axis_const = ov::op::v0::Constant::create(element::i64, Shape{1}, {0}); + auto final_float_shape = make_shared(mul_1, axis_const); + auto final_int_shape = make_shared(final_float_shape, element::i64); + auto reshape_1 = make_shared(input_1, final_int_shape, false); + + model_ref = make_shared(NodeVector{reshape_1}, ParameterVector{input_1, shape_input}); + } + const FunctionsComparator func_comparator = FunctionsComparator::with_default(); + FunctionsComparator::Result result = func_comparator(model_ref, model); + ASSERT_TRUE(result.valid) << result.message; +} + +TEST(TransformationTests, align_mixed_fp16_fp32_with_parameter_for_shape_2) { + shared_ptr model, model_ref; + pass::Manager manager; + { + auto input_1 = make_shared(element::f32, Shape{1, 3, 224, 224}); + auto shape_input = make_shared(element::f32, Shape{2}); + + auto upscale_const = ov::op::v0::Constant::create(element::f32, Shape{1}, {2.0f}); + auto mul_1 = make_shared(shape_input, upscale_const); + auto axis_const = ov::op::v0::Constant::create(element::i64, Shape{1}, {0}); + auto final_float_shape = make_shared(mul_1, axis_const); + auto final_int_shape = make_shared(final_float_shape, element::i64); + auto reshape_1 = make_shared(input_1, final_int_shape, false); + + model = make_shared(NodeVector{reshape_1}, ParameterVector{input_1, shape_input}); + + type_to_fuse_map empty_type_to_fuse_map = {}; + bool keep_precision_sensitive_in_fp32 = true; + const bool convert_input_output_precision = false; + manager.register_pass(precisions_map{{element::f32, element::f16}}, + empty_type_to_fuse_map, + keep_precision_sensitive_in_fp32, + convert_input_output_precision); + manager.run_passes(model); + } + + { + auto input_1 = make_shared(element::f32, Shape{1, 3, 224, 224}); + auto convert_to_f16 = make_shared(input_1, element::f16); + auto shape_input = make_shared(element::f32, Shape{2}); + + // even for FP16 compressed model shape subgraph should be kept in fp32 + auto upscale_const = ov::op::v0::Constant::create(element::f32, Shape{1}, {2.0f}); + auto mul_1 = make_shared(shape_input, upscale_const); + auto axis_const = ov::op::v0::Constant::create(element::i64, Shape{1}, {0}); + auto final_float_shape = make_shared(mul_1, axis_const); + auto final_int_shape = make_shared(final_float_shape, element::i64); + auto reshape_1 = make_shared(convert_to_f16, final_int_shape, false); + auto convert_to_f32 = make_shared(reshape_1, element::f32); + + model_ref = make_shared(NodeVector{convert_to_f32}, ParameterVector{input_1, shape_input}); + } + const FunctionsComparator func_comparator = FunctionsComparator::with_default(); + FunctionsComparator::Result result = func_comparator(model_ref, model); + ASSERT_TRUE(result.valid) << result.message; +}