Skip to content

Commit

Permalink
[core]Migrate Eye to new API (openvinotoolkit#20258)
Browse files Browse the repository at this point in the history
* Migrate Eye to new API

* Fix `matrix_offset` initialization

* get_tensors_shapes -> get_tensors_partial_shapes
  • Loading branch information
praasz authored and alvoron committed Nov 6, 2023
1 parent 08467a0 commit 9ccbb26
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 101 deletions.
4 changes: 1 addition & 3 deletions src/core/include/openvino/op/eye.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,7 @@ class OPENVINO_API Eye : public Op {
m_output_type = output_type;
}

OPENVINO_SUPPRESS_DEPRECATED_START
bool evaluate(const HostTensorVector& outputs, const HostTensorVector& inputs) const override;
OPENVINO_SUPPRESS_DEPRECATED_END
bool evaluate(TensorVector& outputs, const TensorVector& inputs) const override;
bool has_evaluate() const override;

protected:
Expand Down
23 changes: 23 additions & 0 deletions src/core/include/openvino/op/util/evaluate_helpers.hpp
Original file line number Diff line number Diff line change
@@ -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
32 changes: 21 additions & 11 deletions src/core/reference/include/openvino/reference/eye.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,41 @@
#include <cmath>

#include "openvino/core/shape.hpp"
#include "utils/span.hpp"

namespace ov {
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>
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 int64_t num_rows = out_shape[out_shape.size() - 2];
const int64_t num_columns = out_shape[out_shape.size() - 1];
const auto spatial_dims_offset = out_shape.size() - 2;
const int64_t num_columns = out_shape.back();
const int64_t num_rows = out_shape[spatial_dims_offset];
const int64_t matrix_size = num_rows * num_columns;
const int64_t out_size = shape_size(out_shape);

// 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
const int64_t shift_by_columns = std::max(diagonal_index, int64_t(0));
const int64_t count_by_columns = std::max(num_columns - std::abs(diagonal_index), int64_t(0));
const int64_t count_by_rows = std::max(num_rows - std::abs(diagonal_index), int64_t(0));
constexpr int64_t zero{0};
const auto abs_diag_idx = static_cast<int64_t>(std::abs(diagonal_index));
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 =
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 j = 0; j < count; j++) {
for (auto matrix_offset = zero; matrix_offset < out_size; matrix_offset += matrix_size) {
for (auto j = 0; j < count; ++j) {
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};
}
}
}
Expand Down
152 changes: 65 additions & 87 deletions src/core/src/op/eye.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,62 +4,49 @@

#include "openvino/op/eye.hpp"

#include "element_visitor.hpp"
#include "eye_shape_inference.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"

OPENVINO_SUPPRESS_DEPRECATED_START
namespace ov {
namespace op {
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) {
bool rc = true;
switch (out->get_element_type()) {
OPENVINO_TYPE_CASE(evaluate, i8, out, diagonal_index);
OPENVINO_TYPE_CASE(evaluate, u8, out, diagonal_index);
OPENVINO_TYPE_CASE(evaluate, f16, out, diagonal_index);
OPENVINO_TYPE_CASE(evaluate, bf16, out, diagonal_index);
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;
struct Evaluate : element::NoAction<bool> {
using element::NoAction<bool>::visit;

template <element::Type_t ET, class T = fundamental_type_for<ET>>
static result_type visit(Tensor& out, const Shape& out_shape, const int64_t diagonal_idx) {
reference::eye(out.data<T>(), out_shape, diagonal_idx);
return true;
}
return rc;
}
} // namespace
};
} // namespace eye

ov::op::v9::Eye::Eye(const Output<Node>& num_rows,
const Output<Node>& num_columns,
const Output<Node>& diagonal_index,
const Output<Node>& batch_shape,
const ov::element::Type& out_type)
namespace v9 {
Eye::Eye(const Output<Node>& num_rows,
const Output<Node>& num_columns,
const Output<Node>& diagonal_index,
const Output<Node>& batch_shape,
const ov::element::Type& out_type)
: Op({num_rows, num_columns, diagonal_index, batch_shape}),
m_output_type(out_type) {
constructor_validate_and_infer_types();
}

ov::op::v9::Eye::Eye(const Output<Node>& num_rows,
const Output<Node>& num_columns,
const Output<Node>& diagonal_index,
const ov::element::Type& out_type)
Eye::Eye(const Output<Node>& num_rows,
const Output<Node>& num_columns,
const Output<Node>& diagonal_index,
const ov::element::Type& out_type)
: Op({num_rows, num_columns, diagonal_index}),
m_output_type(out_type) {
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);

for (size_t i = 0; i < get_input_size(); ++i) {
Expand All @@ -78,81 +65,72 @@ void ov::op::v9::Eye::validate_and_infer_types() {
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);
visitor.on_attribute("output_type", m_output_type);
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);
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);
} else if (new_args.size() == 4) {
return std::make_shared<v9::Eye>(new_args[0], new_args[1], new_args[2], new_args[3], m_output_type);
} else {

switch (new_args.size()) {
case 3:
return std::make_shared<Eye>(new_args[0], new_args[1], new_args[2], m_output_type);
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());
}
}

bool ov::op::v9::Eye::has_evaluate() const {
bool Eye::has_evaluate() const {
OV_OP_SCOPE(v9_Eye_has_evaluate);
switch (m_output_type) {
case ov::element::i8:
case ov::element::u8:
case ov::element::f16:
case ov::element::bf16:
case ov::element::i32:
case ov::element::f32:
case ov::element::i64:
case element::bf16:
case element::f16:
case element::f32:
case element::f64:
case element::i8:
case element::i32:
case element::i64:
case element::u8:
return true;
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);
OPENVINO_SUPPRESS_DEPRECATED_START
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());
}
OPENVINO_ASSERT(outputs.size() == 1);

// 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();

outputs[0]->set_element_type(get_out_type());
outputs[0]->set_shape(output_shape);
int64_t diagonal_index;
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 ov
17 changes: 17 additions & 0 deletions src/core/src/op/util/evaluate_helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

#include "ngraph/op/util/evaluate_helpers.hpp"

#include "openvino/op/util/evaluate_helpers.hpp"

namespace ngraph {
AxisSet get_normalized_axes_from_tensor(const HostTensorPtr tensor,
const ngraph::Rank& rank,
Expand All @@ -15,3 +17,18 @@ AxisSet get_normalized_axes_from_tensor(const HostTensorPtr tensor,
return AxisSet{normalized_axes};
}
} // 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

0 comments on commit 9ccbb26

Please sign in to comment.