[core]Migrate Eye to new API (#20258)

* Migrate Eye to new API

* Fix `matrix_offset` initialization

* get_tensors_shapes -> get_tensors_partial_shapes
This commit is contained in:
Pawel Raasz 2023-10-11 11:50:29 +02:00 committed by GitHub
parent 1ca2f9c6de
commit ac11751e9c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 127 additions and 101 deletions

View File

@ -55,9 +55,7 @@ public:
m_output_type = output_type; m_output_type = output_type;
} }
OPENVINO_SUPPRESS_DEPRECATED_START bool evaluate(TensorVector& outputs, const TensorVector& inputs) const override;
bool evaluate(const HostTensorVector& outputs, const HostTensorVector& inputs) const override;
OPENVINO_SUPPRESS_DEPRECATED_END
bool has_evaluate() const override; bool has_evaluate() const override;
protected: protected:

View File

@ -0,0 +1,23 @@
// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include "openvino/core/partial_shape.hpp"
#include "openvino/runtime/tensor.hpp"
namespace ov {
namespace op {
namespace util {
/**
* @brief Get the tensors shapes as ov::PartialShape.
*
* @param tensors Input tensors vector to get its shapes.
* @return Vector of partial shapes sam size as input tensor vector.
*/
std::vector<PartialShape> get_tensors_partial_shapes(const TensorVector& tensors);
} // namespace util
} // namespace op
} // namespace ov

View File

