Skip to content

Commit

Permalink
changed namespaces from ngraph -> ov; completed unit-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
pavel-esir committed Nov 22, 2021
1 parent c6146c6 commit c4aa420
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 85 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <pot_transformations.hpp>
#include <pruning.hpp>
#include <transformations/common_optimizations/compress_float_constants.hpp>
#include <transformations/common_optimizations/division_to_zero_fp16_resolver.hpp>
#include <transformations/common_optimizations/mark_precision_sensitive_subgraphs.hpp>
#include <transformations/common_optimizations/moc_transformations.hpp>
#include <transformations/control_flow/unroll_tensor_iterator.hpp>
Expand Down Expand Up @@ -60,6 +61,7 @@ void InferenceEnginePython::GenerateMappingFile(InferenceEnginePython::IENetwork

void InferenceEnginePython::CompressModelTransformation(InferenceEnginePython::IENetwork network) {
ngraph::pass::Manager manager;
manager.register_pass<ov::pass::DivisionToZeroFP16Resolver>();
manager.register_pass<ov::pass::MarkPrecisionSensitiveSubgraphs>();
manager.register_pass<ov::pass::CompressFloatConstants>();
manager.run_passes(network.actual->getFunction());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,23 @@
#include <ngraph/pass/graph_rewrite.hpp>
#include "ngraph/pattern/matcher.hpp"

namespace ngraph {
namespace ov {
namespace pass {

class TRANSFORMATIONS_API DivisionToZeroFP16Resolver;

} // namespace pass
} // namespace ngraph
} // namespace ov

/**
* @ingroup ie_transformation_common_api
* @brief :
* @brief: clamps eps into fp16 minimal normalized value in input_1/Maximum(input_2, eps) and input_1/Add(input_2, eps) patterns
*
* eps must be always nonzero to prevent from NaNs in such expressions if input_1 and input_2 simultaneously happened to be zero.
* We should keep in such patterns eps >= fp16 minimal normalized value so that
* CompressFloatConstants should not cast them into zero during compression into f16.
*/
class ngraph::pass::DivisionToZeroFP16Resolver: public ngraph::pass::MatcherPass {
class ov::pass::DivisionToZeroFP16Resolver: public ngraph::pass::MatcherPass {
public:
NGRAPH_RTTI_DECLARATION;
DivisionToZeroFP16Resolver();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,49 +9,47 @@
#include <memory>
#include <vector>

#include <ngraph/opsets/opset8.hpp>
#include <ngraph/rt_info.hpp>
#include <ngraph/pattern/op/wrap_type.hpp>
#include <ngraph/pattern/op/or.hpp>
#include <openvino/opsets/opset8.hpp>
#include "ngraph/rt_info.hpp"
#include <openvino/pass/pattern/op/wrap_type.hpp>
#include <openvino/pass/pattern/op/or.hpp>

NGRAPH_RTTI_DEFINITION(ngraph::pass::DivisionToZeroFP16Resolver, "DivisionToZeroFP16Resolver", 0);
NGRAPH_RTTI_DEFINITION(ov::pass::DivisionToZeroFP16Resolver, "DivisionToZeroFP16Resolver", 0);

constexpr float normalized_fp16_min = 6.103515625e-05f; // normalized minimum of fp16
constexpr float normalized_fp16_min = 6.103515625e-05f; // fp16 minimal normalized value

ngraph::pass::DivisionToZeroFP16Resolver::DivisionToZeroFP16Resolver() {
MATCHER_SCOPE(DivisionToZeroFP16Resolver);
auto input_1 = ngraph::pattern::any_input();
auto input_2 = ngraph::pattern::any_input();
using namespace ov;

ov::pass::DivisionToZeroFP16Resolver::DivisionToZeroFP16Resolver() {
MATCHER_SCOPE(DivisionToZeroFP16Resolver);
auto input_1 = pattern::any_input();
auto input_2 = pattern::any_input();

auto eps_const_pattern = ngraph::pattern::wrap_type<ngraph::opset8::Constant>();
auto max = std::make_shared<ngraph::opset8::Maximum>(input_2, eps_const_pattern);
auto add = std::make_shared<ngraph::opset8::Add>(input_2, eps_const_pattern);
auto eps_const_pattern = pattern::wrap_type<opset8::Constant>();
auto max = std::make_shared<opset8::Maximum>(input_2, eps_const_pattern);
auto add = std::make_shared<opset8::Add>(input_2, eps_const_pattern);
auto max_or_add = std::make_shared<pattern::op::Or>(OutputVector{max, add});
auto divide = std::make_shared<ngraph::opset8::Divide>(input_1, max_or_add);
auto divide = std::make_shared<opset8::Divide>(input_1, max_or_add);

ngraph::matcher_pass_callback callback = [=](ngraph::pattern::Matcher& m) {
matcher_pass_callback callback = [=](pattern::Matcher& m) {
const auto& pattern_to_output = m.get_pattern_value_map();

const auto eps_const = std::dynamic_pointer_cast<ngraph::opset8::Constant>(pattern_to_output.at(eps_const_pattern).get_node_shared_ptr());

if (!eps_const) {
const auto eps_const = std::dynamic_pointer_cast<opset8::Constant>(pattern_to_output.at(eps_const_pattern).get_node_shared_ptr());
if (!eps_const)
return false;
}
for (float val : eps_const->get_vector<float>()) {
if (val >= normalized_fp16_min) {

for (float val : eps_const->get_vector<float>())
if (val >= normalized_fp16_min)
return false;
}
}

auto new_constant = std::make_shared<opset8::Constant>(eps_const->get_element_type(),
eps_const->get_shape(),
normalized_fp16_min);
ngraph::copy_runtime_info(eps_const, new_constant);
ngraph::replace_node(eps_const, new_constant);
copy_runtime_info(eps_const, new_constant);
replace_node(eps_const, new_constant);
return true;
};

auto m = std::make_shared<ngraph::pattern::Matcher>(divide, matcher_name);
auto m = std::make_shared<pattern::Matcher>(divide, matcher_name);
register_matcher(m, callback);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,82 +8,138 @@
#include <memory>

#include <ngraph/function.hpp>
#include <ngraph/opsets/opset4.hpp>
#include <ngraph/pass/manager.hpp>
#include <openvino/opsets/opset4.hpp>
#include <openvino/pass/manager.hpp>
#include <transformations/common_optimizations/division_to_zero_fp16_resolver.hpp>
#include <transformations/init_node_info.hpp>
#include <transformations/utils/utils.hpp>

#include "common_test_utils/ngraph_test_utils.hpp"

using namespace testing;
constexpr float normalized_fp16_min = 6.103515625e-05f; // normalized minimum of fp16
using namespace ov;
constexpr float normalized_fp16_min = 6.103515625e-05f; // fp16 minimal normalized value


TEST_F(TransformationTestsF, DivisionToZeroMinimalPattern) {
const float eps_value = 1.e-12;
{
auto input_1 = std::make_shared<opset4::Parameter>(element::f32, PartialShape::dynamic(3));
auto input_2 = std::make_shared<opset4::Parameter>(element::f32, PartialShape::dynamic(3));
auto eps_const = opset4::Constant::create(element::f32, Shape{1}, {eps_value});
auto add = std::make_shared<opset4::Add>(input_2, eps_const);
auto divide = std::make_shared<opset4::Divide>(input_1, add);

function = std::make_shared<Function>(NodeVector{divide}, ParameterVector{input_1, input_2});

manager.register_pass<pass::DivisionToZeroFP16Resolver>();
}

{
auto input_1 = std::make_shared<opset4::Parameter>(element::f32, PartialShape::dynamic(3));
auto input_2 = std::make_shared<opset4::Parameter>(element::f32, PartialShape::dynamic(3));
auto eps_const = opset4::Constant::create(element::f32, Shape{1}, {normalized_fp16_min});
auto add = std::make_shared<opset4::Add>(input_2, eps_const);
auto divide = std::make_shared<opset4::Divide>(input_1, add);

function_ref = std::make_shared<Function>(NodeVector{divide}, ParameterVector{input_1, input_2});

manager.register_pass<pass::DivisionToZeroFP16Resolver>();
}
}

TEST_F(TransformationTestsF, DivisionToZeroMinimalPatternUnchanged) {
// if eps_value is greater than normalized_fp16_min then leave graph unchanged
const float eps_value = 0.000099f;
{
auto input_1 = std::make_shared<opset4::Parameter>(element::f32, PartialShape::dynamic(3));
auto input_2 = std::make_shared<opset4::Parameter>(element::f32, PartialShape::dynamic(3));
auto eps_const = opset4::Constant::create(element::f32, Shape{1}, {eps_value});
auto add = std::make_shared<opset4::Add>(input_2, eps_const);
auto divide = std::make_shared<opset4::Divide>(input_1, add);

function = std::make_shared<Function>(NodeVector{divide}, ParameterVector{input_1, input_2});

manager.register_pass<pass::DivisionToZeroFP16Resolver>();
}

{
auto input_1 = std::make_shared<opset4::Parameter>(element::f32, PartialShape::dynamic(3));
auto input_2 = std::make_shared<opset4::Parameter>(element::f32, PartialShape::dynamic(3));
auto eps_const = opset4::Constant::create(element::f32, Shape{1}, {eps_value});
auto add = std::make_shared<opset4::Add>(input_2, eps_const);
auto divide = std::make_shared<opset4::Divide>(input_1, add);

function_ref = std::make_shared<Function>(NodeVector{divide}, ParameterVector{input_1, input_2});

manager.register_pass<pass::DivisionToZeroFP16Resolver>();
}
}

TEST_F(TransformationTestsF, DivisionToZeroWithMax) {
const float eps_value = 1.e-12;
{
auto input = std::make_shared<ngraph::opset4::Parameter>(ngraph::element::f32, ngraph::PartialShape::dynamic(3));
auto exp = ngraph::opset4::Constant::create(ngraph::element::f32, ngraph::Shape{}, {2.f});
auto pow = std::make_shared<ngraph::opset4::Power>(input, exp);
auto axes_const = ngraph::opset4::Constant::create(ngraph::element::i64, ngraph::Shape{2}, {0, 1});
auto reduce_sum = std::make_shared<ngraph::opset4::ReduceSum>(pow, axes_const);
auto eps_const = ngraph::opset4::Constant::create(ngraph::element::f32, ngraph::Shape{}, {eps_value});
auto max = std::make_shared<ngraph::opset4::Maximum>(reduce_sum, eps_const);
auto sqrt = std::make_shared<ngraph::opset4::Sqrt>(max);
auto divide = std::make_shared<ngraph::opset4::Divide>(input, sqrt);

function = std::make_shared<ngraph::Function>(ngraph::NodeVector{divide}, ngraph::ParameterVector{input});

manager.register_pass<ngraph::pass::DivisionToZeroFP16Resolver>();
auto input = std::make_shared<opset4::Parameter>(element::f32, PartialShape::dynamic(3));
auto exp = opset4::Constant::create(element::f32, Shape{}, {2.f});
auto pow = std::make_shared<opset4::Power>(input, exp);
auto axes_const = opset4::Constant::create(element::i64, Shape{2}, {0, 1});
auto reduce_sum = std::make_shared<opset4::ReduceSum>(pow, axes_const);
auto eps_const = opset4::Constant::create(element::f32, Shape{}, {eps_value});
auto max = std::make_shared<opset4::Maximum>(reduce_sum, eps_const);
auto sqrt = std::make_shared<opset4::Sqrt>(max);
auto divide = std::make_shared<opset4::Divide>(input, sqrt);

function = std::make_shared<Function>(NodeVector{divide}, ParameterVector{input});

manager.register_pass<pass::DivisionToZeroFP16Resolver>();
}

{
auto input = std::make_shared<ngraph::opset4::Parameter>(ngraph::element::f32, ngraph::PartialShape::dynamic(3));
auto exp = ngraph::opset4::Constant::create(ngraph::element::f32, ngraph::Shape{}, {2.f});
auto pow = std::make_shared<ngraph::opset4::Power>(input, exp);
auto axes_const = ngraph::opset4::Constant::create(ngraph::element::i64, ngraph::Shape{2}, {0, 1});
auto reduce_sum = std::make_shared<ngraph::opset4::ReduceSum>(pow, axes_const);
auto eps_const = ngraph::opset4::Constant::create(ngraph::element::f32, ngraph::Shape{}, {normalized_fp16_min});
auto max = std::make_shared<ngraph::opset4::Maximum>(reduce_sum, eps_const);
auto sqrt = std::make_shared<ngraph::opset4::Sqrt>(max);
auto divide = std::make_shared<ngraph::opset4::Divide>(input, sqrt);

function_ref = std::make_shared<ngraph::Function>(ngraph::NodeVector{divide}, ngraph::ParameterVector{input});
auto input = std::make_shared<opset4::Parameter>(element::f32, PartialShape::dynamic(3));
auto exp = opset4::Constant::create(element::f32, Shape{}, {2.f});
auto pow = std::make_shared<opset4::Power>(input, exp);
auto axes_const = opset4::Constant::create(element::i64, Shape{2}, {0, 1});
auto reduce_sum = std::make_shared<opset4::ReduceSum>(pow, axes_const);
auto eps_const = opset4::Constant::create(element::f32, Shape{}, {normalized_fp16_min});
auto max = std::make_shared<opset4::Maximum>(reduce_sum, eps_const);
auto sqrt = std::make_shared<opset4::Sqrt>(max);
auto divide = std::make_shared<opset4::Divide>(input, sqrt);

function_ref = std::make_shared<Function>(NodeVector{divide}, ParameterVector{input});
}
}


TEST_F(TransformationTestsF, DivisionToZeroWithAdd) {
const float eps_value = 0.000099f;
{
auto input = std::make_shared<ngraph::opset4::Parameter>(ngraph::element::f32, ngraph::PartialShape::dynamic(3));
auto exp = ngraph::opset4::Constant::create(ngraph::element::f32, ngraph::Shape{}, {2.f});
auto pow = std::make_shared<ngraph::opset4::Power>(input, exp);
auto axes_const = ngraph::opset4::Constant::create(ngraph::element::i64, ngraph::Shape{2}, {0, 1});
auto reduce_sum = std::make_shared<ngraph::opset4::ReduceSum>(pow, axes_const);
auto eps_const = ngraph::opset4::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {eps_value});
auto add = std::make_shared<ngraph::opset4::Add>(reduce_sum, eps_const);
auto sqrt = std::make_shared<ngraph::opset4::Sqrt>(add);
auto divide = std::make_shared<ngraph::opset4::Divide>(input, sqrt);

function = std::make_shared<ngraph::Function>(ngraph::NodeVector{divide}, ngraph::ParameterVector{input});

manager.register_pass<ngraph::pass::DivisionToZeroFP16Resolver>();
auto input = std::make_shared<opset4::Parameter>(element::f32, PartialShape::dynamic(3));
auto exp = opset4::Constant::create(element::f32, Shape{}, {2.f});
auto pow = std::make_shared<opset4::Power>(input, exp);
auto axes_const = opset4::Constant::create(element::i64, Shape{2}, {0, 1});
auto reduce_sum = std::make_shared<opset4::ReduceSum>(pow, axes_const);
auto eps_const = opset4::Constant::create(element::f32, Shape{1}, {eps_value});
auto add = std::make_shared<opset4::Add>(reduce_sum, eps_const);
auto sqrt = std::make_shared<opset4::Sqrt>(add);
auto divide = std::make_shared<opset4::Divide>(input, sqrt);

function = std::make_shared<Function>(NodeVector{divide}, ParameterVector{input});

manager.register_pass<pass::DivisionToZeroFP16Resolver>();
}

{
auto input = std::make_shared<ngraph::opset4::Parameter>(ngraph::element::f32, ngraph::PartialShape::dynamic(3));
auto exp = ngraph::opset4::Constant::create(ngraph::element::f32, ngraph::Shape{}, {2.f});
auto pow = std::make_shared<ngraph::opset4::Power>(input, exp);
auto axes_const = ngraph::opset4::Constant::create(ngraph::element::i64, ngraph::Shape{2}, {0, 1});
auto reduce_sum = std::make_shared<ngraph::opset4::ReduceSum>(pow, axes_const);
auto eps_const = ngraph::opset4::Constant::create(ngraph::element::f32, ngraph::Shape{1}, {normalized_fp16_min});
auto add = std::make_shared<ngraph::opset4::Add>(reduce_sum, eps_const);
auto sqrt = std::make_shared<ngraph::opset4::Sqrt>(add);
auto divide = std::make_shared<ngraph::opset4::Divide>(input, sqrt);

function_ref = std::make_shared<ngraph::Function>(ngraph::NodeVector{divide}, ngraph::ParameterVector{input});

manager.register_pass<ngraph::pass::DivisionToZeroFP16Resolver>();
auto input = std::make_shared<opset4::Parameter>(element::f32, PartialShape::dynamic(3));
auto exp = opset4::Constant::create(element::f32, Shape{}, {2.f});
auto pow = std::make_shared<opset4::Power>(input, exp);
auto axes_const = opset4::Constant::create(element::i64, Shape{2}, {0, 1});
auto reduce_sum = std::make_shared<opset4::ReduceSum>(pow, axes_const);
auto eps_const = opset4::Constant::create(element::f32, Shape{1}, {normalized_fp16_min});
auto add = std::make_shared<opset4::Add>(reduce_sum, eps_const);
auto sqrt = std::make_shared<opset4::Sqrt>(add);
auto divide = std::make_shared<opset4::Divide>(input, sqrt);

function_ref = std::make_shared<Function>(NodeVector{divide}, ParameterVector{input});

manager.register_pass<pass::DivisionToZeroFP16Resolver>();
}
}

0 comments on commit c4aa420

Please sign in to comment.