Moved MVN reference to ov::core. (#13327)
* Moved MVN reference to ov::core. * Code style. * Applied comments. * Code style. * Returned evaluate in evaluates_map() * Added constant folding test. * Use new API. * Use new API. * Use new API. Co-authored-by: Evgenya Stepyreva <evgenya.stepyreva@intel.com>
This commit is contained in:
1 parent
eb0dd26e4b
commit
c95b3e5138
4 files changed
+132
No files matched your search
@@ -125,6 +125,10 @@ public:
|
||||
|
||||
std::shared_ptr<Node> clone_with_new_inputs(const OutputVector& new_args) const override;
|
||||
|
||||
bool evaluate(ov::TensorVector& output_values, const ov::TensorVector& input_values) const override;
|
||||
|
||||
bool has_evaluate() const override;
|
||||
|
||||
float get_eps() const {
|
||||
return m_eps;
|
||||
}
|
||||
|
||||
@@ -86,6 +86,25 @@ void mvn_6(const T* arg,
|
||||
divide(out, tmp_buffer.data(), out, in_shape, reduced_shape, op::AutoBroadcastType::NUMPY, true);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
AxisSet mvn_6_reduction_axes(const ov::Tensor& axes_input, size_t rank) {
|
||||
T* a = axes_input.data<T>();
|
||||
auto v = std::vector<T>(a, a + axes_input.get_shape()[0]);
|
||||
std::vector<size_t> axes(v.size(), 0);
|
||||
for (size_t i = 0; i < v.size(); i++) {
|
||||
if (v[i] < 0) {
|
||||
if (rank + v[i] < 0) {
|
||||
throw ov::Exception("Unexpected axis");
|
||||
}
|
||||
axes[i] = (size_t)(rank + v[i]);
|
||||
} else {
|
||||
axes[i] = (size_t)(v[i]);
|
||||
}
|
||||
}
|
||||
return AxisSet(axes);
|
||||
}
|
||||
|
||||
} // namespace reference
|
||||
} // namespace runtime
|
||||
} // namespace ngraph
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "itt.hpp"
|
||||
#include "ngraph/runtime/reference/mvn.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace ngraph;
|
||||
@@ -135,3 +136,64 @@ bool op::v6::MVN::visit_attributes(AttributeVisitor& visitor) {
|
||||
visitor.on_attribute("eps_mode", m_eps_mode);
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace mvn {
|
||||
namespace {
|
||||
template <element::Type_t ET>
|
||||
bool evaluate(ov::TensorVector& outputs,
|
||||
const ov::TensorVector& inputs,
|
||||
bool normalize_variance,
|
||||
float eps,
|
||||
ov::op::MVNEpsMode eps_mode) {
|
||||
using T = typename element_type_traits<ET>::value_type;
|
||||
AxisSet reduction_axes;
|
||||
auto rank = inputs[0].get_shape().size();
|
||||
if (inputs[1].get_element_type() == element::i64) {
|
||||
reduction_axes = runtime::reference::mvn_6_reduction_axes<int64_t>(inputs[1], rank);
|
||||
} else if (inputs[1].get_element_type() == element::i32) {
|
||||
reduction_axes = runtime::reference::mvn_6_reduction_axes<int32_t>(inputs[1], rank);
|
||||
} else {
|
||||
throw ov::Exception("Unexpected indices type");
|
||||
}
|
||||
runtime::reference::mvn_6<T>(inputs[0].data<T>(),
|
||||
outputs[0].data<T>(),
|
||||
inputs[0].get_shape(),
|
||||
reduction_axes,
|
||||
normalize_variance,
|
||||
eps,
|
||||
eps_mode);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool evaluate_mvn(ov::TensorVector& outputs,
|
||||
const ov::TensorVector& inputs,
|
||||
bool normalize_variance,
|
||||
float eps,
|
||||
ov::op::MVNEpsMode eps_mode) {
|
||||
bool rc = true;
|
||||
switch (inputs[0].get_element_type()) {
|
||||
NGRAPH_TYPE_CASE(evaluate_mvn, f32, outputs, inputs, normalize_variance, eps, eps_mode);
|
||||
default:
|
||||
rc = false;
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
} // namespace
|
||||
} // namespace mvn
|
||||
|
||||
bool op::v6::MVN::evaluate(ov::TensorVector& outputs, const ov::TensorVector& inputs) const {
|
||||
OV_OP_SCOPE(v6_MVN_evaluate);
|
||||
return mvn::evaluate_mvn(outputs, inputs, get_normalize_variance(), get_eps(), get_eps_mode());
|
||||
}
|
||||
|
||||
bool op::v6::MVN::has_evaluate() const {
|
||||
OV_OP_SCOPE(v6_MVN_has_evaluate);
|
||||
switch (get_input_element_type(0)) {
|
||||
case ov::element::f32:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
// Copyright (C) 2018-2022 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "common_test_utils/test_common.hpp"
|
||||
#include "common_test_utils/graph_comparator.hpp"
|
||||
|
||||
#include "openvino/opsets/opset10.hpp"
|
||||
#include "openvino/pass/constant_folding.hpp"
|
||||
#include "openvino/pass/manager.hpp"
|
||||
#include "openvino/pass/pattern/op/wrap_type.hpp"
|
||||
#include "openvino/core/validation_util.hpp"
|
||||
|
||||
using namespace testing;
|
||||
using namespace std;
|
||||
using namespace ov;
|
||||
|
||||
|
||||
TEST(TransformationTests, ConstFoldingMVN) {
|
||||
shared_ptr<ov::Model> fun(nullptr);
|
||||
{
|
||||
const auto in = make_shared<opset10::Parameter>(element::f32, Shape{6});
|
||||
const auto mvn_in = make_shared<opset10::Constant>(element::f32, Shape{6}, vector<float>(6, 0.0));
|
||||
const auto axes = make_shared<opset10::Constant>(element::i32, Shape{1}, vector<int> {0});
|
||||
auto mvn = make_shared<opset10::MVN>(mvn_in, axes, false, 1e-9, op::MVNEpsMode::OUTSIDE_SQRT);
|
||||
auto add = make_shared<opset10::Add>(in, mvn);
|
||||
|
||||
fun = make_shared<ov::Model>(NodeVector {add}, ParameterVector {in});
|
||||
|
||||
ov::pass::Manager manager;
|
||||
manager.register_pass<ov::pass::ConstantFolding>();
|
||||
manager.run_passes(fun);
|
||||
}
|
||||
shared_ptr<ov::Model> f_ref(nullptr);
|
||||
{
|
||||
const auto in = make_shared<opset10::Parameter>(element::f32, Shape{6});
|
||||
const auto mvn_const = make_shared<opset10::Constant>(element::f32, Shape{6}, vector<float>(6, 0.0));
|
||||
auto add = make_shared<opset10::Add>(in, mvn_const);
|
||||
|
||||
f_ref = make_shared<ov::Model>(NodeVector {add}, ParameterVector {in});
|
||||
}
|
||||
|
||||
auto res = compare_functions(fun, f_ref);
|
||||
ASSERT_TRUE(res.first) << res.second;
|
||||
}
|
||||
Reference in new issue
Block a user