Skip to content

Commit

Permalink
[ADD] Identity operation
Browse files Browse the repository at this point in the history
  • Loading branch information
PiotrKrzem committed Sep 20, 2024
1 parent a904d9b commit 0cb3885
Show file tree
Hide file tree
Showing 14 changed files with 393 additions and 2 deletions.
39 changes: 39 additions & 0 deletions src/core/include/openvino/op/identity.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#pragma once

#include "openvino/op/op.hpp"

namespace ov {
namespace op {
namespace v15 {
/// \brief Identity operation is used as a placeholder op.
///
/// \ingroup ov_ops_cpp_api
class OPENVINO_API Identity : public Op {
public:
OPENVINO_OP("Identity", "opset15");
Identity() = default;
/**
* @brief Identity operation is used as a placeholder. It either passes the tensor down to the next layer,
* or copies the tensor to the output.
*
* @param copy Boolean that determines whether to copy the input to the output, or just return the output.
*/
Identity(const Output<Node>& data, const bool copy = false);

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;

bool get_copy() const;
void set_copy(const bool copy);

private:
bool m_copy;
};
} // namespace v15
} // namespace op
} // namespace ov
1 change: 1 addition & 0 deletions src/core/include/openvino/op/ops.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
#include "openvino/op/hswish.hpp"
#include "openvino/op/i420_to_bgr.hpp"
#include "openvino/op/i420_to_rgb.hpp"
#include "openvino/op/identity.hpp"
#include "openvino/op/idft.hpp"
#include "openvino/op/if.hpp"
#include "openvino/op/interpolate.hpp"
Expand Down
1 change: 1 addition & 0 deletions src/core/include/openvino/opsets/opset15_tbl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ _OPENVINO_OP_REG(ScatterNDUpdate, ov::op::v15)
_OPENVINO_OP_REG(EmbeddingBagPacked, ov::op::v15)
_OPENVINO_OP_REG(EmbeddingBagOffsets, ov::op::v15)
_OPENVINO_OP_REG(Col2Im, ov::op::v15)
_OPENVINO_OP_REG(Identity, ov::op::v15)
35 changes: 35 additions & 0 deletions src/core/reference/include/openvino/reference/identity.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#pragma once

#include <cstring>

#include "openvino/core/shape.hpp"

namespace ov {
namespace reference {
namespace identity {

/**
* @brief Identity operation computes the identity of the input tensor.
*
* @param input Input matrix (matrices) pointer.
* @param output Output matrix (matrices) pointer.
* @param copy Boolean that determines whether to return the input as output or
* copy the input to a new memory address.
**/
template <typename T>
void identity(const T** input, T** output, const Shape& shape, const bool copy) {
const auto total_elements = shape_size<Shape>(shape);

if (!copy) {
*output = *input;
} else {
std::memcpy(*output, *input, total_elements * sizeof(T));
}
}
} // namespace identity
} // namespace reference
} // namespace ov
49 changes: 49 additions & 0 deletions src/core/src/op/identity.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#include <cstring>

#include "itt.hpp"
#include "openvino/core/attribute_visitor.hpp"
#include "openvino/op/identity.hpp"
#include "openvino/op/util/op_types.hpp"
#include "openvino/reference/identity.hpp"

namespace ov {
namespace op {
namespace v15 {

Identity::Identity(const Output<Node>& data, const bool copy) : Op({data}), m_copy(copy) {
constructor_validate_and_infer_types();
}

bool Identity::Identity::visit_attributes(AttributeVisitor& visitor) {
OV_OP_SCOPE(v15_Identity_visit_attributes);
visitor.on_attribute("copy", m_copy);
return true;
}

void Identity::Identity::validate_and_infer_types() {
OV_OP_SCOPE(v15_Identity_validate_and_infer_types);

const auto input_shapes = ov::util::get_node_input_partial_shapes(*this);

set_output_type(0, get_input_element_type(0), input_shapes[0]);
}

std::shared_ptr<Node> Identity::Identity::clone_with_new_inputs(const OutputVector& new_args) const {
OV_OP_SCOPE(v15_Identity_clone_with_new_inputs);
check_new_args_count(this, new_args);

return std::make_shared<Identity>(new_args.at(0), m_copy);
}

bool Identity::get_copy() const {
return m_copy;
}

void Identity::set_copy(const bool copy) {
m_copy = copy;
}
} // namespace ov
2 changes: 1 addition & 1 deletion src/core/tests/opset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ INSTANTIATE_TEST_SUITE_P(opset,
OpsetTestParams{ov::get_opset12, 178},
OpsetTestParams{ov::get_opset13, 186},
OpsetTestParams{ov::get_opset14, 188},
OpsetTestParams{ov::get_opset15, 8}),
OpsetTestParams{ov::get_opset15, 9}),
OpsetTestNameGenerator{});

