Skip to content

Commit

Permalink
[core]Migrate VariadicSplit op to new API (openvinotoolkit#20416)
Browse files Browse the repository at this point in the history
* Migrate VariadicSlice to new API
- refactor to reduce bin size

* Move `get_tensors_partial_shapes` to dev API

* Use get_tensors_partial_shapes in VariadicSplit

* Remove `visit_attributes` is same as base
  • Loading branch information
praasz authored Oct 18, 2023
1 parent 6c396fa commit f2549f2
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 102 deletions.
10 changes: 1 addition & 9 deletions src/core/include/openvino/op/variadic_split.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,17 @@ class OPENVINO_API VariadicSplit : public Op {
/// outputs. The sum of split_lengths must match data.shape[axis]
VariadicSplit(const Output<Node>& data, const Output<Node>& axis, const Output<Node>& split_lengths);

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;
size_t get_default_output_index() const override {
return no_default_index();
}
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_lower(TensorVector& outputs) const override;
bool evaluate_upper(TensorVector& outputs) const override;
bool has_evaluate() const override;
bool evaluate_label(TensorLabelVector& output_labels) const override;

private:
bool evaluate_variadic_split(const HostTensorVector& outputs, const HostTensorVector& inputs) const;
bool has_axis_and_splits_bound_set() const;
};
} // namespace v1
} // namespace op
Expand Down
167 changes: 74 additions & 93 deletions src/core/src/op/variadic_split.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,69 @@
// SPDX-License-Identifier: Apache-2.0
//

#include "ngraph/op/variadic_split.hpp"
#include "openvino/op/variadic_split.hpp"

#include <numeric>

#include "bound_evaluate.hpp"
#include "compare.hpp"
#include "itt.hpp"
#include "ngraph/validation_util.hpp"
#include "openvino/core/validation_util.hpp"
#include "openvino/reference/slice.hpp"
#include "variadic_split_shape_inference.hpp"