@ -7,31 +7,41 @@
#include <cmath> #include <cmath>
#include "openvino/core/shape.hpp" #include "openvino/core/shape.hpp"
#include "utils/span.hpp"
namespace ov { namespace ov {
namespace reference { namespace reference {
/**
* @brief Reference implementation of Eye operator
*
* @param data Pointer to output data.
* @param out_shape Output data size.
* @param diagonal_index Eye diagonal index to populate matrix with ones
*/
template <typename T> template <typename T>
void eye(T* data, const Shape& out_shape, const int64_t diagonal_index) { void eye(T* data, const Shape& out_shape, const int64_t diagonal_index) {
const int64_t num_matrices = shape_size(span(out_shape).subspan(0, out_shape.size() - 2)); const auto spatial_dims_offset = out_shape.size() - 2;
const int64_t num_rows = out_shape[out_shape.size() - 2]; const int64_t num_columns = out_shape.back();
const int64_t num_columns = out_shape[out_shape.size() - 1]; const int64_t num_rows = out_shape[spatial_dims_offset];
const int64_t matrix_size = num_rows * num_columns; const int64_t matrix_size = num_rows * num_columns;
const int64_t out_size = shape_size(out_shape);
// fill tensor by zero // fill tensor by zero
std::fill(data, data + num_matrices * matrix_size, T(0)); std::fill(data, std::next(data, out_size), T(0));
// set ones on diagonal // set ones on diagonal
const int64_t shift_by_columns = std::max(diagonal_index, int64_t(0)); constexpr int64_t zero{0};
const int64_t count_by_columns = std::max(num_columns - std::abs(diagonal_index), int64_t(0)); const auto abs_diag_idx = static_cast<int64_t>(std::abs(diagonal_index));
const int64_t count_by_rows = std::max(num_rows - std::abs(diagonal_index), int64_t(0)); const int64_t shift_by_columns = std::max(diagonal_index, zero);
const int64_t count_by_columns = std::max(num_columns - abs_diag_idx, zero);
const int64_t count_by_rows = std::max(num_rows - abs_diag_idx, zero);
const int64_t count = const int64_t count =
diagonal_index > 0 ? std::min(count_by_columns, num_rows) : std::min(count_by_rows, num_columns); diagonal_index > 0 ? std::min(count_by_columns, num_rows) : std::min(count_by_rows, num_columns);
for (auto i = 0; i < num_matrices; i++) { for (auto matrix_offset = zero; matrix_offset < out_size; matrix_offset += matrix_size) {
for (auto j = 0; j < count; j++) { for (auto j = 0; j < count; ++j) {
const int64_t index = (j + shift_by_columns - diagonal_index) * num_columns + j + shift_by_columns; const int64_t index = (j + shift_by_columns - diagonal_index) * num_columns + j + shift_by_columns;
data[index + i * matrix_size] = static_cast<T>(1); data[matrix_offset + index] = T{1};
} }
} }
} }

View File

@ -4,62 +4,49 @@
#include "openvino/op/eye.hpp" #include "openvino/op/eye.hpp"
#include "element_visitor.hpp"
#include "eye_shape_inference.hpp" #include "eye_shape_inference.hpp"
#include "itt.hpp" #include "itt.hpp"
#include "ngraph/validation_util.hpp" #include "openvino/core/validation_util.hpp"
#include "openvino/op/util/evaluate_helpers.hpp"
#include "openvino/reference/eye.hpp" #include "openvino/reference/eye.hpp"
OPENVINO_SUPPRESS_DEPRECATED_START
namespace ov { namespace ov {
namespace op { namespace op {
namespace eye { namespace eye {
namespace {
template <ov::element::Type_t ET>
bool evaluate(const ngraph::HostTensorPtr& out, const int64_t diagonal_index) {
ov::reference::eye(out->get_data_ptr<ET>(), out->get_shape(), diagonal_index);
return true;
}
bool evaluate_eye(const ngraph::HostTensorPtr& out, const int64_t diagonal_index) { struct Evaluate : element::NoAction<bool> {
bool rc = true; using element::NoAction<bool>::visit;
switch (out->get_element_type()) {
OPENVINO_TYPE_CASE(evaluate, i8, out, diagonal_index); template <element::Type_t ET, class T = fundamental_type_for<ET>>
OPENVINO_TYPE_CASE(evaluate, u8, out, diagonal_index); static result_type visit(Tensor& out, const Shape& out_shape, const int64_t diagonal_idx) {
OPENVINO_TYPE_CASE(evaluate, f16, out, diagonal_index); reference::eye(out.data<T>(), out_shape, diagonal_idx);
OPENVINO_TYPE_CASE(evaluate, bf16, out, diagonal_index); return true;
OPENVINO_TYPE_CASE(evaluate, i32, out, diagonal_index);
OPENVINO_TYPE_CASE(evaluate, f32, out, diagonal_index);
OPENVINO_TYPE_CASE(evaluate, f64, out, diagonal_index);
OPENVINO_TYPE_CASE(evaluate, i64, out, diagonal_index);
default:
rc = false;
break;
} }
return rc; };
}
} // namespace
} // namespace eye } // namespace eye
ov::op::v9::Eye::Eye(const Output<Node>& num_rows, namespace v9 {
const Output<Node>& num_columns, Eye::Eye(const Output<Node>& num_rows,
const Output<Node>& diagonal_index, const Output<Node>& num_columns,
const Output<Node>& batch_shape, const Output<Node>& diagonal_index,
const ov::element::Type& out_type) const Output<Node>& batch_shape,
const ov::element::Type& out_type)
: Op({num_rows, num_columns, diagonal_index, batch_shape}), : Op({num_rows, num_columns, diagonal_index, batch_shape}),
m_output_type(out_type) { m_output_type(out_type) {
constructor_validate_and_infer_types(); constructor_validate_and_infer_types();
} }
ov::op::v9::Eye::Eye(const Output<Node>& num_rows, Eye::Eye(const Output<Node>& num_rows,
const Output<Node>& num_columns, const Output<Node>& num_columns,
const Output<Node>& diagonal_index, const Output<Node>& diagonal_index,
const ov::element::Type& out_type) const ov::element::Type& out_type)
: Op({num_rows, num_columns, diagonal_index}), : Op({num_rows, num_columns, diagonal_index}),
m_output_type(out_type) { m_output_type(out_type) {
constructor_validate_and_infer_types(); constructor_validate_and_infer_types();
} }
void ov::op::v9::Eye::validate_and_infer_types() { void Eye::validate_and_infer_types() {
OV_OP_SCOPE(v9_Eye_validate_and_infer_types); OV_OP_SCOPE(v9_Eye_validate_and_infer_types);
for (size_t i = 0; i < get_input_size(); ++i) { for (size_t i = 0; i < get_input_size(); ++i) {
@ -78,81 +65,72 @@ void ov::op::v9::Eye::validate_and_infer_types() {
set_output_type(0, get_out_type(), output_shape); set_output_type(0, get_out_type(), output_shape);
} }
bool ov::op::v9::Eye::visit_attributes(ov::AttributeVisitor& visitor) { bool Eye::visit_attributes(ov::AttributeVisitor& visitor) {
OV_OP_SCOPE(v9_Eye_visit_attributes); OV_OP_SCOPE(v9_Eye_visit_attributes);
visitor.on_attribute("output_type", m_output_type); visitor.on_attribute("output_type", m_output_type);
return true; return true;
} }
std::shared_ptr<ov::Node> ov::op::v9::Eye::clone_with_new_inputs(const ov::OutputVector& new_args) const { std::shared_ptr<ov::Node> Eye::clone_with_new_inputs(const ov::OutputVector& new_args) const {
OV_OP_SCOPE(v9_Eye_clone_with_new_inputs); OV_OP_SCOPE(v9_Eye_clone_with_new_inputs);
check_new_args_count(this, new_args); check_new_args_count(this, new_args);
if (new_args.size() == 3) {
return std::make_shared<v9::Eye>(new_args[0], new_args[1], new_args[2], m_output_type); switch (new_args.size()) {
} else if (new_args.size() == 4) { case 3:
return std::make_shared<v9::Eye>(new_args[0], new_args[1], new_args[2], new_args[3], m_output_type); return std::make_shared<Eye>(new_args[0], new_args[1], new_args[2], m_output_type);
} else { case 4:
return std::make_shared<Eye>(new_args[0], new_args[1], new_args[2], new_args[3], m_output_type);
default:
OPENVINO_THROW("Eye has incorrect input number: ", new_args.size()); OPENVINO_THROW("Eye has incorrect input number: ", new_args.size());
} }
} }
bool ov::op::v9::Eye::has_evaluate() const { bool Eye::has_evaluate() const {
OV_OP_SCOPE(v9_Eye_has_evaluate); OV_OP_SCOPE(v9_Eye_has_evaluate);
switch (m_output_type) { switch (m_output_type) {
case ov::element::i8: case element::bf16:
case ov::element::u8: case element::f16:
case ov::element::f16: case element::f32:
case ov::element::bf16: case element::f64:
case ov::element::i32: case element::i8:
case ov::element::f32: case element::i32:
case ov::element::i64: case element::i64:
case element::u8:
return true; return true;
default: default:
break; return false;
} }
return false;
} }
bool ov::op::v9::Eye::evaluate(const ngraph::HostTensorVector& outputs, const ngraph::HostTensorVector& inputs) const { bool Eye::evaluate(TensorVector& outputs, const TensorVector& inputs) const {
OV_OP_SCOPE(v9_Eye_evaluate); OV_OP_SCOPE(v9_Eye_evaluate);
OPENVINO_SUPPRESS_DEPRECATED_START OPENVINO_ASSERT(outputs.size() == 1);
OPENVINO_ASSERT(ngraph::validate_host_tensor_vector(inputs, get_input_size()), "Invalid Eye input TensorVector.");
OPENVINO_ASSERT(ngraph::validate_host_tensor_vector(outputs, 1), "Invalid Eye output TensorVector.");
OPENVINO_SUPPRESS_DEPRECATED_END
int64_t diagonal_index;
if (get_input_size() > 1) {
const auto& diagonal_index_data = inputs[2];
switch (diagonal_index_data->get_element_type()) {
case element::i32:
diagonal_index = diagonal_index_data->get_data_ptr<const int32_t>()[0];
break;
case element::i64:
diagonal_index = diagonal_index_data->get_data_ptr<const int64_t>()[0];
break;
default:
OPENVINO_THROW("Unsupported type of input `diagonal_index` in Eye operation: ",
diagonal_index_data->get_element_type().to_string());
}
} else {
diagonal_index = 0;
}
std::vector<ov::PartialShape> input_shapes;
input_shapes.reserve(inputs.size());
for (size_t i = 0; i < inputs.size(); ++i) {
input_shapes.push_back(inputs[i]->get_partial_shape());
}
// Inputs size and shapes checked by shape_infer
const auto input_shapes = util::get_tensors_partial_shapes(inputs);
const auto output_shape = shape_infer(this, input_shapes, make_tensor_accessor(inputs)).front().to_shape(); const auto output_shape = shape_infer(this, input_shapes, make_tensor_accessor(inputs)).front().to_shape();
outputs[0]->set_element_type(get_out_type()); int64_t diagonal_index;
outputs[0]->set_shape(output_shape); const auto& diagonal_tensor = inputs[2];
switch (diagonal_tensor.get_element_type()) {
case element::i32:
diagonal_index = diagonal_tensor.data<const fundamental_type_for<element::i32>>()[0];
break;
case element::i64:
diagonal_index = diagonal_tensor.data<const fundamental_type_for<element::i64>>()[0];
break;
default:
OPENVINO_THROW("Unsupported type of input `diagonal_index` in Eye operation: ",
diagonal_tensor.get_element_type().to_string());
}
return eye::evaluate_eye(outputs[0], diagonal_index); outputs[0].set_shape(output_shape);
using namespace ov::element;
return IfTypeOf<bf16, f16, f32, f64, i8, i32, i64, u8>::apply<eye::Evaluate>(outputs[0].get_element_type(),
outputs[0],
output_shape,
diagonal_index);
} }
} // namespace v9
} // namespace op } // namespace op
} // namespace ov } // namespace ov

View File

@ -4,6 +4,8 @@
#include "ngraph/op/util/evaluate_helpers.hpp" #include "ngraph/op/util/evaluate_helpers.hpp"
#include "openvino/op/util/evaluate_helpers.hpp"
namespace ngraph { namespace ngraph {
AxisSet get_normalized_axes_from_tensor(const HostTensorPtr tensor, AxisSet get_normalized_axes_from_tensor(const HostTensorPtr tensor,
const ngraph::Rank& rank, const ngraph::Rank& rank,
@ -15,3 +17,18 @@ AxisSet get_normalized_axes_from_tensor(const HostTensorPtr tensor,
return AxisSet{normalized_axes}; return AxisSet{normalized_axes};
} }
} // namespace ngraph } // namespace ngraph
namespace ov {
namespace op {
namespace util {
std::vector<PartialShape> get_tensors_partial_shapes(const TensorVector& tensors) {
std::vector<PartialShape> shapes;
shapes.reserve(tensors.size());
for (const auto& t : tensors) {
shapes.emplace_back(t.get_shape());
}
return shapes;
}
} // namespace util
} // namespace op
} // namespace ov