class MyOpOld : public ov::op::Op {
Expand Down
28 changes: 28 additions & 0 deletions src/core/tests/type_prop/identity.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#include "openvino/op/Identity.hpp"

#include <gtest/gtest.h>

#include "common_test_utils/test_assertions.hpp"
#include "common_test_utils/type_prop.hpp"
#include "openvino/op/constant.hpp"

using namespace testing;

class TypePropIdentityV15Test : public TypePropOpTest<ov::op::v15::Identity> {};

TEST_F(TypePropIdentityV15Test, default_ctor) {
const auto data = ov::op::v0::Constant::create(ov::element::f64, ov::Shape{2, 2}, {1.0f, 1.0f, 1.0f, 1.0f});
const auto op = make_op();
op->set_arguments(ov::OutputVector{data});
op->validate_and_infer_types();

EXPECT_EQ(op->get_input_size(), 1);
EXPECT_EQ(op->get_output_size(), 1);
EXPECT_EQ(op->get_output_element_type(0), ov::element::f64);
EXPECT_EQ(op->get_output_partial_shape(0), ov::PartialShape({2, 2}));
EXPECT_EQ(op->get_copy(), false);
}
25 changes: 25 additions & 0 deletions src/core/tests/visitors/op/identity.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#include "openvino/op/Identity.hpp"

#include <gtest/gtest.h>

#include "openvino/op/unique.hpp"
#include "visitors/visitors.hpp"

using ov::test::NodeBuilder;

TEST(attributes, Identity) {
NodeBuilder::opset().insert<ov::op::v15::Identity>();
const auto data = std::make_shared<ov::op::v0::Parameter>(ov::element::f32, ov::Shape{2, 2});

const auto op = std::make_shared<ov::op::v15::Identity>(data, true);
NodeBuilder builder(op, {data});
auto g_identity = ov::as_type_ptr<ov::op::v15::Identity>(builder.create());

constexpr auto expected_attr_count = 1;
EXPECT_EQ(builder.get_value_map_size(), expected_attr_count);
EXPECT_EQ(op->get_copy(), g_identity->get_copy());
}
65 changes: 65 additions & 0 deletions src/plugins/template/backend/ops/identity.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#include "openvino/reference/Identity.hpp"

#include "Identity_shape_inference.hpp"
#include "evaluate_node.hpp"

template <ov::element::Type_t ET>
inline bool evaluate(const std::shared_ptr<ov::op::v15::Identity>& op,
ov::TensorVector& outputs,
const ov::TensorVector& inputs) {
using T = typename ov::element_type_traits<ET>::value_type;

const std::vector<ov::PartialShape> input_shapes{op->get_input_shape(0)};
outputs[0].set_shape(input_shapes[0]);

ov::reference::Identity<T>(inputs[0].data<const T>(), outputs[0].data<T>(), out_shape, op->get_copy());
return true;
}

template <>
bool evaluate_node<ov::op::v15::Identity>(std::shared_ptr<ov::Node> node,
ov::TensorVector& outputs,
const ov::TensorVector& inputs) {
switch (node->get_input_element_type(0)) {
case ov::element::boolean:
return evaluate<ov::element::boolean>(ov::as_type_ptr<ov::op::v15::Identity>(node), outputs, inputs);
case ov::element::bf16:
return evaluate<ov::element::bf16>(ov::as_type_ptr<ov::op::v15::Identity>(node), outputs, inputs);
case ov::element::f16:
return evaluate<ov::element::f16>(ov::as_type_ptr<ov::op::v15::Identity>(node), outputs, inputs);
case ov::element::f64:
return evaluate<ov::element::f64>(ov::as_type_ptr<ov::op::v15::Identity>(node), outputs, inputs);
case ov::element::f32:
return evaluate<ov::element::f32>(ov::as_type_ptr<ov::op::v15::Identity>(node), outputs, inputs);
case ov::element::i4:
return evaluate<ov::element::i4>(ov::as_type_ptr<ov::op::v15::Identity>(node), outputs, inputs);
case ov::element::i8:
return evaluate<ov::element::i8>(ov::as_type_ptr<ov::op::v15::Identity>(node), outputs, inputs);
case ov::element::i16:
return evaluate<ov::element::i16>(ov::as_type_ptr<ov::op::v15::Identity>(node), outputs, inputs);
case ov::element::i32:
return evaluate<ov::element::i32>(ov::as_type_ptr<ov::op::v15::Identity>(node), outputs, inputs);
case ov::element::i64:
return evaluate<ov::element::i64>(ov::as_type_ptr<ov::op::v15::Identity>(node), outputs, inputs);
case ov::element::u1:
return evaluate<ov::element::u1>(ov::as_type_ptr<ov::op::v15::Identity>(node), outputs, inputs);
case ov::element::u4:
return evaluate<ov::element::u4>(ov::as_type_ptr<ov::op::v15::Identity>(node), outputs, inputs);
case ov::element::u8:
return evaluate<ov::element::u8>(ov::as_type_ptr<ov::op::v15::Identity>(node), outputs, inputs);
case ov::element::u16:
return evaluate<ov::element::u16>(ov::as_type_ptr<ov::op::v15::Identity>(node), outputs, inputs);
case ov::element::u32:
return evaluate<ov::element::u32>(ov::as_type_ptr<ov::op::v15::Identity>(node), outputs, inputs);
case ov::element::u64:
return evaluate<ov::element::u64>(ov::as_type_ptr<ov::op::v15::Identity>(node), outputs, inputs);
default:
OPENVINO_THROW("Unhandled input data type ",
node->get_input_element_type(0).get_type_name(),
" in evaluate_node().");
}
}
5 changes: 5 additions & 0 deletions src/plugins/template/backend/ops/ops_evaluates.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,11 @@ extern template bool evaluate_node<ov::op::v15::EmbeddingBagOffsets>(std::shared
extern template bool evaluate_node<ov::op::v15::EmbeddingBagPacked>(std::shared_ptr<ov::Node> node,
ov::TensorVector& outputs,
const ov::TensorVector& inputs);

extern template bool evaluate_node<ov::op::v15::Identity>(std::shared_ptr<ov::Node> node,
ov::TensorVector& outputs,
const ov::TensorVector& inputs);

extern template bool evaluate_node<ov::op::internal::AUGRUCell>(std::shared_ptr<ov::Node> node,
ov::TensorVector& outputs,
const ov::TensorVector& inputs);
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/template/backend/opset_int_tbl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,10 @@ _OPENVINO_OP_REG(AvgPool, ov::op::v14)
_OPENVINO_OP_REG(MaxPool, ov::op::v14)

_OPENVINO_OP_REG(ROIAlignRotated, ov::op::v15)

_OPENVINO_OP_REG(EmbeddingBagOffsets, op::v15)
_OPENVINO_OP_REG(EmbeddingBagPacked, op::v15)
_OPENVINO_OP_REG(Col2Im, ov::op::v15)
_OPENVINO_OP_REG(Identity, ov::op::v15)

_OPENVINO_OP_REG(AUGRUCell, ov::op::internal)
_OPENVINO_OP_REG(AUGRUSequence, ov::op::internal)
Expand Down
Loading

0 comments on commit 0cb3885

Please sign in to comment.