[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:
1 parent
5c6b7a5ed4
commit
cec6535eaa
8 files changed
+78
-69
No files matched your search
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -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
|
||||
+3
-3
@@ -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}));
|
||||
}
|
||||
Reference in new issue
Block a user