using namespace std;
using namespace ngraph;
namespace ov {
namespace op {
namespace variadic_split {
namespace {

op::v1::VariadicSplit::VariadicSplit(const Output<Node>& data,
const Output<Node>& axis,
const Output<Node>& split_lengths)
: Op({data, axis, split_lengths}) {
constructor_validate_and_infer_types();
bool has_axis_and_splits_bound_set(const Node* const node) {
return have_node_inputs_bounds_set(node, 1, 2);
}

bool ngraph::op::v1::VariadicSplit::visit_attributes(AttributeVisitor& visitor) {
OV_OP_SCOPE(v1_VariadicSplit_visit_attributes);
bool evaluate(TensorVector& outputs, const TensorVector& inputs) {
const auto& data_tensor = inputs[0];
const auto& axis_tensor = inputs[1];
const auto axis =
ov::util::normalize(get_tensor_data_as<int64_t>(axis_tensor).front(), data_tensor.get_shape().size());

ov::Coordinate upper_bounds(data_tensor.get_shape());
ov::Coordinate lower_bounds(upper_bounds.size());
upper_bounds[axis] = 0;

const Strides default_strides(upper_bounds.size(), 1);
constexpr auto is_zero_dim = ov::cmp::Equal<size_t>(0);

for (auto& output : outputs) {
const auto& out_shape = output.get_shape();
upper_bounds[axis] += out_shape[axis];

if (std::none_of(out_shape.cbegin(), out_shape.cend(), is_zero_dim)) {
reference::slice(static_cast<const char*>(data_tensor.data()),
static_cast<char*>(output.data()),
data_tensor.get_shape(),
lower_bounds,
upper_bounds,
default_strides,
out_shape,
data_tensor.get_element_type().size());
}

lower_bounds[axis] = upper_bounds[axis];
}

return true;
}
} // namespace
} // namespace variadic_split

void ngraph::op::v1::VariadicSplit::validate_and_infer_types() {
namespace v1 {
VariadicSplit::VariadicSplit(const Output<Node>& data, const Output<Node>& axis, const Output<Node>& split_lengths)
: Op({data, axis, split_lengths}) {
constructor_validate_and_infer_types();
}

void VariadicSplit::validate_and_infer_types() {
OV_OP_SCOPE(v1_VariadicSplit_validate_and_infer_types);
for (size_t i = 0; i < get_input_size(); ++i) {
set_input_is_relevant_to_value(i);
Expand All @@ -45,107 +81,52 @@ void ngraph::op::v1::VariadicSplit::validate_and_infer_types() {
}
}

shared_ptr<Node> op::v1::VariadicSplit::clone_with_new_inputs(const OutputVector& new_args) const {
std::shared_ptr<Node> VariadicSplit::clone_with_new_inputs(const OutputVector& new_args) const {
OV_OP_SCOPE(v1_VariadicSplit_clone_with_new_inputs);
check_new_args_count(this, new_args);
return make_shared<v1::VariadicSplit>(new_args.at(0), new_args.at(1), new_args.at(2));
return std::make_shared<VariadicSplit>(new_args.at(0), new_args.at(1), new_args.at(2));
}

OPENVINO_SUPPRESS_DEPRECATED_START
namespace variadic_split {
namespace {
inline bool evaluate(const HostTensorPtr& in,
const HostTensorPtr& out,
const Coordinate& lower_bounds,
const Coordinate& upper_bounds) {
const auto& output_shape = out->get_shape();
const auto has_nonzero_dims = std::none_of(output_shape.begin(), output_shape.end(), ov::cmp::Equal<size_t>(0));

if (has_nonzero_dims) {
ov::reference::slice(in->get_data_ptr<const char>(),
out->get_data_ptr<char>(),
in->get_shape(),
lower_bounds,
upper_bounds,
Strides(lower_bounds.size(), 1),
out->get_shape(),
in->get_element_type().size());
return true;
}
return false;
}
} // namespace
} // namespace variadic_split

bool op::v1::VariadicSplit::evaluate_variadic_split(const HostTensorVector& inputs,
const HostTensorVector& outputs) const {
const auto& data_tensor = inputs[0];
const auto& axis_tensor = inputs[1];
const auto& split_lengths_tensor = inputs[2];
OPENVINO_ASSERT(axis_tensor->get_element_type().is_integral_number(),
"axis element type is not integral data type");
OPENVINO_ASSERT(split_lengths_tensor->get_element_type().is_integral_number(),
"split_lengths element type is not integral data type");

OPENVINO_SUPPRESS_DEPRECATED_START
int64_t axis = host_tensor_2_vector<int64_t>(axis_tensor)[0];
axis = ngraph::normalize_axis(this, axis, data_tensor->get_partial_shape().rank());
OPENVINO_SUPPRESS_DEPRECATED_END
bool VariadicSplit::evaluate(TensorVector& outputs, const TensorVector& inputs) const {
OV_OP_SCOPE(v1_VariadicSplit_evaluate);

std::vector<ov::PartialShape> input_shapes = {data_tensor->get_partial_shape(),
axis_tensor->get_partial_shape(),
split_lengths_tensor->get_partial_shape()};
auto output_shapes = shape_infer(this, input_shapes, make_tensor_accessor(inputs));
if (inputs[1].get_element_type().is_integral_number() && inputs[2].get_element_type().is_integral_number()) {
const auto output_shapes =
shape_infer(this, ov::util::get_tensors_partial_shapes(inputs), make_tensor_accessor(inputs));
OPENVINO_ASSERT(outputs.size() == output_shapes.size());

const auto data_shape = data_tensor->get_shape();
std::vector<size_t> lower_bounds(data_shape.size(), 0);
std::vector<size_t> upper_bounds = data_shape;
upper_bounds[axis] = 0;
auto out_partial_shape = output_shapes.cbegin();
for (auto& output : outputs) {
output.set_shape(out_partial_shape->to_shape());
++out_partial_shape;
}

size_t split_pos = 0;
for (const auto& output : outputs) {
ov::Shape output_shape = output_shapes[split_pos++].get_shape();
upper_bounds[axis] += output_shape[axis];
output->set_shape(output_shape);
variadic_split::evaluate(data_tensor, output, lower_bounds, upper_bounds);
lower_bounds.at(axis) = upper_bounds.at(axis);
return variadic_split::evaluate(outputs, inputs);
} else {
return false;
}

return true;
}
bool op::v1::VariadicSplit::evaluate(const HostTensorVector& outputs, const HostTensorVector& inputs) const {
OV_OP_SCOPE(v1_VariadicSplit_evaluate);
return evaluate_variadic_split(inputs, outputs);
}

bool op::v1::VariadicSplit::has_evaluate() const {
bool VariadicSplit::has_evaluate() const {
OV_OP_SCOPE(v1_VariadicSplit_has_evaluate);
return get_input_element_type(1).is_integral_number() && get_input_element_type(2).is_integral_number();
}

bool op::v1::VariadicSplit::has_axis_and_splits_bound_set() const {
for (size_t i = 1; i < get_input_size(); ++i) {
if (!get_input_tensor(i).has_and_set_bound()) {
return false;
}
}
return true;
}

bool op::v1::VariadicSplit::evaluate_lower(ov::TensorVector& output_values) const {
bool VariadicSplit::evaluate_lower(TensorVector& output_values) const {
OV_OP_SCOPE(v1_Split_evaluate_lower);

return has_axis_and_splits_bound_set() && default_lower_bound_evaluator(this, output_values);
return variadic_split::has_axis_and_splits_bound_set(this) && default_lower_bound_evaluator(this, output_values);
}

bool op::v1::VariadicSplit::evaluate_upper(ov::TensorVector& output_values) const {
bool VariadicSplit::evaluate_upper(TensorVector& output_values) const {
OV_OP_SCOPE(v1_Split_evaluate_upper);

return has_axis_and_splits_bound_set() && default_upper_bound_evaluator(this, output_values);
return variadic_split::has_axis_and_splits_bound_set(this) && default_upper_bound_evaluator(this, output_values);
}

bool op::v1::VariadicSplit::evaluate_label(TensorLabelVector& output_labels) const {
bool VariadicSplit::evaluate_label(TensorLabelVector& output_labels) const {
OPENVINO_SUPPRESS_DEPRECATED_START
return has_axis_and_splits_bound_set() && default_label_evaluator(this, output_labels);
return variadic_split::has_axis_and_splits_bound_set(this) && default_label_evaluator(this, output_labels);
OPENVINO_SUPPRESS_DEPRECATED_END
}
} // namespace v1
} // namespace op
} // namespace ov

0 comments on commit f2549f2

Please sign in to comment.