[core] Migrate ShapeOf operator to new API (#21143)
* Drop legacy stuff
* Drop HostTensor
* Remove unused element types support
* Revert "Remove unused element types support"
This reverts commit 2ca8280c56.
* Improve style
This commit is contained in:
1 parent
af27b6f16a
commit
ffa6e8458d
2 files changed
+81
-143
No files matched your search
@@ -32,9 +32,6 @@ public:
|
||||
// Overload collision with method on Node
|
||||
using Node::set_output_type;
|
||||
|
||||
OPENVINO_SUPPRESS_DEPRECATED_START
|
||||
bool evaluate(const HostTensorVector& output_values, const HostTensorVector& input_values) const override;
|
||||
OPENVINO_SUPPRESS_DEPRECATED_END
|
||||
bool has_evaluate() const override;
|
||||
bool evaluate(TensorVector& output_values, const TensorVector& input_values) const override;
|
||||
bool evaluate_lower(TensorVector& output_values) const override;
|
||||
@@ -57,14 +54,10 @@ public:
|
||||
/// \brief Constructs a shape-of operation.
|
||||
ShapeOf(const Output<Node>& arg);
|
||||
|
||||
bool visit_attributes(AttributeVisitor& visitor) override;
|
||||
std::shared_ptr<Node> clone_with_new_inputs(const OutputVector& new_args) const override;
|
||||
|
||||
void validate_and_infer_types() override;
|
||||
|
||||
OPENVINO_SUPPRESS_DEPRECATED_START
|
||||
bool evaluate(const HostTensorVector& output_values, const HostTensorVector& input_values) const override;
|
||||
OPENVINO_SUPPRESS_DEPRECATED_END
|
||||
bool has_evaluate() const override;
|
||||
bool evaluate(TensorVector& output_values, const TensorVector& input_values) const override;
|
||||
bool evaluate_lower(TensorVector& output_values) const override;
|
||||
|
||||
+81
-136
@@ -2,88 +2,30 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "ngraph/op/shape_of.hpp"
|
||||
#include "openvino/op/shape_of.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <ngraph/validation_util.hpp>
|
||||
#include <vector>
|
||||
|
||||
#include "itt.hpp"
|
||||
#include "ngraph/op/concat.hpp"
|
||||
#include "ngraph/op/constant.hpp"
|
||||
#include "ngraph/op/gather.hpp"
|
||||
#include "ngraph/op/select.hpp"
|
||||
#include "ngraph/runtime/host_tensor.hpp"
|
||||
#include "ngraph/type/element_type_traits.hpp"
|
||||
#include "openvino/core/dimension_tracker.hpp"
|
||||
#include "openvino/op/constant.hpp"
|
||||
#include "openvino/op/select.hpp"
|
||||
#include "openvino/reference/shape_of.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace ngraph;
|
||||
|
||||
op::v3::ShapeOf::ShapeOf(const Output<Node>& arg, element::Type output_type)
|
||||
: ShapeOfBase({arg}),
|
||||
m_output_type(output_type) {
|
||||
constructor_validate_and_infer_types();
|
||||
}
|
||||
|
||||
void op::v3::ShapeOf::validate_and_infer_types() {
|
||||
OV_OP_SCOPE(v3_ShapeOf_validate_and_infer_types);
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
m_output_type == element::i64 || m_output_type == element::i32,
|
||||
"Output type must be i32 or i64");
|
||||
set_input_is_relevant_to_value(0, false);
|
||||
const auto input_partial_shape = get_input_partial_shape(0);
|
||||
set_output_type(0, m_output_type, ov::PartialShape{input_partial_shape.rank()});
|
||||
}
|
||||
|
||||
bool ngraph::op::v3::ShapeOf::visit_attributes(AttributeVisitor& visitor) {
|
||||
OV_OP_SCOPE(v3_ShapeOf_visit_attributes);
|
||||
visitor.on_attribute("output_type", m_output_type);
|
||||
return true;
|
||||
}
|
||||
|
||||
shared_ptr<Node> op::v3::ShapeOf::clone_with_new_inputs(const OutputVector& new_args) const {
|
||||
OV_OP_SCOPE(v3_ShapeOf_clone_with_new_inputs);
|
||||
check_new_args_count(this, new_args);
|
||||
auto new_shape_of = make_shared<op::v3::ShapeOf>(new_args.at(0), m_output_type);
|
||||
return new_shape_of;
|
||||
}
|
||||
|
||||
OPENVINO_SUPPRESS_DEPRECATED_START
|
||||
namespace ov {
|
||||
namespace op {
|
||||
namespace shape_of {
|
||||
namespace {
|
||||
template <element::Type_t ET>
|
||||
inline bool evaluate(const ov::Shape& shape, const HostTensorPtr& output_value) {
|
||||
ov::reference::shape_of(shape, output_value->get_data_ptr<ET>());
|
||||
inline bool evaluate(const Shape& shape, Tensor& output_value) {
|
||||
reference::shape_of(shape, output_value.data<fundamental_type_for<ET>>());
|
||||
return true;
|
||||
}
|
||||
|
||||
template <element::Type_t ET>
|
||||
inline bool evaluate(const ov::Shape& shape, ov::Tensor& output_value) {
|
||||
ov::reference::shape_of(shape, output_value.data<fundamental_type_for<ET>>());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool evaluate_shape_of(const HostTensorPtr& output_value, const HostTensorPtr& input_value) {
|
||||
bool rc = true;
|
||||
ov::Shape shape = input_value->get_shape();
|
||||
output_value->set_shape(ov::Shape{shape.size()});
|
||||
switch (output_value->get_element_type()) {
|
||||
OPENVINO_TYPE_CASE(evaluate_shape_of, i32, shape, output_value);
|
||||
OPENVINO_TYPE_CASE(evaluate_shape_of, i64, shape, output_value);
|
||||
OPENVINO_TYPE_CASE(evaluate_shape_of, u32, shape, output_value);
|
||||
OPENVINO_TYPE_CASE(evaluate_shape_of, u64, shape, output_value);
|
||||
default:
|
||||
rc = false;
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
bool evaluate_shape_of(ov::Tensor& output_value, const Shape& input_shape) {
|
||||
bool evaluate_shape_of(Tensor& output_value, const Shape& input_shape) {
|
||||
bool rc;
|
||||
output_value.set_shape(ov::Shape{input_shape.size()});
|
||||
output_value.set_shape(Shape{input_shape.size()});
|
||||
switch (output_value.get_element_type()) {
|
||||
OPENVINO_TYPE_CASE(evaluate_shape_of, i32, input_shape, output_value);
|
||||
OPENVINO_TYPE_CASE(evaluate_shape_of, i64, input_shape, output_value);
|
||||
@@ -97,29 +39,26 @@ bool evaluate_shape_of(ov::Tensor& output_value, const Shape& input_shape) {
|
||||
}
|
||||
|
||||
bool constant_fold_shape_of(Node* shape_of_node, Output<Node>& replacement, const Output<Node>& shape_of_input) {
|
||||
auto partial_shape = shape_of_input.get_partial_shape();
|
||||
auto output_type = shape_of_node->get_output_element_type(0);
|
||||
const auto& partial_shape = shape_of_input.get_partial_shape();
|
||||
if (partial_shape.is_static()) {
|
||||
auto arg_shape = shape_of_input.get_shape();
|
||||
OPENVINO_SUPPRESS_DEPRECATED_START
|
||||
auto result_tensor = make_shared<HostTensor>(output_type, shape_of_node->get_output_shape(0));
|
||||
if (evaluate_shape_of(result_tensor, make_shared<HostTensor>(output_type, partial_shape))) {
|
||||
replacement = make_shared<op::Constant>(result_tensor);
|
||||
const auto& output_type = shape_of_node->get_output_element_type(0);
|
||||
const auto& output_shape = shape_of_node->get_output_shape(0);
|
||||
auto result_tensor = ov::Tensor{output_type, output_shape};
|
||||
if (evaluate_shape_of(result_tensor, shape_of_input.get_shape())) {
|
||||
replacement = std::make_shared<v0::Constant>(result_tensor);
|
||||
return true;
|
||||
}
|
||||
OPENVINO_SUPPRESS_DEPRECATED_END
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool evaluate_bound_shape(const Node* shape_of_node, ov::TensorVector& output_values, bool is_upper) {
|
||||
bool evaluate_bound_shape(const Node* shape_of_node, TensorVector& output_values, bool is_upper) {
|
||||
OPENVINO_ASSERT(shape_of_node, output_values.size() == 1);
|
||||
const auto& input_partial_shape = shape_of_node->get_input_partial_shape(0);
|
||||
if (input_partial_shape.rank().is_dynamic())
|
||||
return false;
|
||||
const auto rank = input_partial_shape.rank().get_length();
|
||||
auto pshape_low = ov::PartialShape::dynamic(rank), pshape_up = ov::PartialShape::dynamic(rank);
|
||||
auto pshape_low = PartialShape::dynamic(rank), pshape_up = PartialShape::dynamic(rank);
|
||||
for (Dimension::value_type i = 0; i < rank; ++i) {
|
||||
Interval interval = input_partial_shape[i].get_interval();
|
||||
pshape_low[i] = interval.get_min_val();
|
||||
@@ -132,24 +71,24 @@ bool evaluate_bound_shape(const Node* shape_of_node, ov::TensorVector& output_va
|
||||
if (pshape_low.to_shape() == pshape_up.to_shape()) {
|
||||
shape_of::evaluate_shape_of(output_values[0], pshape_low.to_shape());
|
||||
} else {
|
||||
auto&& upper = is_upper ? output_values : ov::TensorVector{{output_et, Shape{pshape_up.to_shape().size()}}};
|
||||
auto&& upper = is_upper ? output_values : TensorVector{{output_et, Shape{pshape_up.to_shape().size()}}};
|
||||
shape_of::evaluate_shape_of(upper[0], pshape_up.to_shape());
|
||||
|
||||
auto&& lower = is_upper ? ov::TensorVector{{output_et, Shape{pshape_low.to_shape().size()}}} : output_values;
|
||||
auto&& lower = is_upper ? TensorVector{{output_et, Shape{pshape_low.to_shape().size()}}} : output_values;
|
||||
shape_of::evaluate_shape_of(lower[0], pshape_low.to_shape());
|
||||
|
||||
vector<char> dynamic_mask; // true if dimension is dynamic
|
||||
std::vector<char> dynamic_mask; // true if dimension is dynamic
|
||||
for (const auto& i : input_partial_shape)
|
||||
dynamic_mask.push_back(static_cast<char>(Dimension(i.get_interval().get_max_val()).is_dynamic()));
|
||||
|
||||
const auto mask_const = ov::Tensor(element::boolean, Shape{dynamic_mask.size()}, dynamic_mask.data());
|
||||
const auto mask_const = Tensor(element::boolean, Shape{dynamic_mask.size()}, dynamic_mask.data());
|
||||
|
||||
auto&& min = output_et == element::i64 ? static_cast<int64_t>(0) : static_cast<int32_t>(0);
|
||||
auto&& max =
|
||||
output_et == element::i64 ? std::numeric_limits<int64_t>::max() : std::numeric_limits<int32_t>::max();
|
||||
|
||||
op::v1::Select().evaluate(lower, {mask_const, {output_et, Shape{}, &min}, lower.front()});
|
||||
op::v1::Select().evaluate(upper, {mask_const, {output_et, Shape{}, &max}, upper.front()});
|
||||
v1::Select().evaluate(lower, {mask_const, {output_et, Shape{}, &min}, lower.front()});
|
||||
v1::Select().evaluate(upper, {mask_const, {output_et, Shape{}, &max}, upper.front()});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -160,7 +99,7 @@ bool evaluate_label(const Node* shape_of_node, TensorLabelVector& output_labels)
|
||||
output_labels[0].reserve(shape.size());
|
||||
bool label_is_set = false;
|
||||
for (const auto& d : shape) {
|
||||
const auto& label = ov::DimensionTracker::get_label(d);
|
||||
const auto& label = DimensionTracker::get_label(d);
|
||||
if (label)
|
||||
label_is_set = true;
|
||||
output_labels[0].push_back(label);
|
||||
@@ -170,16 +109,34 @@ bool evaluate_label(const Node* shape_of_node, TensorLabelVector& output_labels)
|
||||
} // namespace
|
||||
} // namespace shape_of
|
||||
|
||||
bool op::v3::ShapeOf::evaluate(const HostTensorVector& output_values, const HostTensorVector& input_values) const {
|
||||
OV_OP_SCOPE(v3_ShapeOf_evaluate);
|
||||
OPENVINO_SUPPRESS_DEPRECATED_START
|
||||
OPENVINO_ASSERT(validate_host_tensor_vector(input_values, 1));
|
||||
OPENVINO_ASSERT(validate_host_tensor_vector(output_values, 1));
|
||||
OPENVINO_SUPPRESS_DEPRECATED_END
|
||||
return shape_of::evaluate_shape_of(output_values[0], input_values[0]);
|
||||
namespace v3 {
|
||||
ShapeOf::ShapeOf(const Output<Node>& arg, element::Type output_type) : ShapeOfBase({arg}), m_output_type(output_type) {
|
||||
constructor_validate_and_infer_types();
|
||||
}
|
||||
|
||||
bool op::v3::ShapeOf::evaluate(ov::TensorVector& output_values, const ov::TensorVector& input_values) const {
|
||||
void ShapeOf::validate_and_infer_types() {
|
||||
OV_OP_SCOPE(v3_ShapeOf_validate_and_infer_types);
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
m_output_type == element::i64 || m_output_type == element::i32,
|
||||
"Output type must be i32 or i64");
|
||||
set_input_is_relevant_to_value(0, false);
|
||||
const auto input_partial_shape = get_input_partial_shape(0);
|
||||
set_output_type(0, m_output_type, PartialShape{input_partial_shape.rank()});
|
||||
}
|
||||
|
||||
bool ShapeOf::visit_attributes(AttributeVisitor& visitor) {
|
||||
OV_OP_SCOPE(v3_ShapeOf_visit_attributes);
|
||||
visitor.on_attribute("output_type", m_output_type);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::shared_ptr<Node> ShapeOf::clone_with_new_inputs(const OutputVector& new_args) const {
|
||||
OV_OP_SCOPE(v3_ShapeOf_clone_with_new_inputs);
|
||||
check_new_args_count(this, new_args);
|
||||
return std::make_shared<ShapeOf>(new_args.at(0), m_output_type);
|
||||
}
|
||||
|
||||
bool ShapeOf::evaluate(TensorVector& output_values, const TensorVector& input_values) const {
|
||||
OV_OP_SCOPE(v0_ShapeOf_evaluate);
|
||||
OPENVINO_ASSERT(input_values.size() == 1);
|
||||
OPENVINO_ASSERT(output_values.size() == 1);
|
||||
@@ -187,60 +144,55 @@ bool op::v3::ShapeOf::evaluate(ov::TensorVector& output_values, const ov::Tensor
|
||||
return shape_of::evaluate_shape_of(output_values[0], input_values[0].get_shape());
|
||||
}
|
||||
|
||||
bool op::v3::ShapeOf::has_evaluate() const {
|
||||
bool ShapeOf::has_evaluate() const {
|
||||
OV_OP_SCOPE(v3_ShapeOf_has_evaluate);
|
||||
switch (get_output_element_type(0)) {
|
||||
case ngraph::element::i32:
|
||||
case ngraph::element::i64:
|
||||
case ngraph::element::u32:
|
||||
case ngraph::element::u64:
|
||||
case element::i32:
|
||||
case element::i64:
|
||||
case element::u32:
|
||||
case element::u64:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool op::v3::ShapeOf::evaluate_lower(ov::TensorVector& output_values) const {
|
||||
bool ShapeOf::evaluate_lower(TensorVector& output_values) const {
|
||||
return shape_of::evaluate_bound_shape(this, output_values, false);
|
||||
}
|
||||
|
||||
bool op::v3::ShapeOf::evaluate_upper(ov::TensorVector& output_values) const {
|
||||
bool ShapeOf::evaluate_upper(TensorVector& output_values) const {
|
||||
return shape_of::evaluate_bound_shape(this, output_values, true);
|
||||
}
|
||||
|
||||
bool op::v3::ShapeOf::evaluate_label(TensorLabelVector& output_labels) const {
|
||||
bool ShapeOf::evaluate_label(TensorLabelVector& output_labels) const {
|
||||
return shape_of::evaluate_label(this, output_labels);
|
||||
}
|
||||
|
||||
bool op::v3::ShapeOf::constant_fold(OutputVector& output_values, const OutputVector& input_values) {
|
||||
bool ShapeOf::constant_fold(OutputVector& output_values, const OutputVector& input_values) {
|
||||
OV_OP_SCOPE(v3_ShapeOf_constant_fold);
|
||||
if (is_const_fold_disabled()) {
|
||||
return false;
|
||||
}
|
||||
return shape_of::constant_fold_shape_of(this, output_values[0], input_values[0]);
|
||||
}
|
||||
} // namespace v3
|
||||
|
||||
// op::v0::ShapeOf
|
||||
op::v0::ShapeOf::ShapeOf(const Output<Node>& arg) : ShapeOfBase({arg}) {
|
||||
namespace v0 {
|
||||
ShapeOf::ShapeOf(const Output<Node>& arg) : ShapeOfBase({arg}) {
|
||||
constructor_validate_and_infer_types();
|
||||
}
|
||||
|
||||
void op::v0::ShapeOf::validate_and_infer_types() {
|
||||
void ShapeOf::validate_and_infer_types() {
|
||||
OV_OP_SCOPE(v0_ShapeOf_validate_and_infer_types);
|
||||
set_input_is_relevant_to_value(0, false);
|
||||
set_output_type(0, element::i64, ov::PartialShape{get_input_partial_shape(0).rank()});
|
||||
set_output_type(0, element::i64, PartialShape{get_input_partial_shape(0).rank()});
|
||||
}
|
||||
|
||||
bool ngraph::op::v0::ShapeOf::visit_attributes(AttributeVisitor& visitor) {
|
||||
OV_OP_SCOPE(v0_ShapeOf_visit_attributes);
|
||||
return true;
|
||||
}
|
||||
|
||||
shared_ptr<Node> op::v0::ShapeOf::clone_with_new_inputs(const OutputVector& new_args) const {
|
||||
std::shared_ptr<Node> ShapeOf::clone_with_new_inputs(const OutputVector& new_args) const {
|
||||
OV_OP_SCOPE(v0_ShapeOf_clone_with_new_inputs);
|
||||
check_new_args_count(this, new_args);
|
||||
auto new_shape_of = make_shared<op::v0::ShapeOf>(new_args.at(0));
|
||||
auto new_shape_of = std::make_shared<v0::ShapeOf>(new_args.at(0));
|
||||
OPENVINO_ASSERT(new_shape_of.get(),
|
||||
new_shape_of != nullptr,
|
||||
"Cannot clone ",
|
||||
@@ -250,16 +202,7 @@ shared_ptr<Node> op::v0::ShapeOf::clone_with_new_inputs(const OutputVector& new_
|
||||
return new_shape_of;
|
||||
}
|
||||
|
||||
bool op::v0::ShapeOf::evaluate(const HostTensorVector& output_values, const HostTensorVector& input_values) const {
|
||||
OV_OP_SCOPE(v0_ShapeOf_evaluate);
|
||||
OPENVINO_SUPPRESS_DEPRECATED_START
|
||||
OPENVINO_ASSERT(validate_host_tensor_vector(input_values, 1));
|
||||
OPENVINO_ASSERT(validate_host_tensor_vector(output_values, 1));
|
||||
OPENVINO_SUPPRESS_DEPRECATED_END
|
||||
return shape_of::evaluate_shape_of(output_values[0], input_values[0]);
|
||||
}
|
||||
|
||||
bool op::v0::ShapeOf::evaluate(ov::TensorVector& output_values, const ov::TensorVector& input_values) const {
|
||||
bool ShapeOf::evaluate(TensorVector& output_values, const TensorVector& input_values) const {
|
||||
OV_OP_SCOPE(v0_ShapeOf_evaluate);
|
||||
OPENVINO_ASSERT(input_values.size() == 1);
|
||||
OPENVINO_ASSERT(output_values.size() == 1);
|
||||
@@ -267,21 +210,20 @@ bool op::v0::ShapeOf::evaluate(ov::TensorVector& output_values, const ov::Tensor
|
||||
return shape_of::evaluate_shape_of(output_values[0], input_values[0].get_shape());
|
||||
}
|
||||
|
||||
bool op::v0::ShapeOf::has_evaluate() const {
|
||||
bool ShapeOf::has_evaluate() const {
|
||||
OV_OP_SCOPE(v0_ShapeOf_has_evaluate);
|
||||
switch (get_output_element_type(0)) {
|
||||
case ngraph::element::i32:
|
||||
case ngraph::element::i64:
|
||||
case ngraph::element::u32:
|
||||
case ngraph::element::u64:
|
||||
case element::i32:
|
||||
case element::i64:
|
||||
case element::u32:
|
||||
case element::u64:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool op::v0::ShapeOf::constant_fold(OutputVector& output_values, const OutputVector& input_values) {
|
||||
bool ShapeOf::constant_fold(OutputVector& output_values, const OutputVector& input_values) {
|
||||
OV_OP_SCOPE(v0_ShapeOf_constant_fold);
|
||||
if (is_const_fold_disabled()) {
|
||||
return false;
|
||||
@@ -289,14 +231,17 @@ bool op::v0::ShapeOf::constant_fold(OutputVector& output_values, const OutputVec
|
||||
return shape_of::constant_fold_shape_of(this, output_values[0], input_values[0]);
|
||||
}
|
||||
|
||||
bool op::v0::ShapeOf::evaluate_lower(ov::TensorVector& output_values) const {
|
||||
bool ShapeOf::evaluate_lower(TensorVector& output_values) const {
|
||||
return shape_of::evaluate_bound_shape(this, output_values, false);
|
||||
}
|
||||
|
||||
bool op::v0::ShapeOf::evaluate_upper(ov::TensorVector& output_values) const {
|
||||
bool ShapeOf::evaluate_upper(TensorVector& output_values) const {
|
||||
return shape_of::evaluate_bound_shape(this, output_values, true);
|
||||
}
|
||||
|
||||
bool op::v0::ShapeOf::evaluate_label(TensorLabelVector& output_labels) const {
|
||||
bool ShapeOf::evaluate_label(TensorLabelVector& output_labels) const {
|
||||
return shape_of::evaluate_label(this, output_labels);
|
||||
}
|
||||
} // namespace v0
|
||||
} // namespace op
|
||||
} // namespace ov
|
||||
Reference in new issue
Block a user