[core]Migrate Transpose operator to new API (#20647)

* Migrate Transpose to new API

* Move shape validation to shape_infer

* Remove visit_attributes is same as base

* Correct transpose order shape check
for static shapes
- correct creation of order shape for static shape tests

---------

Co-authored-by: Michal Lukaszewski <michal.lukaszewski@intel.com>
This commit is contained in:
Pawel RaaszandMichal Lukaszewski authored and GitHub committed 2023-10-30 07:05:17 +01:00
1 parent 5c6b7a5ed4
commit cec6535eaa
8 files changed
+78 -69

No files matched your search

+1 -5
View File
@@ -27,15 +27,11 @@ public:
///
Transpose(const Output<Node>& arg, const Output<Node>& input_order);
bool visit_attributes(AttributeVisitor& visitor) override;
void validate_and_infer_types() override;
std::shared_ptr<Node> clone_with_new_inputs(const OutputVector& new_args) const override;
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 evaluate_upper(TensorVector& output_values) const override;
bool evaluate_lower(TensorVector& output_values) const override;
bool has_evaluate() const override;
@@ -636,7 +636,7 @@ void InterpolateEval<T>::multidim_pil_func(const T* input_data, T* out, const in
reinterpret_cast<char*>(transposed_in.data()),
m_input_data_shape,
sizeof(T),
in_transp_axes_order.data(),
in_transp_axes_order,
transp_input_shape);
std::vector<T> transposed_out(shape_size(m_out_shape));
@@ -667,7 +667,7 @@ void InterpolateEval<T>::multidim_pil_func(const T* input_data, T* out, const in
reinterpret_cast<char*>(out),
transp_output_shape,
sizeof(T),
out_transp_axes_order.data(),
out_transp_axes_order,
m_out_shape);
}
}
@@ -13,11 +13,22 @@
namespace ov {
namespace reference {
/**
* @brief Reference implementation of Transpose operator.
*
* @param data Pointer to input data.
* @param out Pointer to output data.
* @param data_shape Input data shape.
* @param element_size Element size in bytes for input and output.
* @param axes_order Transpose order.
* @param out_shape Output data shape.
*/
void transpose(const char* data,
char* out,
const Shape& data_shape,
size_t element_size,
const int64_t* axes_order,
Shape out_shape);
const std::vector<int64_t>& axes_order,
const Shape& out_shape);
} // namespace reference
} // namespace ov
+1 -1
View File
@@ -404,7 +404,7 @@ void transpose_input(ov::TensorVector& inputs,
reinterpret_cast<char*>(output_ptr.data<T>()),
input_shape,
element_type.size(),
permutation.data(),
permutation,
output_shape);
// update a vector of inputs and input subscripts
+4 -4
View File
@@ -18,12 +18,12 @@ void transpose(const char* data,
char* out,
const Shape& data_shape,
size_t element_size,
const int64_t* axes_order,
Shape out_shape) {
const std::vector<int64_t>& axes_order,
const Shape& out_shape) {
// To reuse reference::reshape axes order vector has to be converted to AxisVector
// Negative axes are not supported, it is validated by transpose evaluate method
std::vector<size_t> axis_vector(axes_order, axes_order + data_shape.size());
reshape(data, out, data_shape, axis_vector, out_shape, element_size);
const AxisVector axes_vector(axes_order.begin(), axes_order.end());
reshape(data, out, data_shape, axes_vector, out_shape, element_size);
}
} // namespace reference
} // namespace ov
@@ -62,12 +62,25 @@ template <class TShape, class TRShape = result_shape_t<TShape>>
std::vector<TRShape> shape_infer(const Transpose* op,
const std::vector<TShape>& input_shapes,
const ITensorAccessor& tensor_accessor = make_tensor_accessor()) {
OPENVINO_ASSERT(input_shapes.size() == 2);
const auto& input_shape = input_shapes[Transpose::ARG];
const auto& input_order_shape = input_shapes[Transpose::ORDER];
const auto input_rank = input_shape.rank();
if (input_order_shape.rank().is_static()) {
NODE_SHAPE_INFER_CHECK(op, input_shapes, input_order_shape.size() == 1, "Input order must be a vector.");
NODE_SHAPE_INFER_CHECK(
op,
input_shapes,
input_order_shape[0].compatible(input_rank.get_max_length()) || input_order_shape[0] == 0,
"Input order must have shape [n], where n is the rank of arg.");
}
const auto axes = get_input_const_data_as<TShape, int64_t>(op, Transpose::ORDER, tensor_accessor);
auto output_shapes = std::vector<TRShape>();
if (axes && input_shape.rank().is_static()) {
if (axes && input_rank.is_static()) {
output_shapes.push_back(calc_output_shape(op, input_shape, *axes));
} else if (axes) {
output_shapes.push_back(ov::PartialShape::dynamic(axes->size()));
+40 -51
View File
@@ -2,99 +2,88 @@
// SPDX-License-Identifier: Apache-2.0
//
#include "ngraph/op/transpose.hpp"
#include "openvino/op/transpose.hpp"
#include "bound_evaluate.hpp"
#include "itt.hpp"
#include "ngraph/validation_util.hpp"
#include "openvino/core/validation_util.hpp"
#include "openvino/reference/transpose.hpp"
#include "transpose_shape_inference.hpp"
using namespace std;
using namespace ngraph;
namespace ov {
namespace op {
namespace v1 {
op::v1::Transpose::Transpose(const Output<Node>& arg, const Output<Node>& input_order) : Op({arg, input_order}) {
Transpose::Transpose(const Output<Node>& arg, const Output<Node>& input_order) : Op({arg, input_order}) {
constructor_validate_and_infer_types();
}
bool op::v1::Transpose::visit_attributes(AttributeVisitor& visitor) {
OV_OP_SCOPE(v1_Transpose_visit_attributes);
return true;
}
void op::v1::Transpose::validate_and_infer_types() {
void Transpose::validate_and_infer_types() {
OV_OP_SCOPE(v1_Transpose_validate_and_infer_types);
const auto& input_order_et = get_input_element_type(ORDER);
NODE_VALIDATION_CHECK(this,
input_order_et.is_dynamic() || input_order_et.is_integral_number(),
"Input order must have an integral number element type.");
const auto& input_order_shape = get_input_partial_shape(ORDER);
NODE_VALIDATION_CHECK(this, input_order_shape.rank().compatible(1), "Input order must be a vector.");
const auto& arg_shape = get_input_partial_shape(ARG);
NODE_VALIDATION_CHECK(
this,
input_order_shape.compatible(ov::PartialShape{arg_shape.rank()}) ||
(input_order_shape.is_static() && input_order_shape.rank() == 1 && input_order_shape[0] == 0),
"Input order must have shape [n], where n is the rank of arg.");
set_input_is_relevant_to_shape(ORDER);
std::vector<ov::PartialShape> input_shapes{arg_shape, input_order_shape};
std::vector<ov::PartialShape> output_shapes = shape_infer(this, input_shapes);
OPENVINO_SUPPRESS_DEPRECATED_START
const auto input_shapes = get_node_input_partial_shapes(*this);
OPENVINO_SUPPRESS_DEPRECATED_END
const auto output_shapes = shape_infer(this, input_shapes);
set_output_type(ARG, get_input_element_type(ARG), output_shapes[ARG_T]);
}
shared_ptr<Node> op::v1::Transpose::clone_with_new_inputs(const OutputVector& new_args) const {
std::shared_ptr<Node> Transpose::clone_with_new_inputs(const OutputVector& new_args) const {
OV_OP_SCOPE(v1_Transpose_clone_with_new_inputs);
check_new_args_count(this, new_args);
return make_shared<v1::Transpose>(new_args[ARG], new_args[ORDER]);
return std::make_shared<Transpose>(new_args[ARG], new_args[ORDER]);
}
OPENVINO_SUPPRESS_DEPRECATED_START
bool op::v1::Transpose::evaluate(const HostTensorVector& output_values, const HostTensorVector& input_values) const {
bool Transpose::evaluate(TensorVector& outputs, const TensorVector& inputs) const {
OV_OP_SCOPE(v1_Transpose_evaluate);
OPENVINO_ASSERT(outputs.size() == 1);
OPENVINO_ASSERT(inputs.size() == 2);
const auto& order = input_values[ORDER];
OPENVINO_ASSERT(order->get_element_type().is_integral_number(),
"Transpose axis element type has to be integral data type.");
const auto& order = inputs[ORDER];
if (order.get_element_type().is_integral()) {
const auto& arg = inputs[ARG];
auto axes_order = ov::get_tensor_data_as<int64_t>(order);
const auto out_shape = calc_output_shape(this, arg.get_shape(), axes_order);
const auto& arg = input_values[ARG];
OPENVINO_SUPPRESS_DEPRECATED_START
std::vector<int64_t> axes_order = host_tensor_2_vector<int64_t>(order);
OPENVINO_SUPPRESS_DEPRECATED_END
auto out_shape = calc_output_shape(this, arg->get_shape(), axes_order);
auto& out = output_values[ARG_T];
out->set_shape(out_shape);
out->set_element_type(arg->get_element_type());
ov::reference::transpose(arg->get_data_ptr<char>(),
out->get_data_ptr<char>(),
arg->get_shape(),
arg->get_element_type().size(),
axes_order.data(),
auto& out = outputs[ARG_T];
out.set_shape(out_shape);
reference::transpose(static_cast<const char*>(arg.data()),
static_cast<char*>(out.data()),
arg.get_shape(),
arg.get_element_type().size(),
axes_order,
out_shape);
return true;
return true;
} else {
return false;
}
}
OPENVINO_SUPPRESS_DEPRECATED_END
bool op::v1::Transpose::has_evaluate() const {
bool Transpose::has_evaluate() const {
OV_OP_SCOPE(v1_Transpose_has_evaluate);
return get_input_element_type(1).is_integral_number();
return get_input_element_type(ORDER).is_integral_number();
}
bool op::v1::Transpose::evaluate_lower(ov::TensorVector& output_values) const {
bool Transpose::evaluate_lower(ov::TensorVector& output_values) const {
return get_input_tensor(ORDER).has_and_set_bound() && default_lower_bound_evaluator(this, output_values);
}
bool op::v1::Transpose::evaluate_upper(ov::TensorVector& output_values) const {
bool Transpose::evaluate_upper(ov::TensorVector& output_values) const {
return get_input_tensor(ORDER).has_and_set_bound() && default_upper_bound_evaluator(this, output_values);
}
bool op::v1::Transpose::evaluate_label(TensorLabelVector& output_labels) const {
bool Transpose::evaluate_label(TensorLabelVector& output_labels) const {
OPENVINO_SUPPRESS_DEPRECATED_START
return get_input_tensor(ORDER).has_and_set_bound() && default_label_evaluator(this, output_labels);
OPENVINO_SUPPRESS_DEPRECATED_END
}
} // namespace v1
} // namespace op
} // namespace ov
@@ -68,7 +68,7 @@ INSTANTIATE_TEST_SUITE_P(
/** \brief Check shape_infer for transpose on static shapes. */
TEST_P(StaticShapeInferenceTest, transpose_static) {
auto output_shapes = shape_inference(transpose.get(), {input_shape, transpose_order});
auto output_shapes = shape_inference(transpose.get(), {input_shape, StaticShape{transpose_order.size()}});
ASSERT_EQ(output_shapes[op::v1::Transpose::ARG_T], exp_shape);
}
@@ -79,7 +79,7 @@ TEST(StaticShapeInferenceTest, transpose_input_shape_dim_dynamic) {
const auto order = std::vector<size_t>{1, 2, 0};
const auto transpose = make_transpose(input_shape, order);
auto output_shapes = shape_inference(transpose.get(), {StaticShape{2, 6, 3}, order});
auto output_shapes = shape_inference(transpose.get(), {StaticShape{2, 6, 3}, StaticShape{order.size()}});
ASSERT_EQ(output_shapes[op::v1::Transpose::ARG_T], StaticShape({6, 3, 2}));
}
@@ -96,7 +96,7 @@ TEST(StaticShapeInferenceTest, transpose_order_in_constant_map) {
const std::unordered_map<size_t, ov::Tensor> const_map = {{1, const_tensor}};
auto output_shapes = std::vector<StaticShape>{StaticShape{}};
output_shapes = shape_inference(transpose.get(), {StaticShape({2, 4, 6, 8}), StaticShape()}, const_map);
output_shapes = shape_inference(transpose.get(), {StaticShape({2, 4, 6, 8}), StaticShape({0})}, const_map);
ASSERT_EQ(output_shapes[op::v1::Transpose::ARG_T], StaticShape({4, 6, 2, 8}));
}