diff --git a/src/core/include/openvino/op/minimum.hpp b/src/core/include/openvino/op/minimum.hpp index c8cfc5c9d7c..30819b2a72f 100644 --- a/src/core/include/openvino/op/minimum.hpp +++ b/src/core/include/openvino/op/minimum.hpp @@ -29,9 +29,7 @@ public: std::shared_ptr 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 has_evaluate() const override; }; } // namespace v1 diff --git a/src/core/reference/include/openvino/reference/minimum.hpp b/src/core/reference/include/openvino/reference/minimum.hpp index 4bfe8ff0c89..8d70ae0fc99 100644 --- a/src/core/reference/include/openvino/reference/minimum.hpp +++ b/src/core/reference/include/openvino/reference/minimum.hpp @@ -4,7 +4,7 @@ #pragma once -#include +#include #include "openvino/core/shape.hpp" #include "openvino/op/util/attr_types.hpp" @@ -12,11 +12,16 @@ namespace ov { namespace reference { +namespace func { +template +T min(const T a, const T b) { + return std::min(a, b); +} +} // namespace func + template void minimum(const T* arg0, const T* arg1, T* out, size_t count) { - for (size_t i = 0; i < count; i++) { - out[i] = arg0[i] < arg1[i] ? arg0[i] : arg1[i]; - } + std::transform(arg0, std::next(arg0, count), arg1, out, func::min); } template @@ -26,9 +31,7 @@ void minimum(const T* arg0, const Shape& arg0_shape, const Shape& arg1_shape, const op::AutoBroadcastSpec& broadcast_spec) { - autobroadcast_binop(arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, [](T x, T y) -> T { - return x < y ? x : y; - }); + autobroadcast_binop(arg0, arg1, out, arg0_shape, arg1_shape, broadcast_spec, func::min); } } // namespace reference } // namespace ov diff --git a/src/core/shape_inference/include/utils.hpp b/src/core/shape_inference/include/utils.hpp index 32e53766ba0..cac12973a18 100644 --- a/src/core/shape_inference/include/utils.hpp +++ b/src/core/shape_inference/include/utils.hpp @@ -419,6 +419,17 @@ ov::optional get_input_bounds(const ov::Node* op, size_t port, const IT * @return Result shape from inputs with applied broadcast specification. */ ov::Shape infer_broadcast_shape(const ov::Node* const op, const ov::Shape& first, const ov::Shape& second); + +/** + * @brief Inference broadcast shape from input tensor shapes for element wise operator + * according to broadcast specification stored in operator. + * + * @param op Pointer to operator. + * @param inputs Tensors vector to get theirs shapes. + * + * @return Result shape from input tensors shape with applied broadcast specification. + */ +ov::Shape infer_broadcast_shape(const ov::Node* const op, const ov::TensorVector& inputs); } // namespace op /** diff --git a/src/core/shape_inference/src/utils.cpp b/src/core/shape_inference/src/utils.cpp index c89221d286a..74351e6fc1c 100644 --- a/src/core/shape_inference/src/utils.cpp +++ b/src/core/shape_inference/src/utils.cpp @@ -5,6 +5,7 @@ #include "utils.hpp" #include "eltwise_shape_inference.hpp" +#include "openvino/core/validation_util.hpp" namespace ov { namespace op { @@ -12,5 +13,9 @@ namespace op { ov::Shape infer_broadcast_shape(const ov::Node* const op, const ov::Shape& first, const ov::Shape& second) { return eltwise_shape_infer(op, std::vector{first, second}).front().to_shape(); } + +ov::Shape infer_broadcast_shape(const ov::Node* const op, const ov::TensorVector& inputs) { + return eltwise_shape_infer(op, ov::util::get_tensors_partial_shapes(inputs)).front().to_shape(); +} } // namespace op } // namespace ov diff --git a/src/core/src/op/add.cpp b/src/core/src/op/add.cpp index 316f71b3ebc..0d09563b9ae 100644 --- a/src/core/src/op/add.cpp +++ b/src/core/src/op/add.cpp @@ -19,14 +19,11 @@ struct Evaluate : element::NoAction { static result_type visit(const Tensor& in0, const Tensor& in1, Tensor& out, + const Shape& shape0, + const Shape& shape1, const AutoBroadcastSpec& broadcast_spec) { using T = typename element_type_traits::value_type; - reference::add(in0.data(), - in1.data(), - out.data(), - in0.get_shape(), - in1.get_shape(), - broadcast_spec); + reference::add(in0.data(), in1.data(), out.data(), shape0, shape1, broadcast_spec); return true; } }; @@ -48,15 +45,16 @@ std::shared_ptr Add::clone_with_new_inputs(const OutputVector& new_args) c bool Add::evaluate(ov::TensorVector& outputs, const ov::TensorVector& inputs) const { OV_OP_SCOPE(v1_Add_evaluate); OPENVINO_ASSERT(outputs.size() == 1); - OPENVINO_ASSERT(inputs.size() == 2); - outputs[0].set_shape(infer_broadcast_shape(this, inputs[0].get_shape(), inputs[1].get_shape())); + outputs[0].set_shape(infer_broadcast_shape(this, inputs)); using namespace ov::element; return IfTypeOf::apply( inputs[0].get_element_type(), inputs[0], inputs[1], outputs[0], + inputs[0].get_shape(), + inputs[1].get_shape(), get_autob()); } diff --git a/src/core/src/op/logical_and.cpp b/src/core/src/op/logical_and.cpp index fe8bd612ed2..91ff10dc156 100644 --- a/src/core/src/op/logical_and.cpp +++ b/src/core/src/op/logical_and.cpp @@ -25,19 +25,16 @@ std::shared_ptr LogicalAnd::clone_with_new_inputs(const OutputVector& new_ bool LogicalAnd::evaluate(TensorVector& outputs, const TensorVector& inputs) const { OV_OP_SCOPE(v1_LogicalAnd_evaluate); OPENVINO_ASSERT(outputs.size() == 1); - OPENVINO_ASSERT(inputs.size() == 2); - const auto& shape_0 = inputs[0].get_shape(); - const auto& shape_1 = inputs[1].get_shape(); - outputs[0].set_shape(infer_broadcast_shape(this, shape_0, shape_1)); + outputs[0].set_shape(infer_broadcast_shape(this, inputs)); if (inputs[0].get_element_type() == element::boolean) { using T = fundamental_type_for; reference::logical_and(inputs[0].data(), inputs[1].data(), outputs[0].data(), - shape_0, - shape_1, + inputs[0].get_shape(), + inputs[1].get_shape(), get_autob()); return true; } else { diff --git a/src/core/src/op/logical_or.cpp b/src/core/src/op/logical_or.cpp index 403089318de..5d9532b1358 100644 --- a/src/core/src/op/logical_or.cpp +++ b/src/core/src/op/logical_or.cpp @@ -26,19 +26,16 @@ std::shared_ptr LogicalOr::clone_with_new_inputs(const OutputVector& new_a bool LogicalOr::evaluate(TensorVector& outputs, const TensorVector& inputs) const { OV_OP_SCOPE(v1_LogicalOr_evaluate); OPENVINO_ASSERT(outputs.size() == 1); - OPENVINO_ASSERT(inputs.size() == 2); - const auto& shape_0 = inputs[0].get_shape(); - const auto& shape_1 = inputs[1].get_shape(); - outputs[0].set_shape(infer_broadcast_shape(this, shape_0, shape_1)); + outputs[0].set_shape(infer_broadcast_shape(this, inputs)); if (inputs[0].get_element_type() == element::boolean) { using T = fundamental_type_for; reference::logical_or(inputs[0].data(), inputs[1].data(), outputs[0].data(), - shape_0, - shape_1, + inputs[0].get_shape(), + inputs[1].get_shape(), get_autob()); return true; } else { diff --git a/src/core/src/op/minimum.cpp b/src/core/src/op/minimum.cpp index 83252519bee..1844c6e5b25 100644 --- a/src/core/src/op/minimum.cpp +++ b/src/core/src/op/minimum.cpp @@ -2,92 +2,78 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "ngraph/op/minimum.hpp" - -#include +#include "openvino/op/minimum.hpp" +#include "element_visitor.hpp" #include "itt.hpp" -#include "ngraph/op/convert.hpp" -#include "ngraph/op/less.hpp" -#include "ngraph/op/multiply.hpp" -#include "ngraph/runtime/host_tensor.hpp" -#include "ngraph/type/element_type.hpp" #include "openvino/reference/minimum.hpp" +#include "utils.hpp" -using namespace std; -using namespace ngraph; +namespace ov { +namespace op { -OPENVINO_SUPPRESS_DEPRECATED_START -namespace minimumop { -namespace { -template -bool evaluate(const HostTensorPtr& arg0, - const HostTensorPtr& arg1, - const HostTensorPtr& out, - const op::AutoBroadcastSpec& broadcast_spec) { - ov::reference::minimum(arg0->get_data_ptr(), - arg1->get_data_ptr(), - out->get_data_ptr(), - arg0->get_shape(), - arg1->get_shape(), - broadcast_spec); - return true; -} +namespace minimum { -bool evaluate_minimum(const HostTensorPtr& arg0, - const HostTensorPtr& arg1, - const HostTensorPtr& out, - const op::AutoBroadcastSpec& broadcast_spec) { - bool rc = true; - out->set_broadcast(broadcast_spec, arg0, arg1); - switch (arg0->get_element_type()) { - OPENVINO_TYPE_CASE(evaluate_minimum, i32, arg0, arg1, out, broadcast_spec); - OPENVINO_TYPE_CASE(evaluate_minimum, i64, arg0, arg1, out, broadcast_spec); - OPENVINO_TYPE_CASE(evaluate_minimum, u8, arg0, arg1, out, broadcast_spec); - OPENVINO_TYPE_CASE(evaluate_minimum, u16, arg0, arg1, out, broadcast_spec); - OPENVINO_TYPE_CASE(evaluate_minimum, u32, arg0, arg1, out, broadcast_spec); - OPENVINO_TYPE_CASE(evaluate_minimum, u64, arg0, arg1, out, broadcast_spec); - OPENVINO_TYPE_CASE(evaluate_minimum, f16, arg0, arg1, out, broadcast_spec); - OPENVINO_TYPE_CASE(evaluate_minimum, f32, arg0, arg1, out, broadcast_spec); - default: - rc = false; - break; +struct Evaluate : element::NoAction { + using element::NoAction::visit; + + template > + static result_type visit(const Tensor& arg0, + const Tensor& arg1, + Tensor& out, + const Shape& shape0, + const Shape& shape1, + const AutoBroadcastSpec& broadcast_spec) { + reference::minimum(arg0.data(), arg1.data(), out.data(), shape0, shape1, broadcast_spec); + return true; } - return rc; -} -} // namespace -} // namespace minimumop +}; +} // namespace minimum // ------------------------------ v1 ------------------------------------------- - -op::v1::Minimum::Minimum(const Output& arg0, const Output& arg1, const AutoBroadcastSpec& auto_broadcast) +namespace v1 { +Minimum::Minimum(const Output& arg0, const Output& arg1, const AutoBroadcastSpec& auto_broadcast) : BinaryElementwiseArithmetic(arg0, arg1, auto_broadcast) { constructor_validate_and_infer_types(); } -shared_ptr op::v1::Minimum::clone_with_new_inputs(const OutputVector& new_args) const { +std::shared_ptr Minimum::clone_with_new_inputs(const OutputVector& new_args) const { OV_OP_SCOPE(v1_Minimum_clone_with_new_inputs); check_new_args_count(this, new_args); - return make_shared(new_args.at(0), new_args.at(1), this->get_autob()); + return std::make_shared(new_args.at(0), new_args.at(1), get_autob()); } -bool op::v1::Minimum::evaluate(const HostTensorVector& outputs, const HostTensorVector& inputs) const { +bool Minimum::evaluate(TensorVector& outputs, const TensorVector& inputs) const { OV_OP_SCOPE(v1_Minimum_evaluate); - return minimumop::evaluate_minimum(inputs[0], inputs[1], outputs[0], get_autob()); + OPENVINO_ASSERT(outputs.size() == 1); + + outputs[0].set_shape(infer_broadcast_shape(this, inputs)); + using namespace ov::element; + return IfTypeOf::apply(inputs[0].get_element_type(), + inputs[0], + inputs[1], + outputs[0], + inputs[0].get_shape(), + inputs[1].get_shape(), + get_autob()); } -bool op::v1::Minimum::has_evaluate() const { +bool Minimum::has_evaluate() const { OV_OP_SCOPE(v1_Minimum_has_evaluate); switch (get_input_element_type(0)) { - case ngraph::element::i32: - case ngraph::element::i64: - case ngraph::element::u32: - case ngraph::element::u64: - case ngraph::element::f16: - case ngraph::element::f32: + case element::f16: + case element::f32: + case element::i32: + case element::i64: + case element::u8: + case element::u16: + case element::u32: + case element::u64: return true; default: - break; + return false; } - return false; } +} // namespace v1 +} // namespace op +} // namespace ov diff --git a/src/core/src/op/mod.cpp b/src/core/src/op/mod.cpp index 816d605a292..69ac9493052 100644 --- a/src/core/src/op/mod.cpp +++ b/src/core/src/op/mod.cpp @@ -37,14 +37,11 @@ struct Evaluate : ov::element::NoAction { static result_type visit(const Tensor& in0, const Tensor& in1, Tensor& out, + const Shape& shape0, + const Shape& shape1, const AutoBroadcastSpec& broadcast_spec) { using T = typename element_type_traits::value_type; - reference::mod(in0.data(), - in1.data(), - out.data(), - in0.get_shape(), - in1.get_shape(), - broadcast_spec); + reference::mod(in0.data(), in1.data(), out.data(), shape0, shape1, broadcast_spec); return true; } }; @@ -244,14 +241,15 @@ std::shared_ptr Mod::clone_with_new_inputs(const OutputVector& new_args) c bool Mod::evaluate(ov::TensorVector& outputs, const ov::TensorVector& inputs) const { OV_OP_SCOPE(v1_Mod_evaluate); OPENVINO_ASSERT(outputs.size() == 1); - OPENVINO_ASSERT(inputs.size() == 2); - outputs[0].set_shape(infer_broadcast_shape(this, inputs[0].get_shape(), inputs[1].get_shape())); + outputs[0].set_shape(infer_broadcast_shape(this, inputs)); using namespace ov::element; return IfTypeOf::apply(inputs[0].get_element_type(), inputs[0], inputs[1], outputs[0], + inputs[0].get_shape(), + inputs[1].get_shape(), get_autob()); } diff --git a/src/core/src/op/subtract.cpp b/src/core/src/op/subtract.cpp index 6538918f9f1..6b21fa00483 100644 --- a/src/core/src/op/subtract.cpp +++ b/src/core/src/op/subtract.cpp @@ -19,14 +19,11 @@ struct Evaluate : element::NoAction { static result_type visit(const Tensor& in0, const Tensor& in1, Tensor& out, + const Shape& shape0, + const Shape& shape1, const AutoBroadcastSpec& broadcast_spec) { using T = typename element_type_traits::value_type; - reference::subtract(in0.data(), - in1.data(), - out.data(), - in0.get_shape(), - in1.get_shape(), - broadcast_spec); + reference::subtract(in0.data(), in1.data(), out.data(), shape0, shape1, broadcast_spec); return true; } }; @@ -48,14 +45,15 @@ std::shared_ptr Subtract::clone_with_new_inputs(const OutputVector& new_ar bool Subtract::evaluate(TensorVector& outputs, const TensorVector& inputs) const { OV_OP_SCOPE(v1_Subtract_evaluate); OPENVINO_ASSERT(outputs.size() == 1); - OPENVINO_ASSERT(inputs.size() == 2); - outputs[0].set_shape(infer_broadcast_shape(this, inputs[0].get_shape(), inputs[1].get_shape())); + outputs[0].set_shape(infer_broadcast_shape(this, inputs)); using namespace ov::element; return IfTypeOf::apply(inputs[0].get_element_type(), inputs[0], inputs[1], outputs[0], + inputs[0].get_shape(), + inputs[1].get_shape(), get_autob()); } diff --git a/src/core/src/op/xor.cpp b/src/core/src/op/xor.cpp index eafe1fe465e..c96599d9de3 100644 --- a/src/core/src/op/xor.cpp +++ b/src/core/src/op/xor.cpp @@ -21,13 +21,15 @@ struct Evaluate : element::NoAction { static result_type visit(const Tensor& arg0, const Tensor& arg1, Tensor& out, + const Shape& shape0, + const Shape& shape1, const AutoBroadcastSpec& broadcast_spec) { using T = typename element_type_traits::value_type; reference::logical_xor(arg0.data(), arg1.data(), out.data(), - arg0.get_shape(), - arg1.get_shape(), + shape0, + shape1, broadcast_spec); return true; } @@ -40,14 +42,15 @@ bool input_supported_type(const element::Type& et) { bool evaluate(const Node* const op, TensorVector& outputs, const TensorVector& inputs) { OPENVINO_ASSERT(outputs.size() == 1); - OPENVINO_ASSERT(inputs.size() == 2); - outputs[0].set_shape(infer_broadcast_shape(op, inputs[0].get_shape(), inputs[1].get_shape())); + outputs[0].set_shape(infer_broadcast_shape(op, inputs)); using namespace ov::element; return IfTypeOf::apply(inputs[0].get_element_type(), inputs[0], inputs[1], outputs[0], + inputs[0].get_shape(), + inputs[1].get_shape(), op->get_autob()); } } // namespace diff --git a/src/plugins/template/backend/ops/bitwise_and.cpp b/src/plugins/template/backend/ops/bitwise_and.cpp index d0e5d05b113..b6686175377 100644 --- a/src/plugins/template/backend/ops/bitwise_and.cpp +++ b/src/plugins/template/backend/ops/bitwise_and.cpp @@ -14,9 +14,9 @@ template bool evaluate(const std::shared_ptr& node, ov::TensorVector& outputs, const ov::TensorVector& inputs) { - OPENVINO_ASSERT(inputs.size() == 2); OPENVINO_ASSERT(outputs.size() == 1); - outputs[0].set_shape(infer_broadcast_shape(node.get(), inputs[0].get_shape(), inputs[1].get_shape())); + + outputs[0].set_shape(infer_broadcast_shape(node.get(), inputs)); using T = typename ov::element_type_traits::value_type; ov::reference::bitwise_and(inputs[0].data(), inputs[1].data(), diff --git a/src/plugins/template/backend/ops/bitwise_or.cpp b/src/plugins/template/backend/ops/bitwise_or.cpp index fe163edeccb..69f45d29167 100644 --- a/src/plugins/template/backend/ops/bitwise_or.cpp +++ b/src/plugins/template/backend/ops/bitwise_or.cpp @@ -14,9 +14,9 @@ template bool evaluate(const std::shared_ptr& node, ov::TensorVector& outputs, const ov::TensorVector& inputs) { - OPENVINO_ASSERT(inputs.size() == 2); OPENVINO_ASSERT(outputs.size() == 1); - outputs[0].set_shape(infer_broadcast_shape(node.get(), inputs[0].get_shape(), inputs[1].get_shape())); + + outputs[0].set_shape(infer_broadcast_shape(node.get(), inputs)); using T = typename ov::element_type_traits::value_type; ov::reference::bitwise_or(inputs[0].data(), inputs[1].data(), diff --git a/src/plugins/template/backend/ops/bitwise_xor.cpp b/src/plugins/template/backend/ops/bitwise_xor.cpp index 3fa98775a05..43a15c60b5e 100644 --- a/src/plugins/template/backend/ops/bitwise_xor.cpp +++ b/src/plugins/template/backend/ops/bitwise_xor.cpp @@ -14,9 +14,9 @@ template bool evaluate(const std::shared_ptr& node, ov::TensorVector& outputs, const ov::TensorVector& inputs) { - OPENVINO_ASSERT(inputs.size() == 2); OPENVINO_ASSERT(outputs.size() == 1); - outputs[0].set_shape(infer_broadcast_shape(node.get(), inputs[0].get_shape(), inputs[1].get_shape())); + + outputs[0].set_shape(infer_broadcast_shape(node.get(), inputs)); using T = typename ov::element_type_traits::value_type; ov::reference::bitwise_xor(inputs[0].data(), inputs[1].data(),