[Opset15] Implementation for EmbeddingBagPacked and EmbeddingBagOffsets ops (#24541)

### Details:
- *Create PoC implementation for EmbeddingBag Offsets and Packed that
introduce mode 'mean'*
 - *Add Core, Reference and CPU implementation for both ops*

Specification will be added in separate PR

### Tickets:
 - *138229*

---------

Co-authored-by: Michal Lukaszewski <michal.lukaszewski@intel.com>
This commit is contained in:
Mateusz Mikolajczyk 2024-05-21 11:07:14 +02:00 committed by GitHub
parent 6556567bdd
commit 23b54736e4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
59 changed files with 3089 additions and 203 deletions

View File

@ -0,0 +1,23 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include "openvino/pass/graph_rewrite.hpp"
#include "transformations_visibility.hpp"
namespace ov {
namespace pass {
/**
* @ingroup ov_transformation_common_api
* @brief Converts EmbeddingBagOffsets v15 to EmbeddingBagOffsets v3.
*/
class TRANSFORMATIONS_API ConvertEmbeddingBagOffsets15ToEmbeddingBagOffsetsSum3 : public MatcherPass {
public:
OPENVINO_RTTI("ConvertEmbeddingBagOffsets15ToEmbeddingBagOffsetsSum3", "0");
ConvertEmbeddingBagOffsets15ToEmbeddingBagOffsetsSum3();
};
} // namespace pass
} // namespace ov

View File

@ -0,0 +1,23 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include "openvino/pass/graph_rewrite.hpp"
#include "transformations_visibility.hpp"
namespace ov {
namespace pass {
/**
* @ingroup ov_transformation_common_api
* @brief Converts EmbeddingBagPacked v15 to EmbeddingBagPacked v3.
*/
class TRANSFORMATIONS_API ConvertEmbeddingBagPacked15ToEmbeddingBagPackedSum3 : public MatcherPass {
public:
OPENVINO_RTTI("ConvertEmbeddingBagPacked15ToEmbeddingBagPackedSum3", "0");
ConvertEmbeddingBagPacked15ToEmbeddingBagPackedSum3();
};
} // namespace pass
} // namespace ov

View File

@ -73,6 +73,8 @@
#include "transformations/op_conversions/convert_deformable_conv_v8_to_v1.hpp"
#include "transformations/op_conversions/convert_depth_to_space.hpp"
#include "transformations/op_conversions/convert_divide.hpp"
#include "transformations/op_conversions/convert_embedding_bag_offsets15_downgrade.hpp"
#include "transformations/op_conversions/convert_embedding_bag_packed15_downgrade.hpp"
#include "transformations/op_conversions/convert_gather_downgrade.hpp"
#include "transformations/op_conversions/convert_gather_upgrade.hpp"
#include "transformations/op_conversions/convert_gelu.hpp"
@ -224,6 +226,8 @@ bool ov::pass::CommonOptimizations::run_on_model(const std::shared_ptr<ov::Model
REGISTER_PASS(manager, ConvertScatterElementsUpdate12ToScatterElementsUpdate3)
REGISTER_PASS(manager, ConcatFusion)
REGISTER_PASS(manager, ConvertAvgPool14ToAvgPool1)
REGISTER_PASS(manager, ConvertEmbeddingBagOffsets15ToEmbeddingBagOffsetsSum3)
REGISTER_PASS(manager, ConvertEmbeddingBagPacked15ToEmbeddingBagPackedSum3)
auto fq_fusions = manager.register_pass<GraphRewrite>();
ADD_MATCHER(fq_fusions, FakeQuantizeMulFusion)

View File

@ -0,0 +1,55 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "transformations/op_conversions/convert_embedding_bag_offsets15_downgrade.hpp"
#include "itt.hpp"
#include "openvino/core/rt_info.hpp"
#include "openvino/op/embeddingbag_offsets.hpp"
#include "openvino/op/embeddingbag_offsets_sum.hpp"
#include "openvino/pass/pattern/op/wrap_type.hpp"
#include "transformations/utils/utils.hpp"
ov::pass::ConvertEmbeddingBagOffsets15ToEmbeddingBagOffsetsSum3::
ConvertEmbeddingBagOffsets15ToEmbeddingBagOffsetsSum3() {
MATCHER_SCOPE(ConvertEmbeddingBagOffsets15ToEmbeddingBagOffsetsSum3);
const auto emb_v15_pattern = pattern::wrap_type<ov::op::v15::EmbeddingBagOffsets>();
const matcher_pass_callback callback = [OV_CAPTURE_CPY_AND_THIS](pattern::Matcher& m) {
const auto emb_v15 = std::dynamic_pointer_cast<ov::op::v15::EmbeddingBagOffsets>(m.get_match_root());
if (!emb_v15 || transformation_callback(emb_v15) ||
emb_v15->get_reduction() != ov::op::v15::EmbeddingBagOffsets::Reduction::SUM) {
return false;
}
std::shared_ptr<ov::op::v3::EmbeddingBagOffsetsSum> emb_v3;
if (emb_v15->get_input_size() == 3) {
emb_v3 = std::make_shared<op::v3::EmbeddingBagOffsetsSum>(emb_v15->input_value(0),
emb_v15->input_value(1),
emb_v15->input_value(2));
} else if (emb_v15->get_input_size() == 4) {
emb_v3 = std::make_shared<op::v3::EmbeddingBagOffsetsSum>(emb_v15->input_value(0),
emb_v15->input_value(1),
emb_v15->input_value(2),
emb_v15->input_value(3));
} else if (emb_v15->get_input_size() == 5) {
emb_v3 = std::make_shared<op::v3::EmbeddingBagOffsetsSum>(emb_v15->input_value(0),
emb_v15->input_value(1),
emb_v15->input_value(2),
emb_v15->input_value(3),
emb_v15->input_value(4));
} else {
return false;
}
emb_v3->set_friendly_name(emb_v15->get_friendly_name());
copy_runtime_info(emb_v15, emb_v3);
replace_node(emb_v15, emb_v3);
return true;
};
auto m = std::make_shared<pattern::Matcher>(emb_v15_pattern, matcher_name);
register_matcher(m, callback);
}

View File

@ -0,0 +1,45 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "transformations/op_conversions/convert_embedding_bag_packed15_downgrade.hpp"
#include "itt.hpp"
#include "openvino/core/rt_info.hpp"
#include "openvino/op/embeddingbag_packed.hpp"
#include "openvino/op/embeddingbag_packedsum.hpp"
#include "openvino/pass/pattern/op/wrap_type.hpp"
#include "transformations/utils/utils.hpp"
ov::pass::ConvertEmbeddingBagPacked15ToEmbeddingBagPackedSum3::ConvertEmbeddingBagPacked15ToEmbeddingBagPackedSum3() {
MATCHER_SCOPE(ConvertEmbeddingBagPacked15ToEmbeddingBagPackedSum3);
const auto emb_v15_pattern = pattern::wrap_type<ov::op::v15::EmbeddingBagPacked>();
const matcher_pass_callback callback = [OV_CAPTURE_CPY_AND_THIS](pattern::Matcher& m) {
const auto emb_v15 = std::dynamic_pointer_cast<ov::op::v15::EmbeddingBagPacked>(m.get_match_root());
if (!emb_v15 || transformation_callback(emb_v15) ||
emb_v15->get_reduction() != ov::op::v15::EmbeddingBagPacked::Reduction::SUM) {
return false;
}
std::shared_ptr<ov::op::v3::EmbeddingBagPackedSum> emb_v3;
if (emb_v15->get_input_size() == 2) {
emb_v3 = std::make_shared<op::v3::EmbeddingBagPackedSum>(emb_v15->input_value(0), emb_v15->input_value(1));
} else if (emb_v15->get_input_size() == 3) {
emb_v3 = std::make_shared<op::v3::EmbeddingBagPackedSum>(emb_v15->input_value(0),
emb_v15->input_value(1),
emb_v15->input_value(2));
} else {
return false;
}
emb_v3->set_friendly_name(emb_v15->get_friendly_name());
copy_runtime_info(emb_v15, emb_v3);
replace_node(emb_v15, emb_v3);
return true;
};
auto m = std::make_shared<pattern::Matcher>(emb_v15_pattern, matcher_name);
register_matcher(m, callback);
}

View File

@ -0,0 +1,146 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "transformations/op_conversions/convert_embedding_bag_offsets15_downgrade.hpp"
#include <gtest/gtest.h>
#include <memory>
#include "common_test_utils/ov_test_utils.hpp"
#include "openvino/opsets/opset15.hpp"
#include "openvino/opsets/opset3.hpp"
#include "openvino/pass/manager.hpp"
#include "transformations/utils/utils.hpp"
using namespace ov;
using namespace testing;
namespace {
std::shared_ptr<ov::Model> create_v15_model(const op::v15::EmbeddingBagOffsets::Reduction reduction_type,
const size_t num_inputs) {
const auto emb_table = std::make_shared<ov::opset15::Parameter>(ov::element::f32, ov::Shape{5, 2});
const auto indices = std::make_shared<ov::opset15::Parameter>(ov::element::i32, ov::Shape{4});
const auto offsets = std::make_shared<ov::opset15::Parameter>(ov::element::i32, ov::Shape{3});
const auto default_index = std::make_shared<ov::opset15::Parameter>(ov::element::i32, ov::Shape{});
const auto per_sample_weights = std::make_shared<ov::opset15::Parameter>(ov::element::f32, ov::Shape{4});
std::shared_ptr<ov::op::v15::EmbeddingBagOffsets> emb;
ov::ParameterVector params;
switch (num_inputs) {
case 0:
emb = std::make_shared<ov::opset15::EmbeddingBagOffsets>();
params = {};
break;
case 3:
emb = std::make_shared<ov::opset15::EmbeddingBagOffsets>(emb_table, indices, offsets, reduction_type);
params = {emb_table, indices, offsets};
break;
case 4:
emb = std::make_shared<ov::opset15::EmbeddingBagOffsets>(emb_table,
indices,
offsets,
default_index,
reduction_type);
params = {emb_table, indices, offsets, default_index};
break;
case 5:
emb = std::make_shared<ov::opset15::EmbeddingBagOffsets>(emb_table,
indices,
offsets,
default_index,
per_sample_weights,
reduction_type);
params = {emb_table, indices, offsets, default_index, per_sample_weights};
break;
}
emb->set_friendly_name("emb15");
return std::make_shared<ov::Model>(emb->outputs(), params);
}
std::shared_ptr<ov::Model> create_v3_model(const size_t num_inputs) {
const auto emb_table = std::make_shared<ov::opset15::Parameter>(ov::element::f32, ov::Shape{5, 2});
const auto indices = std::make_shared<ov::opset15::Parameter>(ov::element::i32, ov::Shape{4});
const auto offsets = std::make_shared<ov::opset15::Parameter>(ov::element::i32, ov::Shape{3});
const auto default_index = std::make_shared<ov::opset15::Parameter>(ov::element::i32, ov::Shape{});
const auto per_sample_weights = std::make_shared<ov::opset15::Parameter>(ov::element::f32, ov::Shape{4});
std::shared_ptr<ov::op::v3::EmbeddingBagOffsetsSum> emb;
ov::ParameterVector params;
switch (num_inputs) {
case 0:
emb = std::make_shared<ov::opset3::EmbeddingBagOffsetsSum>();
params = {};
break;
case 3:
emb = std::make_shared<ov::opset3::EmbeddingBagOffsetsSum>(emb_table, indices, offsets);
params = {emb_table, indices, offsets};
break;
case 4:
emb = std::make_shared<ov::opset3::EmbeddingBagOffsetsSum>(emb_table, indices, offsets, default_index);
params = {emb_table, indices, offsets, default_index};
break;
case 5:
emb = std::make_shared<ov::opset3::EmbeddingBagOffsetsSum>(emb_table,
indices,
offsets,
default_index,
per_sample_weights);
params = {emb_table, indices, offsets, default_index, per_sample_weights};
break;
}
emb->set_friendly_name("emb3");
return std::make_shared<ov::Model>(emb->outputs(), params);
}
} // namespace
TEST_F(TransformationTestsF, ConvertEmbeddingBagOffsets15ToEmbeddingBagOffsetsSum3_sum_0) {
manager.register_pass<ov::pass::ConvertEmbeddingBagOffsets15ToEmbeddingBagOffsetsSum3>();
model = create_v15_model(op::v15::EmbeddingBagOffsets::Reduction::SUM, 0);
model_ref = create_v3_model(0);
comparator.enable(FunctionsComparator::CmpValues::CONST_VALUES);
comparator.enable(FunctionsComparator::CmpValues::ATTRIBUTES);
}
TEST_F(TransformationTestsF, ConvertEmbeddingBagOffsets15ToEmbeddingBagOffsetsSum3_sum_3) {
manager.register_pass<ov::pass::ConvertEmbeddingBagOffsets15ToEmbeddingBagOffsetsSum3>();
model = create_v15_model(op::v15::EmbeddingBagOffsets::Reduction::SUM, 3);
model_ref = create_v3_model(3);
comparator.enable(FunctionsComparator::CmpValues::CONST_VALUES);
comparator.enable(FunctionsComparator::CmpValues::ATTRIBUTES);
}
TEST_F(TransformationTestsF, ConvertEmbeddingBagOffsets15ToEmbeddingBagOffsetsSum3_sum_4) {
manager.register_pass<ov::pass::ConvertEmbeddingBagOffsets15ToEmbeddingBagOffsetsSum3>();
model = create_v15_model(op::v15::EmbeddingBagOffsets::Reduction::SUM, 4);
model_ref = create_v3_model(4);
comparator.enable(FunctionsComparator::CmpValues::CONST_VALUES);
comparator.enable(FunctionsComparator::CmpValues::ATTRIBUTES);
}
TEST_F(TransformationTestsF, ConvertEmbeddingBagOffsets15ToEmbeddingBagOffsetsSum3_sum_5) {
manager.register_pass<ov::pass::ConvertEmbeddingBagOffsets15ToEmbeddingBagOffsetsSum3>();
model = create_v15_model(op::v15::EmbeddingBagOffsets::Reduction::SUM, 5);
model_ref = create_v3_model(5);
comparator.enable(FunctionsComparator::CmpValues::CONST_VALUES);
comparator.enable(FunctionsComparator::CmpValues::ATTRIBUTES);
}
TEST_F(TransformationTestsF, ConvertEmbeddingBagOffsets15ToEmbeddingBagOffsetsSum3_mean_0) {
manager.register_pass<ov::pass::ConvertEmbeddingBagOffsets15ToEmbeddingBagOffsetsSum3>();
model = create_v15_model(op::v15::EmbeddingBagOffsets::Reduction::MEAN, 0);
}
TEST_F(TransformationTestsF, ConvertEmbeddingBagOffsets15ToEmbeddingBagOffsetsSum3_mean_3) {
manager.register_pass<ov::pass::ConvertEmbeddingBagOffsets15ToEmbeddingBagOffsetsSum3>();
model = create_v15_model(op::v15::EmbeddingBagOffsets::Reduction::MEAN, 3);
}
TEST_F(TransformationTestsF, ConvertEmbeddingBagOffsets15ToEmbeddingBagOffsetsSum3_mean_4) {
manager.register_pass<ov::pass::ConvertEmbeddingBagOffsets15ToEmbeddingBagOffsetsSum3>();
model = create_v15_model(op::v15::EmbeddingBagOffsets::Reduction::MEAN, 4);
}

View File

@ -0,0 +1,108 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "transformations/op_conversions/convert_embedding_bag_packed15_downgrade.hpp"
#include <gtest/gtest.h>
#include <memory>
#include "common_test_utils/ov_test_utils.hpp"
#include "openvino/opsets/opset15.hpp"
#include "openvino/opsets/opset3.hpp"
#include "openvino/pass/manager.hpp"
#include "transformations/utils/utils.hpp"
using namespace ov;
using namespace testing;
namespace {
std::shared_ptr<ov::Model> create_v15_model(const op::v15::EmbeddingBagPacked::Reduction reduction_type,
const size_t num_inputs) {
const auto emb_table = std::make_shared<ov::opset15::Parameter>(ov::element::f32, ov::Shape{5, 2});
const auto indices = std::make_shared<ov::opset15::Parameter>(ov::element::i32, ov::Shape{3, 2});
const auto per_sample_weights = std::make_shared<ov::opset15::Parameter>(ov::element::f32, ov::Shape{3, 2});
std::shared_ptr<ov::op::v15::EmbeddingBagPacked> emb;
ov::ParameterVector params;
switch (num_inputs) {
case 0:
emb = std::make_shared<ov::opset15::EmbeddingBagPacked>();
params = {};
break;
case 2:
emb = std::make_shared<ov::opset15::EmbeddingBagPacked>(emb_table, indices, reduction_type);
params = {emb_table, indices};
break;
case 3:
emb = std::make_shared<ov::opset15::EmbeddingBagPacked>(emb_table, indices, per_sample_weights, reduction_type);
params = {emb_table, indices, per_sample_weights};
break;
}
emb->set_friendly_name("emb15");
return std::make_shared<ov::Model>(emb->outputs(), params);
}
std::shared_ptr<ov::Model> create_v3_model(const size_t num_inputs) {
const auto emb_table = std::make_shared<ov::opset15::Parameter>(ov::element::f32, ov::Shape{5, 2});
const auto indices = std::make_shared<ov::opset15::Parameter>(ov::element::i32, ov::Shape{3, 2});
const auto per_sample_weights = std::make_shared<ov::opset15::Parameter>(ov::element::f32, ov::Shape{3, 2});
std::shared_ptr<ov::op::v3::EmbeddingBagPackedSum> emb;
ov::ParameterVector params;
switch (num_inputs) {
case 0:
emb = std::make_shared<ov::opset3::EmbeddingBagPackedSum>();
params = {};
break;
case 2:
emb = std::make_shared<ov::opset3::EmbeddingBagPackedSum>(emb_table, indices);
params = {emb_table, indices};
break;
case 3:
emb = std::make_shared<ov::opset3::EmbeddingBagPackedSum>(emb_table, indices, per_sample_weights);
params = {emb_table, indices, per_sample_weights};
break;
}
emb->set_friendly_name("emb3");
return std::make_shared<ov::Model>(emb->outputs(), params);
}
} // namespace
TEST_F(TransformationTestsF, ConvertEmbeddingBagPacked15ToEmbeddingBagPackedSum3_sum_0) {
manager.register_pass<ov::pass::ConvertEmbeddingBagPacked15ToEmbeddingBagPackedSum3>();
model = create_v15_model(op::v15::EmbeddingBagPacked::Reduction::SUM, 0);
model_ref = create_v3_model(0);
comparator.enable(FunctionsComparator::CmpValues::CONST_VALUES);
comparator.enable(FunctionsComparator::CmpValues::ATTRIBUTES);
}
TEST_F(TransformationTestsF, ConvertEmbeddingBagPacked15ToEmbeddingBagPackedSum3_sum_2) {
manager.register_pass<ov::pass::ConvertEmbeddingBagPacked15ToEmbeddingBagPackedSum3>();
model = create_v15_model(op::v15::EmbeddingBagPacked::Reduction::SUM, 2);
model_ref = create_v3_model(2);
comparator.enable(FunctionsComparator::CmpValues::CONST_VALUES);
comparator.enable(FunctionsComparator::CmpValues::ATTRIBUTES);
}
TEST_F(TransformationTestsF, ConvertEmbeddingBagPacked15ToEmbeddingBagPackedSum3_sum_3) {
manager.register_pass<ov::pass::ConvertEmbeddingBagPacked15ToEmbeddingBagPackedSum3>();
model = create_v15_model(op::v15::EmbeddingBagPacked::Reduction::SUM, 3);
model_ref = create_v3_model(3);
comparator.enable(FunctionsComparator::CmpValues::CONST_VALUES);
comparator.enable(FunctionsComparator::CmpValues::ATTRIBUTES);
}
TEST_F(TransformationTestsF, ConvertEmbeddingBagPacked15ToEmbeddingBagPackedSum3_mean_0) {
manager.register_pass<ov::pass::ConvertEmbeddingBagPacked15ToEmbeddingBagPackedSum3>();
model = create_v15_model(op::v15::EmbeddingBagPacked::Reduction::MEAN, 0);
}
TEST_F(TransformationTestsF, ConvertEmbeddingBagPacked15ToEmbeddingBagPackedSum3_mean_2) {
manager.register_pass<ov::pass::ConvertEmbeddingBagPacked15ToEmbeddingBagPackedSum3>();
model = create_v15_model(op::v15::EmbeddingBagPacked::Reduction::MEAN, 2);
}

View File

@ -0,0 +1,61 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include "openvino/core/axis_set.hpp"
#include "openvino/op/util/embeddingbag_offsets_base.hpp"
#include "openvino/op/util/index_reduction.hpp"
namespace ov {
namespace op {
namespace v15 {
/// \brief Returns embeddings for given indices
/// \ingroup ov_ops_cpp_api
class OPENVINO_API EmbeddingBagOffsets : public util::EmbeddingBagOffsetsBase {
public:
OPENVINO_OP("EmbeddingBagOffsets", "opset15", util::EmbeddingBagOffsetsBase);
/// \brief Constructs a EmbeddingBagOffsets operation.
EmbeddingBagOffsets() = default;
/// \brief Constructs a EmbeddingBagOffsets operation.
///
/// EmbeddingBagOffsets constructs an output tensor by replacing every index in a
/// given
/// input tensor with a row (from the weights matrix) at that index
///
/// \param emb_table tensor containing the embedding lookup table of the module of
/// shape [num_emb, emb_dim1, emb_dim2, ...] and of type T
/// \param indices tensor of shape [num_indices] and of type T_IND. Required
/// \param offsets tensor of shape [batch] and of type T_IND containing the starting
/// index positions of each "bag" in indices. Required.
/// \param default_index scalar of type T_IND containing default index in embedding
/// table to fill empty "bags". If not provided empty "bags"
/// are filled with zeros. Optional.
/// \param per_sample_weigths tensor of the same shape as indices and of type T.
/// Each value in this tensor are multiplied with each
/// value pooled from embedding table for each index. Optional.
EmbeddingBagOffsets(const Output<Node>& emb_table,
const Output<Node>& indices,
const Output<Node>& offsets,
const Output<Node>& default_index,
const Output<Node>& per_sample_weights,
const Reduction& reduction = Reduction::SUM);
EmbeddingBagOffsets(const Output<Node>& emb_table,
const Output<Node>& indices,
const Output<Node>& offsets,
const Output<Node>& default_index,
const Reduction& reduction = Reduction::SUM);
EmbeddingBagOffsets(const Output<Node>& emb_table,
const Output<Node>& indices,
const Output<Node>& offsets,
const Reduction& reduction = Reduction::SUM);
std::shared_ptr<Node> clone_with_new_inputs(const OutputVector& new_args) const override;
};
} // namespace v15
} // namespace op
} // namespace ov

View File

@ -32,7 +32,7 @@ public:
/// \param default_index scalar of type T_IND containing default index in embedding
/// table to fill empty "bags". If not provided empty "bags"
/// are filled with zeros. Optional.
/// \param per_sample_weigths tensor of the same shape as indices and of type T.
/// \param per_sample_weights tensor of the same shape as indices and of type T.
/// Each value in this tensor are multiplied with each
/// value pooled from embedding table for each index. Optional.
@ -50,6 +50,8 @@ public:
EmbeddingBagOffsetsSum(const Output<Node>& emb_table, const Output<Node>& indices, const Output<Node>& offsets);
std::shared_ptr<Node> clone_with_new_inputs(const OutputVector& new_args) const override;
bool visit_attributes(AttributeVisitor& visitor) override;
};
} // namespace v3
} // namespace op

View File

@ -0,0 +1,48 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include "openvino/core/axis_set.hpp"
#include "openvino/op/util/embeddingbag_packed_base.hpp"
#include "openvino/op/util/index_reduction.hpp"
namespace ov {
namespace op {
namespace v15 {
/// \brief Returns embeddings for given indices
/// \ingroup ov_ops_cpp_api
class OPENVINO_API EmbeddingBagPacked : public util::EmbeddingBagPackedBase {
public:
OPENVINO_OP("EmbeddingBagPacked", "opset15", util::EmbeddingBagPackedBase);
/// \brief Constructs a EmbeddingBagPacked operation.
EmbeddingBagPacked() = default;
/// \brief Constructs a EmbeddingBagPacked operation.
///
/// EmbeddingBagPacked constructs an output tensor by replacing every index in a
/// given
/// input tensor with a row (from the weights matrix) at that index
///
/// \param emb_table Tensor containing the embedding lookup table of the module of
/// shape [num_emb, emb_dim1, emb_dim2, ...] and of type T
/// \param indices Tensor of shape `[batch, indices_per_bag]` and of type *T_IND*.
/// Required.
/// \param per_sample_weigths tensor of the same shape as indices and of type T.
/// Each value in this tensor are multiplied with each
/// value pooled from embedding table for each index. Optional.
EmbeddingBagPacked(const Output<Node>& emb_table,
const Output<Node>& indices,
const Output<Node>& per_sample_weights,
const Reduction& reduction = Reduction::SUM);
EmbeddingBagPacked(const Output<Node>& emb_table,
const Output<Node>& indices,
const Reduction& reduction = Reduction::SUM);
std::shared_ptr<Node> clone_with_new_inputs(const OutputVector& new_args) const override;
};
} // namespace v15
} // namespace op
} // namespace ov

View File

@ -39,6 +39,8 @@ public:
EmbeddingBagPackedSum(const Output<Node>& emb_table, const Output<Node>& indices);
std::shared_ptr<Node> clone_with_new_inputs(const OutputVector& new_args) const override;
bool visit_attributes(AttributeVisitor& visitor) override;
};
} // namespace v3
} // namespace op

View File

@ -51,7 +51,9 @@
#include "openvino/op/einsum.hpp"
#include "openvino/op/elu.hpp"
#include "openvino/op/embedding_segments_sum.hpp"
#include "openvino/op/embeddingbag_offsets.hpp"
#include "openvino/op/embeddingbag_offsets_sum.hpp"
#include "openvino/op/embeddingbag_packed.hpp"
#include "openvino/op/embeddingbag_packedsum.hpp"
#include "openvino/op/equal.hpp"
#include "openvino/op/erf.hpp"

View File

@ -14,6 +14,9 @@ namespace util {
class OPENVINO_API EmbeddingBagOffsetsBase : public Op {
public:
OPENVINO_OP("EmbeddingBagOffsetsBase", "util");
enum class Reduction { SUM, MEAN };
/// \brief Constructs a EmbeddingBagOffsetsBase operation.
EmbeddingBagOffsetsBase() = default;
/// \brief Constructs a EmbeddingBagOffsetsBase operation.
@ -28,13 +31,12 @@ public:
/// \param indices tensor of shape [num_indices] and of type T_IND. Required
/// \param offsets tensor of shape [batch] and of type T_IND containing the starting
/// index positions of each "bag" in indices. Required.
/// \param per_sample_weigths tensor of the same shape as indices and of type T.
/// \param per_sample_weights tensor of the same shape as indices and of type T.
/// Each value in this tensor are multiplied with each
/// value pooled from embedding table for each index. Optional.
/// \param default_index scalar of type T_IND containing default index in embedding
/// table to fill empty "bags". If not provided empty "bags"
/// are filled with zeros. Optional.
EmbeddingBagOffsetsBase(const Output<Node>& emb_table,
const Output<Node>& indices,
const Output<Node>& offsets,
@ -48,16 +50,53 @@ public:
EmbeddingBagOffsetsBase(const Output<Node>& emb_table, const Output<Node>& indices, const Output<Node>& offsets);
EmbeddingBagOffsetsBase(const Output<Node>& emb_table,
const Output<Node>& indices,
const Output<Node>& offsets,
const Output<Node>& default_index,
const Output<Node>& per_sample_weights,
const Reduction& reduction);
EmbeddingBagOffsetsBase(const Output<Node>& emb_table,
const Output<Node>& indices,
const Output<Node>& offsets,
const Output<Node>& default_index,
const Reduction& reduction);
EmbeddingBagOffsetsBase(const Output<Node>& emb_table,
const Output<Node>& indices,
const Output<Node>& offsets,
const Reduction& reduction);
void validate_and_infer_types() override;
bool visit_attributes(AttributeVisitor& visitor) override;
const Reduction& get_reduction() {
return m_reduction;
}
private:
static constexpr int EMB_TABLE = 0;
static constexpr int INDICES = 1;
static constexpr int OFFSETS = 2;
static constexpr int DEFAULT_INDEX = 3;
static constexpr int PER_SAMPLE_WEIGHTS = 4;
protected:
Reduction m_reduction = Reduction::SUM;
};
} // namespace util
} // namespace op
template <>
class OPENVINO_API AttributeAdapter<op::util::EmbeddingBagOffsetsBase::Reduction>
: public EnumAttributeAdapterBase<op::util::EmbeddingBagOffsetsBase::Reduction> {
public:
AttributeAdapter(op::util::EmbeddingBagOffsetsBase::Reduction& value)
: EnumAttributeAdapterBase<op::util::EmbeddingBagOffsetsBase::Reduction>(value) {}
OPENVINO_RTTI("AttributeAdapter<ov::op::util::EmbeddingBagOffsetsBase::Reduction>");
};
OPENVINO_API
std::ostream& operator<<(std::ostream& s, const op::util::EmbeddingBagOffsetsBase::Reduction& reduction);
} // namespace ov

View File

@ -13,6 +13,7 @@ namespace util {
/// \brief Returns embeddings for given indices
class OPENVINO_API EmbeddingBagPackedBase : public Op {
public:
enum class Reduction { SUM, MEAN };
OPENVINO_OP("EmbeddingBagPackedBase", "util");
/// \brief Constructs a EmbeddingBagPackedBase operation.
EmbeddingBagPackedBase() = default;
@ -26,24 +27,49 @@ public:
/// shape [num_emb, emb_dim1, emb_dim2, ...] and of type T
/// \param indices Tensor of shape `[batch, indices_per_bag]` and of type *T_IND*.
/// Required.
/// \param per_sample_weigths tensor of the same shape as indices and of type T.
/// \param per_sample_weights tensor of the same shape as indices and of type T.
/// Each value in this tensor are multiplied with each
/// value pooled from embedding table for each index. Optional.
EmbeddingBagPackedBase(const Output<Node>& emb_table,
const Output<Node>& indices,
const Output<Node>& per_sample_weights);
EmbeddingBagPackedBase(const Output<Node>& emb_table, const Output<Node>& indices);
EmbeddingBagPackedBase(const Output<Node>& emb_table,
const Output<Node>& indices,
const Output<Node>& per_sample_weights,
const Reduction& reduction);
EmbeddingBagPackedBase(const Output<Node>& emb_table, const Output<Node>& indices, const Reduction& reduction);
void validate_and_infer_types() override;
bool visit_attributes(AttributeVisitor& visitor) override;
const Reduction& get_reduction() {
return m_reduction;
}
private:
static constexpr int EMB_TABLE = 0;
static constexpr int INDICES = 1;
static constexpr int PER_SAMPLE_WEIGHTS = 2;
protected:
Reduction m_reduction = Reduction::SUM;
};
} // namespace util
} // namespace op
template <>
class OPENVINO_API AttributeAdapter<op::util::EmbeddingBagPackedBase::Reduction>
: public EnumAttributeAdapterBase<op::util::EmbeddingBagPackedBase::Reduction> {
public:
AttributeAdapter(op::util::EmbeddingBagPackedBase::Reduction& value)
: EnumAttributeAdapterBase<op::util::EmbeddingBagPackedBase::Reduction>(value) {}
OPENVINO_RTTI("AttributeAdapter<ov::op::util::EmbeddingBagPackedBase::Reduction>");
};
OPENVINO_API
std::ostream& operator<<(std::ostream& s, const op::util::EmbeddingBagPackedBase::Reduction& reduction);
} // namespace ov

View File

@ -14,3 +14,5 @@ _OPENVINO_OP_REG(ShapeOf, ov::op::v3)
// New operations added in opset15
_OPENVINO_OP_REG(ScatterNDUpdate, ov::op::v15)
_OPENVINO_OP_REG(EmbeddingBagPacked, ov::op::v15)
_OPENVINO_OP_REG(EmbeddingBagOffsets, ov::op::v15)

View File

@ -5,18 +5,22 @@
#pragma once
#include "openvino/core/shape.hpp"
#include "openvino/op/util/embeddingbag_offsets_base.hpp"
#include "openvino/reference/divide.hpp"
namespace ov {
namespace reference {
template <typename T, typename U>
void embeddingBagOffsetsSum(const T* emb_table,
const U* indices,
const U* offsets,
const U* default_index,
const T* weights,
T* out,
const size_t indices_count,
const Shape& outShape) {
void embeddingBagOffsets(const T* emb_table,
const U* indices,
const U* offsets,
const U* default_index,
const T* weights,
T* out,
const size_t indices_count,
const Shape& outShape,
ov::op::util::EmbeddingBagOffsetsBase::Reduction reduction) {
using Reduction = ov::op::util::EmbeddingBagOffsetsBase::Reduction;
const size_t offsets_size = outShape[0];
std::vector<U> default_indices;
if (default_index)
@ -27,7 +31,6 @@ void embeddingBagOffsetsSum(const T* emb_table,
embDepth *= outShape[i];
}
std::fill(out, out + shape_size(outShape), T{0});
auto get_indices =
[&](size_t emb_index, const U*& indices_ref, size_t& indices_num, size_t& weights_idx, bool& with_weights) {
if (emb_index >= offsets_size)
@ -86,6 +89,11 @@ void embeddingBagOffsetsSum(const T* emb_table,
}
}
}
if (reduction == Reduction::MEAN) {
for (size_t i = 0lu; i < embDepth; i++) {
out[dst_index + i] /= (T)indices_size;
}
}
}
}

View File

@ -5,16 +5,19 @@
#pragma once
#include "openvino/core/shape.hpp"
#include "openvino/op/util/embeddingbag_packed_base.hpp"
namespace ov {
namespace reference {
template <typename T, typename U>
void embeddingBagPackedSum(const T* emb_table,
const U* indices,
const T* weights,
T* out,
const Shape& indicesShape,
const Shape& outShape) {
void embeddingBagPacked(const T* emb_table,
const U* indices,
const T* weights,
T* out,
const Shape& indicesShape,
const Shape& outShape,
const ov::op::util::EmbeddingBagPackedBase::Reduction reduction) {
using Reduction = ov::op::util::EmbeddingBagPackedBase::Reduction;
const size_t indices_per_bag = indicesShape[1];
size_t embDepth = 1lu;
@ -42,6 +45,11 @@ void embeddingBagPackedSum(const T* emb_table,
}
}
}
if (reduction == Reduction::MEAN) {
for (size_t i = 0lu; i < shape_size(outShape); i++) {
out[i] /= (T)indices_per_bag;
}
}
} // embeddingBagPackedSum

View File

@ -0,0 +1,57 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "openvino/op/embeddingbag_offsets.hpp"
#include "itt.hpp"
namespace ov {
op::v15::EmbeddingBagOffsets::EmbeddingBagOffsets(const Output<Node>& emb_table,
const Output<Node>& indices,
const Output<Node>& offsets,
const Output<Node>& default_index,
const Output<Node>& per_sample_weights,
const Reduction& reduction)
: util::EmbeddingBagOffsetsBase(emb_table, indices, offsets, default_index, per_sample_weights, reduction) {}
op::v15::EmbeddingBagOffsets::EmbeddingBagOffsets(const Output<Node>& emb_table,
const Output<Node>& indices,
const Output<Node>& offsets,
const Output<Node>& default_index,
const Reduction& reduction)
: util::EmbeddingBagOffsetsBase(emb_table, indices, offsets, default_index, reduction) {}
op::v15::EmbeddingBagOffsets::EmbeddingBagOffsets(const Output<Node>& emb_table,
const Output<Node>& indices,
const Output<Node>& offsets,
const Reduction& reduction)
: util::EmbeddingBagOffsetsBase(emb_table, indices, offsets, reduction) {}
std::shared_ptr<Node> op::v15::EmbeddingBagOffsets::clone_with_new_inputs(const OutputVector& new_args) const {
OV_OP_SCOPE(v15_EmbeddingBagOffsets_clone_with_new_inputs);
check_new_args_count(this, new_args);
if (new_args.size() == 3) {
return std::make_shared<op::v15::EmbeddingBagOffsets>(new_args.at(0),
new_args.at(1),
new_args.at(2),
m_reduction);
} else if (new_args.size() == 4) {
return std::make_shared<op::v15::EmbeddingBagOffsets>(new_args.at(0),
new_args.at(1),
new_args.at(2),
new_args.at(3),
m_reduction);
} else if (new_args.size() == 5) {
return std::make_shared<op::v15::EmbeddingBagOffsets>(new_args.at(0),
new_args.at(1),
new_args.at(2),
new_args.at(3),
new_args.at(4),
m_reduction);
} else {
OPENVINO_THROW("Incorrect number of arguments");
}
}
} // namespace ov

View File

@ -46,4 +46,8 @@ std::shared_ptr<Node> op::v3::EmbeddingBagOffsetsSum::clone_with_new_inputs(cons
OPENVINO_THROW("Incorrect number of arguments");
}
}
bool op::v3::EmbeddingBagOffsetsSum::visit_attributes(AttributeVisitor& visitor) {
OV_OP_SCOPE(v3_EmbeddingBagOffsetsSum_visit_attributes);
return true;
}
} // namespace ov

View File

@ -0,0 +1,36 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "openvino/op/embeddingbag_packed.hpp"
#include "itt.hpp"
namespace ov {
op::v15::EmbeddingBagPacked::EmbeddingBagPacked(const Output<Node>& emb_table,
const Output<Node>& indices,
const Output<Node>& per_sample_weights,
const Reduction& reduction)
: util::EmbeddingBagPackedBase(emb_table, indices, per_sample_weights, reduction) {}
op::v15::EmbeddingBagPacked::EmbeddingBagPacked(const Output<Node>& emb_table,
const Output<Node>& indices,
const Reduction& reduction)
: util::EmbeddingBagPackedBase(emb_table, indices, reduction) {}
std::shared_ptr<Node> op::v15::EmbeddingBagPacked::clone_with_new_inputs(const OutputVector& new_args) const {
OV_OP_SCOPE(v15_EmbeddingBagPacked_clone_with_new_inputs);
check_new_args_count(this, new_args);
if (new_args.size() == 2) {
return std::make_shared<op::v15::EmbeddingBagPacked>(new_args.at(0), new_args.at(1), m_reduction);
} else if (new_args.size() == 3) {
return std::make_shared<op::v15::EmbeddingBagPacked>(new_args.at(0),
new_args.at(1),
new_args.at(2),
m_reduction);
} else {
OPENVINO_THROW("Incorrect number of arguments");
}
}
} // namespace ov

View File

@ -27,4 +27,8 @@ std::shared_ptr<Node> op::v3::EmbeddingBagPackedSum::clone_with_new_inputs(const
OPENVINO_THROW("Incorrect number of arguments");
}
}
bool op::v3::EmbeddingBagPackedSum::visit_attributes(AttributeVisitor& visitor) {
OV_OP_SCOPE(v3_EmbeddingBagPackedSum_visit_attributes);
return true;
}
} // namespace ov

View File

@ -12,7 +12,8 @@ ov::op::util::EmbeddingBagOffsetsBase::EmbeddingBagOffsetsBase(const Output<Node
const Output<Node>& offsets,
const Output<Node>& default_index,
const Output<Node>& per_sample_weights)
: Op({emb_table, indices, offsets, default_index, per_sample_weights}) {
: Op({emb_table, indices, offsets, default_index, per_sample_weights}),
m_reduction{Reduction::SUM} {
constructor_validate_and_infer_types();
}
@ -20,14 +21,46 @@ ov::op::util::EmbeddingBagOffsetsBase::EmbeddingBagOffsetsBase(const Output<Node
const Output<Node>& indices,
const Output<Node>& offsets,
const Output<Node>& default_index)
: Op({emb_table, indices, offsets, default_index}) {
: Op({emb_table, indices, offsets, default_index}),
m_reduction{Reduction::SUM} {
constructor_validate_and_infer_types();
}
ov::op::util::EmbeddingBagOffsetsBase::EmbeddingBagOffsetsBase(const Output<Node>& emb_table,
const Output<Node>& indices,
const Output<Node>& offsets)
: Op({emb_table, indices, offsets}) {
: Op({emb_table, indices, offsets}),
m_reduction{Reduction::SUM} {
constructor_validate_and_infer_types();
}
ov::op::util::EmbeddingBagOffsetsBase::EmbeddingBagOffsetsBase(const Output<Node>& emb_table,
const Output<Node>& indices,
const Output<Node>& offsets,
const Output<Node>& default_index,
const Output<Node>& per_sample_weights,
const Reduction& reduction)
: Op({emb_table, indices, offsets, default_index, per_sample_weights}),
m_reduction{reduction} {
constructor_validate_and_infer_types();
}
ov::op::util::EmbeddingBagOffsetsBase::EmbeddingBagOffsetsBase(const Output<Node>& emb_table,
const Output<Node>& indices,
const Output<Node>& offsets,
const Output<Node>& default_index,
const Reduction& reduction)
: Op({emb_table, indices, offsets, default_index}),
m_reduction{reduction} {
constructor_validate_and_infer_types();
}
ov::op::util::EmbeddingBagOffsetsBase::EmbeddingBagOffsetsBase(const Output<Node>& emb_table,
const Output<Node>& indices,
const Output<Node>& offsets,
const Reduction& reduction)
: Op({emb_table, indices, offsets}),
m_reduction{reduction} {
constructor_validate_and_infer_types();
}
@ -67,6 +100,9 @@ void ov::op::util::EmbeddingBagOffsetsBase::validate_and_infer_types() {
}
if (get_input_size() == 5) {
NODE_VALIDATION_CHECK(this,
m_reduction == Reduction::SUM,
"Per sample weights can only be used in Reduction::SUM mode.");
NODE_VALIDATION_CHECK(this,
get_input_element_type(EMB_TABLE).compatible(get_input_element_type(PER_SAMPLE_WEIGHTS)),
"Per sample weight element type (",
@ -83,5 +119,20 @@ void ov::op::util::EmbeddingBagOffsetsBase::validate_and_infer_types() {
bool ov::op::util::EmbeddingBagOffsetsBase::visit_attributes(AttributeVisitor& visitor) {
OV_OP_SCOPE(util_EmbeddingBagOffsetsBase_visit_attributes);
visitor.on_attribute("reduction", m_reduction);
return true;
}
namespace ov {
template <>
OPENVINO_API EnumNames<op::util::EmbeddingBagOffsetsBase::Reduction>&
EnumNames<op::util::EmbeddingBagOffsetsBase::Reduction>::get() {
static auto enum_names = EnumNames<op::util::EmbeddingBagOffsetsBase::Reduction>(
"op::util::EmbeddingBagOffsetsBase::Reduction",
{{"sum", op::util::EmbeddingBagOffsetsBase::Reduction::SUM},
{"mean", op::util::EmbeddingBagOffsetsBase::Reduction::MEAN}});
return enum_names;
}
std::ostream& operator<<(std::ostream& s, const op::util::EmbeddingBagOffsetsBase::Reduction& reduction) {
return s << as_string(reduction);
}
} // namespace ov

View File

@ -7,17 +7,35 @@
#include "embeddingbag_packed_shape_inference.hpp"
#include "itt.hpp"
using namespace std;
ov::op::util::EmbeddingBagPackedBase::EmbeddingBagPackedBase(const Output<Node>& emb_table,
const Output<Node>& indices,
const Output<Node>& per_sample_weights)
: Op({emb_table, indices, per_sample_weights}) {
: Op({emb_table, indices, per_sample_weights}),
m_reduction{Reduction::SUM} {
constructor_validate_and_infer_types();
}
ov::op::util::EmbeddingBagPackedBase::EmbeddingBagPackedBase(const Output<Node>& emb_table, const Output<Node>& indices)
: Op({emb_table, indices}) {
: Op({emb_table, indices}),
m_reduction{Reduction::SUM} {
constructor_validate_and_infer_types();
}
ov::op::util::EmbeddingBagPackedBase::EmbeddingBagPackedBase(
const Output<Node>& emb_table,
const Output<Node>& indices,
const Output<Node>& per_sample_weights,
const ov::op::util::EmbeddingBagPackedBase::Reduction& reduction)
: Op({emb_table, indices, per_sample_weights}),
m_reduction{reduction} {
constructor_validate_and_infer_types();
}
ov::op::util::EmbeddingBagPackedBase::EmbeddingBagPackedBase(
const Output<Node>& emb_table,
const Output<Node>& indices,
const ov::op::util::EmbeddingBagPackedBase::Reduction& reduction)
: Op({emb_table, indices}),
m_reduction{reduction} {
constructor_validate_and_infer_types();
}
@ -29,6 +47,9 @@ void ov::op::util::EmbeddingBagPackedBase::validate_and_infer_types() {
"INDICES type must be i32 or i64");
if (get_input_size() == 3) {
NODE_VALIDATION_CHECK(this,
m_reduction == Reduction::SUM,
"Per sample weights can only be used in Reduction::SUM mode.");
NODE_VALIDATION_CHECK(this,
get_input_element_type(EMB_TABLE).compatible(get_input_element_type(PER_SAMPLE_WEIGHTS)),
"Per sample weight element type (",
@ -45,5 +66,22 @@ void ov::op::util::EmbeddingBagPackedBase::validate_and_infer_types() {
bool ov::op::util::EmbeddingBagPackedBase::visit_attributes(AttributeVisitor& visitor) {
OV_OP_SCOPE(util_EmbeddingBagPackedBase_visit_attributes);
visitor.on_attribute("reduction", m_reduction);
return true;
}
namespace ov {
std::ostream& operator<<(std::ostream& s, const op::util::EmbeddingBagPackedBase::Reduction& reduction) {
return s << as_string(reduction);
}
template <>
OPENVINO_API EnumNames<op::util::EmbeddingBagPackedBase::Reduction>&
EnumNames<op::util::EmbeddingBagPackedBase::Reduction>::get() {
static auto enum_names = EnumNames<op::util::EmbeddingBagPackedBase::Reduction>(
"op::util::EmbeddingBagPackedBase::Reduction",
{{"sum", op::util::EmbeddingBagPackedBase::Reduction::SUM},
{"mean", op::util::EmbeddingBagPackedBase::Reduction::MEAN}});
return enum_names;
}
} // namespace ov

View File

@ -75,7 +75,7 @@ INSTANTIATE_TEST_SUITE_P(opset,
OpsetTestParams{ov::get_opset12, 178},
OpsetTestParams{ov::get_opset13, 186},
OpsetTestParams{ov::get_opset14, 189},
OpsetTestParams{ov::get_opset15, 4}),
OpsetTestParams{ov::get_opset15, 6}),
OpsetTestNameGenerator{});
class MyOpOld : public ov::op::Op {

View File

@ -0,0 +1,380 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "openvino/op/embeddingbag_offsets.hpp"
#include <gtest/gtest.h>
#include "common_test_utils/test_assertions.hpp"
#include "common_test_utils/type_prop.hpp"
using namespace ov;
using namespace testing;
TEST(type_prop, embedding_bag_offsets_default_ctor) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2, 6});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{4});
auto offsets = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{3});
auto per_sample_weights = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{4});
auto default_index = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{});
auto op = std::make_shared<op::v15::EmbeddingBagOffsets>();
op->set_arguments(OutputVector{emb_table, indices, offsets, default_index, per_sample_weights});
op->validate_and_infer_types();
EXPECT_EQ(op->get_output_partial_shape(0), (PartialShape{3, 2, 6}));
EXPECT_EQ(op->get_output_element_type(0), element::f32);
EXPECT_EQ(op->get_reduction(), op::v15::EmbeddingBagOffsets::Reduction::SUM);
}
TEST(type_prop, embedding_bag_reduction_mean) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{4});
auto offsets = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{3});
auto reduction = op::v15::EmbeddingBagOffsets::Reduction::MEAN;
auto embedding_bag_offsets = std::make_shared<op::v15::EmbeddingBagOffsets>(emb_table, indices, offsets, reduction);
EXPECT_TRUE(embedding_bag_offsets->get_output_partial_shape(0).same_scheme(PartialShape{3, 2}));
EXPECT_EQ(embedding_bag_offsets->get_output_element_type(0), element::f32);
EXPECT_EQ(indices->get_partial_shape().rank().get_length(), 1);
EXPECT_EQ(offsets->get_partial_shape().rank().get_length(), 1);
EXPECT_EQ(embedding_bag_offsets->get_reduction(), op::v15::EmbeddingBagOffsets::Reduction::MEAN);
}
TEST(type_prop, embedding_bag_reduction_mean_index) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{4});
auto offsets = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{3});
auto default_index = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{});
auto reduction = op::v15::EmbeddingBagOffsets::Reduction::MEAN;
auto embedding_bag_offsets =
std::make_shared<op::v15::EmbeddingBagOffsets>(emb_table, indices, offsets, default_index, reduction);
EXPECT_TRUE(embedding_bag_offsets->get_output_partial_shape(0).same_scheme(PartialShape{3, 2}));
EXPECT_EQ(embedding_bag_offsets->get_output_element_type(0), element::f32);
EXPECT_EQ(indices->get_partial_shape().rank().get_length(), 1);
EXPECT_EQ(offsets->get_partial_shape().rank().get_length(), 1);
EXPECT_EQ(embedding_bag_offsets->get_reduction(), op::v15::EmbeddingBagOffsets::Reduction::MEAN);
}
TEST(type_prop, embedding_bag_offsets_labeled_interval_dims) {
auto emb_shape = PartialShape{{5, 10}, {2, 4}, {1, 3}};
auto emb_symbols = set_shape_symbols(emb_shape);
auto off_shape = PartialShape{{6, 8}};
auto off_symbols = set_shape_symbols(off_shape);
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, emb_shape);
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, PartialShape{{3, 4}});
auto offsets = std::make_shared<ov::op::v0::Parameter>(element::i64, off_shape);
auto per_sample_weights = std::make_shared<ov::op::v0::Parameter>(element::f32, PartialShape{{3, 4}});
auto default_index = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{});
auto op =
std::make_shared<op::v15::EmbeddingBagOffsets>(emb_table, indices, offsets, default_index, per_sample_weights);
EXPECT_EQ(op->get_output_element_type(0), element::f32);
EXPECT_EQ(op->get_output_partial_shape(0), (PartialShape{{6, 8}, {2, 4}, {1, 3}}));
EXPECT_THAT(get_shape_symbols(op->get_output_partial_shape(0)),
ElementsAre(off_symbols[0], emb_symbols[1], emb_symbols[2]));
EXPECT_EQ(op->get_reduction(), op::v15::EmbeddingBagOffsets::Reduction::SUM);
}
TEST(type_prop, embedding_bag_offsets) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{4});
auto offsets = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{3});
auto per_sample_weights = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{4});
auto default_index = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{});
auto embedding_bag_offsets =
std::make_shared<op::v15::EmbeddingBagOffsets>(emb_table, indices, offsets, default_index, per_sample_weights);
EXPECT_TRUE(embedding_bag_offsets->get_output_partial_shape(0).same_scheme(PartialShape{3, 2}));
EXPECT_TRUE(indices->get_partial_shape().same_scheme(per_sample_weights->get_partial_shape()));
EXPECT_EQ(embedding_bag_offsets->get_output_element_type(0), element::f32);
EXPECT_EQ(indices->get_partial_shape().rank().get_length(), 1);
EXPECT_EQ(offsets->get_partial_shape().rank().get_length(), 1);
EXPECT_EQ(embedding_bag_offsets->get_reduction(), op::v15::EmbeddingBagOffsets::Reduction::SUM);
}
TEST(type_prop, embedding_bag_offsets_dynamic_emb_table) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, PartialShape{5, Dimension::dynamic()});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{4});
auto offsets = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{3});
auto per_sample_weights = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{4});
auto default_index = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{});
auto embedding_bag_offsets =
std::make_shared<op::v15::EmbeddingBagOffsets>(emb_table, indices, offsets, default_index, per_sample_weights);
EXPECT_TRUE(embedding_bag_offsets->get_output_partial_shape(0).same_scheme(PartialShape{3, Dimension::dynamic()}));
EXPECT_EQ(embedding_bag_offsets->get_reduction(), op::v15::EmbeddingBagOffsets::Reduction::SUM);
}
TEST(type_prop, embedding_bag_offsets_dynamic_offsets) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{4});
auto offsets = std::make_shared<ov::op::v0::Parameter>(element::i64, PartialShape{Dimension::dynamic()});
auto per_sample_weights = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{4});
auto default_index = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{});
auto embedding_bag_offsets =
std::make_shared<op::v15::EmbeddingBagOffsets>(emb_table, indices, offsets, default_index, per_sample_weights);
EXPECT_TRUE(embedding_bag_offsets->get_output_partial_shape(0).same_scheme(PartialShape{Dimension::dynamic(), 2}));
EXPECT_EQ(embedding_bag_offsets->get_reduction(), op::v15::EmbeddingBagOffsets::Reduction::SUM);
}
TEST(type_prop, embedding_bag_offsets_dynamic_emb_table_offsets) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, PartialShape{5, Dimension::dynamic()});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{4});
auto offsets = std::make_shared<ov::op::v0::Parameter>(element::i64, PartialShape{Dimension::dynamic()});
auto per_sample_weights = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{4});
auto default_index = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{});
auto reduction = op::v15::EmbeddingBagOffsets::Reduction::SUM;
auto embedding_bag_offsets = std::make_shared<op::v15::EmbeddingBagOffsets>(emb_table,
indices,
offsets,
default_index,
per_sample_weights,
reduction);
EXPECT_TRUE(embedding_bag_offsets->get_output_partial_shape(0).same_scheme(
PartialShape{Dimension::dynamic(), Dimension::dynamic()}));
EXPECT_EQ(embedding_bag_offsets->get_reduction(), op::v15::EmbeddingBagOffsets::Reduction::SUM);
}
TEST(type_prop, embedding_bag_offsets_fail_indices_element_type) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{4});
auto offsets = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{3});
auto per_sample_weights = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{4});
auto default_index = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{});
OV_EXPECT_THROW(auto embedding_bag_offsets = std::make_shared<op::v15::EmbeddingBagOffsets>(emb_table,
indices,
offsets,
default_index,
per_sample_weights),
NodeValidationFailure,
HasSubstr("INDICES type must be i32 or i64"));
}
TEST(type_prop, embedding_bag_offsets_fail_offsets_element_type) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{4});
auto offsets = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{3});
auto per_sample_weights = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{4});
auto default_index = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{});
OV_EXPECT_THROW(auto embedding_bag_offsets = std::make_shared<op::v15::EmbeddingBagOffsets>(emb_table,
indices,
offsets,
default_index,
per_sample_weights),
NodeValidationFailure,
HasSubstr("OFFSETS type must be i32 or i64"));
}
TEST(type_prop, embedding_bag_offsets_fail_default_index_element_type) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{4});
auto offsets = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{3});
auto per_sample_weights = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{4});
auto default_index = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{});
OV_EXPECT_THROW(auto embedding_bag_offsets = std::make_shared<op::v15::EmbeddingBagOffsets>(emb_table,
indices,
offsets,
default_index,
per_sample_weights),
NodeValidationFailure,
HasSubstr("DEFAULT_INDEX type must be i32 or i64"));
}
TEST(type_prop, embedding_bag_offsets_fail_mismatch_element_type) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i32, Shape{4});
auto offsets = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{3});
auto per_sample_weights = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{4});
auto default_index = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{});
OV_EXPECT_THROW(auto embedding_bag_offsets = std::make_shared<op::v15::EmbeddingBagOffsets>(emb_table,
indices,
offsets,
default_index,
per_sample_weights),
NodeValidationFailure,
HasSubstr("Offsets element type (i64) must match indices element type (i32)"));
}
TEST(type_prop, embedding_bag_offsets_fail_mismatch_element_type_1) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{4});
auto offsets = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{3});
auto per_sample_weights = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{4});
auto default_index = std::make_shared<ov::op::v0::Parameter>(element::i32, Shape{});
OV_EXPECT_THROW(auto embedding_bag_offsets = std::make_shared<op::v15::EmbeddingBagOffsets>(emb_table,
indices,
offsets,
default_index,
per_sample_weights),
NodeValidationFailure,
HasSubstr("Default_index element type (i32) must match indices element type (i64)"));
}
TEST(type_prop, embedding_bag_offsets_fail_mismatch_element_type_2) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{4});
auto offsets = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{3});
auto per_sample_weights = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{4});
auto default_index = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{});
OV_EXPECT_THROW(auto embedding_bag_offsets = std::make_shared<op::v15::EmbeddingBagOffsets>(emb_table,
indices,
offsets,
default_index,
per_sample_weights),
NodeValidationFailure,
HasSubstr("Per sample weight element type (i64) must "
"match embedding table element type (f32)"));
}
TEST(type_prop, embedding_bag_offsets_fail_mismatch_shape) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{4});
auto offsets = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{3});
auto per_sample_weights = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{3});
auto default_index = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{});
OV_EXPECT_THROW(auto embedding_bag_offsets = std::make_shared<op::v15::EmbeddingBagOffsets>(emb_table,
indices,
offsets,
default_index,
per_sample_weights),
NodeValidationFailure,
HasSubstr("INDICES and PER_SAMPLE_WEIGHTS shape must be same"));
}
TEST(type_prop, embedding_bag_offsets_fail_default_index_scalar) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{4});
auto offsets = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{3});
auto per_sample_weights = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{4});
auto default_index = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{2});
OV_EXPECT_THROW(auto embedding_bag_offsets = std::make_shared<op::v15::EmbeddingBagOffsets>(emb_table,
indices,
offsets,
default_index,
per_sample_weights),
NodeValidationFailure,
HasSubstr("DEFAULT_INDEX must be a scalar"));
}
TEST(type_prop, embedding_bag_offsets_fail_indices_1d) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{4, 2});
auto offsets = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{3});
auto per_sample_weights = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{4});
auto default_index = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{});
OV_EXPECT_THROW(auto embedding_bag_offsets = std::make_shared<op::v15::EmbeddingBagOffsets>(emb_table,
indices,
offsets,
default_index,
per_sample_weights),
NodeValidationFailure,
HasSubstr("INDICES must be 1D"));
}
TEST(type_prop, embedding_bag_offsets_fail_emb_table_0d) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{4});
auto offsets = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{3});
auto per_sample_weights = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{4});
auto default_index = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{});
OV_EXPECT_THROW(auto op = std::make_shared<op::v15::EmbeddingBagOffsets>(emb_table,
indices,
offsets,
default_index,
per_sample_weights),
NodeValidationFailure,
HasSubstr("EMB_TABLE can't be a scalar"));
}
TEST(type_prop, embedding_bag_offsets_fail_offsets_1d) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{4});
auto offsets = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{3, 2});
auto per_sample_weights = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{4});
auto default_index = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{});
OV_EXPECT_THROW(auto embedding_bag_offsets = std::make_shared<op::v15::EmbeddingBagOffsets>(emb_table,
indices,
offsets,
default_index,
per_sample_weights),
NodeValidationFailure,
HasSubstr("OFFSETS must be 1D"));
}
TEST(type_prop, embedding_bag_offsets_fail_per_sample_weights_1d) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{4});
auto offsets = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{3});
auto per_sample_weights = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{4, 2});
auto default_index = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{});
OV_EXPECT_THROW(auto embedding_bag_offsets = std::make_shared<op::v15::EmbeddingBagOffsets>(emb_table,
indices,
offsets,
default_index,
per_sample_weights),
NodeValidationFailure,
HasSubstr("PER_SAMPLE_WEIGHTS must be 1D"));
}
TEST(type_prop, embedding_bag_offsets_fail_per_sample_weights_reduction_mean) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{4});
auto offsets = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{3});
auto per_sample_weights = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{4, 2});
auto default_index = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{});
auto reduction = op::v15::EmbeddingBagOffsets::Reduction::MEAN;
OV_EXPECT_THROW(auto embedding_bag_offsets = std::make_shared<op::v15::EmbeddingBagOffsets>(emb_table,
indices,
offsets,
default_index,
per_sample_weights,
reduction),
NodeValidationFailure,
HasSubstr("Per sample weights can only be used in Reduction::SUM mode"));
}
TEST(type_prop, embedding_bag_offsets_3_args_api) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{4});
auto offsets = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{3});
auto embedding_bag_offsets = std::make_shared<op::v15::EmbeddingBagOffsets>(emb_table, indices, offsets);
EXPECT_TRUE(embedding_bag_offsets->get_output_partial_shape(0).same_scheme(PartialShape{3, 2}));
EXPECT_EQ(embedding_bag_offsets->get_output_element_type(0), element::f32);
EXPECT_EQ(indices->get_partial_shape().rank().get_length(), 1);
EXPECT_EQ(offsets->get_partial_shape().rank().get_length(), 1);
EXPECT_EQ(embedding_bag_offsets->get_reduction(), op::v15::EmbeddingBagOffsets::Reduction::SUM);
}
TEST(type_prop, embedding_bag_offsets_fail_indices_element_type_3_args_api) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{4});
auto offsets = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{3});
OV_EXPECT_THROW(
auto embedding_bag_offsets = std::make_shared<op::v15::EmbeddingBagOffsets>(emb_table, indices, offsets),
NodeValidationFailure,
HasSubstr("INDICES type must be i32 or i64"));
}

View File

@ -0,0 +1,229 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "openvino/op/embeddingbag_packed.hpp"
#include <gtest/gtest.h>
#include "common_test_utils/test_assertions.hpp"
#include "common_test_utils/type_prop.hpp"
using namespace ov;
using namespace testing;
TEST(type_prop, embedding_bag_packed_default_ctor) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2, 6});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{3, 4});
auto per_sample_weights = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{3, 4});
auto op = std::make_shared<op::v15::EmbeddingBagPacked>();
op->set_arguments(OutputVector{emb_table, indices, per_sample_weights});
op->validate_and_infer_types();
EXPECT_EQ(op->get_output_partial_shape(0), (PartialShape{3, 2, 6}));
EXPECT_EQ(op->get_output_element_type(0), element::f32);
EXPECT_EQ(op->get_reduction(), op::v15::EmbeddingBagPacked::Reduction::SUM);
}
TEST(type_prop, embedding_bag_packed_labeled_interval_dims_2in) {
auto emb_shape = PartialShape{{5, 10}, {2, 4}, {1, 3}};
auto emb_symbols = set_shape_symbols(emb_shape);
auto ind_shape = PartialShape{{6, 8}, 4};
auto ind_symbols = set_shape_symbols(ind_shape);
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, emb_shape);
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, ind_shape);
auto op = std::make_shared<op::v15::EmbeddingBagPacked>(emb_table, indices);
EXPECT_EQ(op->get_output_element_type(0), element::f32);
EXPECT_EQ(op->get_output_partial_shape(0), (PartialShape{{6, 8}, {2, 4}, {1, 3}}));
EXPECT_THAT(get_shape_symbols(op->get_output_partial_shape(0)),
ElementsAre(ind_symbols[0], emb_symbols[1], emb_symbols[2]));
EXPECT_EQ(op->get_reduction(), op::v15::EmbeddingBagPacked::Reduction::SUM);
}
TEST(type_prop, embedding_bag_packed_labeled_interval_dims_2in_reduction) {
auto emb_shape = PartialShape{{5, 10}, {2, 4}, {1, 3}};
auto emb_symbols = set_shape_symbols(emb_shape);
auto ind_shape = PartialShape{{6, 8}, 4};
auto ind_symbols = set_shape_symbols(ind_shape);
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, emb_shape);
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, ind_shape);
auto reduction = op::v15::EmbeddingBagPacked::Reduction::MEAN;
auto op = std::make_shared<op::v15::EmbeddingBagPacked>(emb_table, indices, reduction);
EXPECT_EQ(op->get_output_element_type(0), element::f32);
EXPECT_EQ(op->get_output_partial_shape(0), (PartialShape{{6, 8}, {2, 4}, {1, 3}}));
EXPECT_THAT(get_shape_symbols(op->get_output_partial_shape(0)),
ElementsAre(ind_symbols[0], emb_symbols[1], emb_symbols[2]));
EXPECT_EQ(op->get_reduction(), op::v15::EmbeddingBagPacked::Reduction::MEAN);
}
TEST(type_prop, embedding_bag_packed_labeled_interval_dims_3in) {
auto emb_shape = PartialShape{{5, 10}, {2, 4}, {1, 3}};
auto emb_symbols = set_shape_symbols(emb_shape);
auto ind_shape = PartialShape{{2, 6}, 4};
auto ind_symbols = set_shape_symbols(ind_shape);
auto sample_shape = PartialShape{{4, 8}, 4};
auto sample_symbols = set_shape_symbols(sample_shape);
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, emb_shape);
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, ind_shape);
auto per_sample_weights = std::make_shared<ov::op::v0::Parameter>(element::f32, sample_shape);
auto op = std::make_shared<op::v15::EmbeddingBagPacked>(emb_table, indices, per_sample_weights);
EXPECT_EQ(op->get_output_element_type(0), element::f32);
EXPECT_EQ(op->get_output_partial_shape(0), (PartialShape{{4, 6}, {2, 4}, {1, 3}}));
EXPECT_THAT(get_shape_symbols(op->get_output_partial_shape(0)),
ElementsAre(ind_symbols[0], emb_symbols[1], emb_symbols[2]));
EXPECT_EQ(op->get_reduction(), op::v15::EmbeddingBagPacked::Reduction::SUM);
}
TEST(type_prop, embedding_bag_packed) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{3, 4});
auto per_sample_weights = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{3, 4});
auto embedding_bag_packed = std::make_shared<op::v15::EmbeddingBagPacked>(emb_table, indices, per_sample_weights);
EXPECT_TRUE(embedding_bag_packed->get_output_partial_shape(0).same_scheme(PartialShape{3, 2}));
EXPECT_TRUE(indices->get_partial_shape().same_scheme(per_sample_weights->get_partial_shape()));
EXPECT_EQ(embedding_bag_packed->get_output_element_type(0), element::f32);
EXPECT_EQ(indices->get_partial_shape().rank().get_length(), 2);
EXPECT_EQ(embedding_bag_packed->get_reduction(), op::v15::EmbeddingBagPacked::Reduction::SUM);
}
TEST(type_prop, embedding_bag_packed_dynamic_emb_table) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, PartialShape{5, Dimension::dynamic()});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{3, 4});
auto per_sample_weights = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{3, 4});
auto default_index = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{});
auto embedding_bag_packed = std::make_shared<op::v15::EmbeddingBagPacked>(emb_table, indices, per_sample_weights);
EXPECT_TRUE(embedding_bag_packed->get_output_partial_shape(0).same_scheme(PartialShape{3, Dimension::dynamic()}));
EXPECT_EQ(embedding_bag_packed->get_reduction(), op::v15::EmbeddingBagPacked::Reduction::SUM);
}
TEST(type_prop, embedding_bag_packed_dynamic_indices) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, PartialShape{Dimension::dynamic(), 4});
auto per_sample_weights =
std::make_shared<ov::op::v0::Parameter>(element::f32, PartialShape{Dimension::dynamic(), 4});
auto embedding_bag_packed = std::make_shared<op::v15::EmbeddingBagPacked>(emb_table, indices, per_sample_weights);
EXPECT_TRUE(embedding_bag_packed->get_output_partial_shape(0).same_scheme(PartialShape{Dimension::dynamic(), 2}));
EXPECT_EQ(embedding_bag_packed->get_reduction(), op::v15::EmbeddingBagPacked::Reduction::SUM);
}
TEST(type_prop, embedding_bag_packed_dynamic_emb_table_indices) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, PartialShape{5, Dimension::dynamic()});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, PartialShape{Dimension::dynamic(), 4});
auto per_sample_weights =
std::make_shared<ov::op::v0::Parameter>(element::f32, PartialShape{Dimension::dynamic(), 4});
auto reduction = op::v15::EmbeddingBagPacked::Reduction::SUM;
auto embedding_bag_packed =
std::make_shared<op::v15::EmbeddingBagPacked>(emb_table, indices, per_sample_weights, reduction);
EXPECT_TRUE(embedding_bag_packed->get_output_partial_shape(0).same_scheme(
PartialShape{Dimension::dynamic(), Dimension::dynamic()}));
EXPECT_EQ(embedding_bag_packed->get_reduction(), op::v15::EmbeddingBagPacked::Reduction::SUM);
}
TEST(type_prop, embedding_bag_packed_fail_indices_element_type) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{3, 4});
auto per_sample_weights = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{3, 4});
OV_EXPECT_THROW(auto embedding_bag_packed =
std::make_shared<op::v15::EmbeddingBagPacked>(emb_table, indices, per_sample_weights),
NodeValidationFailure,
HasSubstr("INDICES type must be i32 or i64"));
}
TEST(type_prop, embedding_bag_packed_fail_mismatch_element_type) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{3, 4});
auto per_sample_weights = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{3, 4});
OV_EXPECT_THROW(auto embedding_bag_packed =
std::make_shared<op::v15::EmbeddingBagPacked>(emb_table, indices, per_sample_weights),
NodeValidationFailure,
HasSubstr("Per sample weight element type (i64) must "
"match embedding table element type (f32)"));
}
TEST(type_prop, embedding_bag_packed_fail_mismatch_shape) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{3, 4});
auto per_sample_weights = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{4, 3});
OV_EXPECT_THROW(auto embedding_bag_packed =
std::make_shared<op::v15::EmbeddingBagPacked>(emb_table, indices, per_sample_weights),
NodeValidationFailure,
HasSubstr("INDICES and PER_SAMPLE_WEIGHTS shape must be same"));
}
TEST(type_prop, embedding_bag_packed_fail_indices_1d) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{4});
auto per_sample_weights = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{3, 4});
OV_EXPECT_THROW(auto embedding_bag_packed =
std::make_shared<op::v15::EmbeddingBagPacked>(emb_table, indices, per_sample_weights),
NodeValidationFailure,
HasSubstr("INDICES must be 2D"));
}
TEST(type_prop, embedding_bag_packed_fail_emb_table_0d) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{3, 4});
auto per_sample_weights = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{3, 4});
OV_EXPECT_THROW(auto op = std::make_shared<op::v15::EmbeddingBagPacked>(emb_table, indices, per_sample_weights),
NodeValidationFailure,
HasSubstr("EMB_TABLE can't be a scalar"));
}
TEST(type_prop, embedding_bag_packed_fail_per_sample_weights_1d) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{3, 4});
auto per_sample_weights = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{4});
OV_EXPECT_THROW(auto embedding_bag_packed =
std::make_shared<op::v15::EmbeddingBagPacked>(emb_table, indices, per_sample_weights),
NodeValidationFailure,
HasSubstr("PER_SAMPLE_WEIGHTS must be 2D"));
}
TEST(type_prop, embedding_bag_packed_fail_per_sample_weights_reduction_mean) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{3, 4});
auto per_sample_weights = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{4});
auto reduction = op::v15::EmbeddingBagPacked::Reduction::MEAN;
OV_EXPECT_THROW(
auto embedding_bag_packed =
std::make_shared<op::v15::EmbeddingBagPacked>(emb_table, indices, per_sample_weights, reduction),
NodeValidationFailure,
HasSubstr("Per sample weights can only be used in Reduction::SUM mode."));
}
TEST(type_prop, embedding_bag_packed_2_args_api) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i64, Shape{3, 4});
auto embedding_bag_packed = std::make_shared<op::v15::EmbeddingBagPacked>(emb_table, indices);
EXPECT_TRUE(embedding_bag_packed->get_output_partial_shape(0).same_scheme(PartialShape{3, 2}));
EXPECT_EQ(embedding_bag_packed->get_output_element_type(0), element::f32);
EXPECT_EQ(indices->get_partial_shape().rank().get_length(), 2);
}
TEST(type_prop, embedding_bag_packed_fail_indices_element_type_2_args_api) {
auto emb_table = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{3, 4});
OV_EXPECT_THROW(auto embedding_bag_packed = std::make_shared<op::v15::EmbeddingBagPacked>(emb_table, indices),
NodeValidationFailure,
HasSubstr("INDICES type must be i32 or i64"));
}

View File

@ -0,0 +1,68 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "openvino/op/embeddingbag_offsets.hpp"
#include <gtest/gtest.h>
#include "visitors/visitors.hpp"
using namespace std;
using namespace ov;
using ov::test::NodeBuilder;
TEST(visitor_without_attribute, embedding_bag_offsets_op) {
NodeBuilder::opset().insert<ov::op::v15::EmbeddingBagOffsets>();
auto emb_table = make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2, 3});
auto indices = make_shared<ov::op::v0::Parameter>(element::i64, Shape{4});
auto offsets = make_shared<ov::op::v0::Parameter>(element::i64, Shape{4});
auto default_index = make_shared<ov::op::v0::Parameter>(element::i64, Shape{});
auto per_sample_weights = make_shared<ov::op::v0::Parameter>(element::f32, Shape{4});
auto reduction = ov::op::v15::EmbeddingBagOffsets::Reduction::SUM;
auto ebos = make_shared<ov::op::v15::EmbeddingBagOffsets>(emb_table,
indices,
offsets,
default_index,
per_sample_weights,
reduction);
NodeBuilder builder(ebos, {emb_table, indices, offsets, default_index, per_sample_weights});
EXPECT_NO_THROW(auto g_ebos = ov::as_type_ptr<ov::op::v15::EmbeddingBagOffsets>(builder.create()));
const auto expected_attr_count = 1;
EXPECT_EQ(builder.get_value_map_size(), expected_attr_count);
}
TEST(visitor_without_attribute, embedding_bag_offsets_op2) {
NodeBuilder::opset().insert<ov::op::v15::EmbeddingBagOffsets>();
auto emb_table = make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2, 3});
auto indices = make_shared<ov::op::v0::Parameter>(element::i64, Shape{4});
auto offsets = make_shared<ov::op::v0::Parameter>(element::i64, Shape{4});
auto default_index = make_shared<ov::op::v0::Parameter>(element::i64, Shape{});
auto reduction = ov::op::v15::EmbeddingBagOffsets::Reduction::MEAN;
auto ebos = make_shared<ov::op::v15::EmbeddingBagOffsets>(emb_table, indices, offsets, default_index, reduction);
NodeBuilder builder(ebos, {emb_table, indices, offsets, default_index});
EXPECT_NO_THROW(auto g_ebos = ov::as_type_ptr<ov::op::v15::EmbeddingBagOffsets>(builder.create()));
const auto expected_attr_count = 1;
EXPECT_EQ(builder.get_value_map_size(), expected_attr_count);
}
TEST(visitor_without_attribute, embedding_bag_offsets_op3) {
NodeBuilder::opset().insert<ov::op::v15::EmbeddingBagOffsets>();
auto emb_table = make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2, 3});
auto indices = make_shared<ov::op::v0::Parameter>(element::i64, Shape{4});
auto offsets = make_shared<ov::op::v0::Parameter>(element::i64, Shape{4});
auto ebos = make_shared<ov::op::v15::EmbeddingBagOffsets>(emb_table, indices, offsets);
NodeBuilder builder(ebos, {emb_table, indices, offsets});
EXPECT_NO_THROW(auto g_ebos = ov::as_type_ptr<ov::op::v15::EmbeddingBagOffsets>(builder.create()));
const auto expected_attr_count = 1;
EXPECT_EQ(builder.get_value_map_size(), expected_attr_count);
}

View File

@ -0,0 +1,42 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "openvino/op/embeddingbag_packed.hpp"
#include <gtest/gtest.h>
#include "visitors/visitors.hpp"
using namespace std;
using namespace ov;
using ov::test::NodeBuilder;
TEST(visitor_without_attribute, embedding_bag_packed_op) {
NodeBuilder::opset().insert<ov::op::v15::EmbeddingBagPacked>();
auto emb_table = make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2});
auto indices = make_shared<ov::op::v0::Parameter>(element::i64, Shape{3, 4});
auto per_sample_weights = make_shared<ov::op::v0::Parameter>(element::f32, Shape{3, 4});
auto reduction = ov::op::v15::EmbeddingBagPacked::Reduction::SUM;
auto ebps = make_shared<ov::op::v15::EmbeddingBagPacked>(emb_table, indices, per_sample_weights, reduction);
NodeBuilder builder(ebps, {emb_table, indices, per_sample_weights});
EXPECT_NO_THROW(auto g_ebps = ov::as_type_ptr<ov::op::v15::EmbeddingBagPacked>(builder.create()));
const auto expected_attr_count = 1;
EXPECT_EQ(builder.get_value_map_size(), expected_attr_count);
}
TEST(visitor_without_attribute, embedding_bag_packed_op2) {
NodeBuilder::opset().insert<ov::op::v15::EmbeddingBagPacked>();
auto emb_table = make_shared<ov::op::v0::Parameter>(element::f32, Shape{5, 2});
auto indices = make_shared<ov::op::v0::Parameter>(element::i64, Shape{3, 4});
auto reduction = ov::op::v15::EmbeddingBagPacked::Reduction::MEAN;
auto ebps = make_shared<ov::op::v15::EmbeddingBagPacked>(emb_table, indices, reduction);
NodeBuilder builder(ebps, {emb_table, indices});
EXPECT_NO_THROW(auto g_ebps = ov::as_type_ptr<ov::op::v15::EmbeddingBagPacked>(builder.create()));
const auto expected_attr_count = 1;
EXPECT_EQ(builder.get_value_map_size(), expected_attr_count);
}

View File

@ -6,8 +6,8 @@
#include "openvino/op/constant.hpp"
#include "openvino/op/convert.hpp"
#include "openvino/op/convert_like.hpp"
#include "openvino/op/embeddingbag_offsets_sum.hpp"
#include "openvino/op/embeddingbag_packedsum.hpp"
#include "openvino/op/embeddingbag_offsets.hpp"
#include "openvino/op/embeddingbag_packed.hpp"
#include "utils.hpp"
namespace ov {
@ -18,9 +18,10 @@ namespace op {
OutputVector translate_embedding_bag_common(const NodeContext& context) {
// aten::embedding_bag(weight, input, offsets=None, scale_grad_by_freq=False, mode_enum=1, sparse=False,
// per_sample_weights=None, include_last_offset=False, padding_idx=None)
// we have only EmbeddingBagSum case support, check it before translation
// we have only EmbeddingBag case support, check it before translation
auto mode = context.const_input<int64_t>(4);
PYTORCH_OP_CONVERSION_CHECK(mode == 0, "Only sum mode supported for aten::embedding_bag translation");
PYTORCH_OP_CONVERSION_CHECK(mode <= 1, "Only sum and mean mode supported for aten::embedding_bag translation");
auto weight = context.get_input(0);
auto indices = context.get_input(1);
indices = context.mark_node(std::make_shared<ov::op::v0::Convert>(indices, element::i32));
@ -29,17 +30,21 @@ OutputVector translate_embedding_bag_common(const NodeContext& context) {
// parameters scale_grad_by_freq, sparse, padding_idx have relation to gradient calculation for training, skip them
// no offsets case
if (context.input_is_none(2)) {
using Reduction = ov::op::v15::EmbeddingBagPacked::Reduction;
Reduction reduction = Reduction(mode);
// no per_sample_weights
if (context.input_is_none(6)) {
result = context.mark_node(std::make_shared<ov::op::v3::EmbeddingBagPackedSum>(weight, indices));
result = context.mark_node(std::make_shared<ov::op::v15::EmbeddingBagPacked>(weight, indices, reduction));
} else {
auto per_sample_weight = context.get_input(6);
per_sample_weight = context.mark_node(std::make_shared<ov::op::v1::ConvertLike>(per_sample_weight, weight));
result = context.mark_node(
std::make_shared<ov::op::v3::EmbeddingBagPackedSum>(weight, indices, per_sample_weight));
std::make_shared<ov::op::v15::EmbeddingBagPacked>(weight, indices, per_sample_weight, reduction));
}
} else {
// with offsets case
using Reduction = ov::op::v15::EmbeddingBagOffsets::Reduction;
Reduction reduction = Reduction(mode);
auto offsets = context.get_input(2);
offsets = context.mark_node(std::make_shared<ov::op::v0::Convert>(offsets, element::i32));
bool include_last_offset = false;
@ -48,15 +53,17 @@ OutputVector translate_embedding_bag_common(const NodeContext& context) {
PYTORCH_OP_CONVERSION_CHECK(!include_last_offset, "Inclusion last offset is not supported");
// no per_sample_wights
if (context.input_is_none(6)) {
result = context.mark_node(std::make_shared<ov::op::v3::EmbeddingBagOffsetsSum>(weight, indices, offsets));
result = context.mark_node(
std::make_shared<ov::op::v15::EmbeddingBagOffsets>(weight, indices, offsets, reduction));
} else {
auto per_sample_weight = context.get_input(6);
per_sample_weight = context.mark_node(std::make_shared<ov::op::v1::ConvertLike>(per_sample_weight, weight));
result = context.mark_node(std::make_shared<ov::op::v3::EmbeddingBagOffsetsSum>(weight,
indices,
offsets,
zero,
per_sample_weight));
result = context.mark_node(std::make_shared<ov::op::v15::EmbeddingBagOffsets>(weight,
indices,
offsets,
zero,
per_sample_weight,
reduction));
}
// aten::embedding_bag returns a tuple of 4 elements: output, offset2bag, bag_size, max_indices.
// But the last three outputs are not used in torch.nn.EmbeddingBag or torch.nn.functional.embedding_bag.

View File

@ -163,8 +163,8 @@ static const TypeToNameMap& get_type_to_name_tbl() {
{"ReduceSumSquare", Type::Reduce},
{"Broadcast", Type::Broadcast},
{"EmbeddingSegmentsSum", Type::EmbeddingSegmentsSum},
{"EmbeddingBagPackedSum", Type::EmbeddingBagPackedSum},
{"EmbeddingBagOffsetsSum", Type::EmbeddingBagOffsetsSum},
{"EmbeddingBagPackedSum", Type::EmbeddingBagPacked},
{"EmbeddingBagOffsetsSum", Type::EmbeddingBagOffsets},
{"Gather", Type::Gather},
{"GatherElements", Type::GatherElements},
{"GatherND", Type::GatherND},
@ -242,6 +242,8 @@ static const TypeToNameMap& get_type_to_name_tbl() {
{"RoPE", Type::RoPE},
{"GatherCompressed", Type::Gather},
{"CausalMaskPreprocess", Type::CausalMaskPreprocess},
{"EmbeddingBagPacked", Type::EmbeddingBagPacked},
{"EmbeddingBagOffsets", Type::EmbeddingBagOffsets},
};
return type_to_name_tbl;
}
@ -311,6 +313,8 @@ std::string NameFromType(const Type type) {
CASE(Reduce);
CASE(Broadcast);
CASE(EmbeddingSegmentsSum);
CASE(EmbeddingBagPacked);
CASE(EmbeddingBagOffsets);
CASE(EmbeddingBagPackedSum);
CASE(EmbeddingBagOffsetsSum);
CASE(Gather);

View File

@ -69,6 +69,8 @@ enum class Type {
Interpolate,
Reduce,
Broadcast,
EmbeddingBagPacked,
EmbeddingBagOffsets,
EmbeddingSegmentsSum,
EmbeddingBagPackedSum,
EmbeddingBagOffsetsSum,

View File

@ -2,57 +2,60 @@
// SPDX-License-Identifier: Apache-2.0
//
#include "embedding_bag.h"
#include <cmath>
#include <vector>
#include <string>
#include <vector>
#include "common/cpu_memcpy.h"
#include "dnnl_types.h"
#include "openvino/core/parallel.hpp"
#include "embedding_bag_sum.h"
#include "openvino/opsets/opset1.hpp"
#include "common/cpu_memcpy.h"
namespace ov {
namespace intel_cpu {
namespace node {
EmbeddingBagSum::EmbeddingBagSum(
const std::shared_ptr<ov::Node>& op,
size_t requiredInputNum,
size_t indicesIdx,
size_t perSampleWeightsIdx,
size_t defaultIndexIdx) :
INDICES_IDX(indicesIdx),
PER_SAMPLE_WEIGHTS_IDX(perSampleWeightsIdx),
DEFAULT_INDEX_IDX(defaultIndexIdx) {
EmbeddingBag::EmbeddingBag(const std::shared_ptr<ov::Node>& op,
size_t requiredInputNum,
size_t indicesIdx,
size_t perSampleWeightsIdx,
size_t defaultIndexIdx)
: INDICES_IDX(indicesIdx),
PER_SAMPLE_WEIGHTS_IDX(perSampleWeightsIdx),
DEFAULT_INDEX_IDX(defaultIndexIdx) {
_layerName = op->get_friendly_name();
std::string logPrefix = std::string("Layer EmbeddingBagSum with name '") + _layerName + "' ";
std::string logPrefix = std::string("Layer EmbeddingBag with name '") + _layerName + "' ";
if (op->get_input_size() < requiredInputNum || op->get_output_size() != 1)
OPENVINO_THROW(logPrefix, "has incorrect number of input or output edges!");
if (op->get_input_size() > PER_SAMPLE_WEIGHTS_IDX)
if ((op->get_input_size() > PER_SAMPLE_WEIGHTS_IDX)) {
_withWeights = true;
}
if (_withWeights) {
if (op->get_input_shape(PER_SAMPLE_WEIGHTS_IDX) != op->get_input_shape(INDICES_IDX))
OPENVINO_THROW(logPrefix, "must have equal shapes for indices and per_sample_weights inputs.");
}
}
void EmbeddingBagSum::prepareParams(const VectorDims& indexStaticShape) {
void EmbeddingBag::prepareParams(const VectorDims& indexStaticShape) {
_embDepth = 1lu;
for (size_t i = 1lu; i < indexStaticShape.size(); i++) {
_embDepth *= indexStaticShape[i];
}
}
template<typename T>
void EmbeddingBagSum::processData(const T* srcData, const T* weightsData,
const VectorDims& inDataDims, const MemoryPtr& outMemory) {
std::string msgPrefix = std::string("Node EmbeddingBagSum with name '") + _layerName + "' ";
template <typename T>
void EmbeddingBag::processData(const T* srcData,
const T* weightsData,
const VectorDims& inDataDims,
const MemoryPtr& outMemory) {
std::string msgPrefix = std::string("Node EmbeddingBag with name '") + _layerName + "' ";
initFromInputs();
const size_t outputBagsNum = outMemory->getShape().getStaticDims()[0];
auto *dstData = outMemory->getDataAs<T>();
auto* dstData = outMemory->getDataAs<T>();
auto threadBody = [&](const int ithr, const int nthr) {
size_t start(0lu), end(0lu);
@ -91,7 +94,8 @@ void EmbeddingBagSum::processData(const T* srcData, const T* weightsData,
for (inIdx = 1lu; inIdx < indicesSize; inIdx++) {
if (static_cast<size_t>(indices[inIdx]) >= inDataDims[0]) {
OPENVINO_THROW(msgPrefix + "' has invalid embedding bag index: " + std::to_string(indices[inIdx]));
OPENVINO_THROW(msgPrefix +
"' has invalid embedding bag index: " + std::to_string(indices[inIdx]));
}
size_t srcIndex = indices[inIdx] * _embDepth;
@ -106,6 +110,11 @@ void EmbeddingBagSum::processData(const T* srcData, const T* weightsData,
}
}
}
if (_reduction == Reduction::MEAN) {
for (size_t i = 0lu; i < _embDepth; i++) {
dstData[dstIndex + i] /= indicesSize;
}
}
} else {
for (size_t i = 0lu; i < _embDepth; i++) {
dstData[dstIndex + i] = 0;
@ -117,30 +126,43 @@ void EmbeddingBagSum::processData(const T* srcData, const T* weightsData,
parallel_nt(0, threadBody);
}
void EmbeddingBagSum::execute(const uint8_t* srcData, const uint8_t* weightsData, const ov::element::Type &srcPrc,
const VectorDims& inDims, const MemoryPtr& outMemory) {
void EmbeddingBag::execute(const uint8_t* srcData,
const uint8_t* weightsData,
const ov::element::Type& srcPrc,
const VectorDims& inDims,
const MemoryPtr& outMemory) {
switch (srcPrc) {
case ov::element::f32: {
return processData<element_type_traits<ov::element::f32>::value_type>(reinterpret_cast<const float*>(srcData),
reinterpret_cast<const float*>(weightsData), inDims, outMemory);
}
case ov::element::i8: {
return processData<element_type_traits<ov::element::i8>::value_type>(reinterpret_cast<const int8_t*>(srcData),
reinterpret_cast<const int8_t*>(weightsData), inDims, outMemory);
}
case ov::element::u8: {
return processData<element_type_traits<ov::element::u8>::value_type>(srcData, weightsData, inDims, outMemory);
}
case ov::element::i32: {
return processData<element_type_traits<ov::element::i32>::value_type>(reinterpret_cast<const int32_t*>(srcData),
reinterpret_cast<const int32_t*>(weightsData), inDims, outMemory);
}
default: {
OPENVINO_THROW("EmbeddingBagSum layer does not support precision '" + std::string(srcPrc.get_type_name()) + "'");
}
case ov::element::f32: {
return processData<element_type_traits<ov::element::f32>::value_type>(
reinterpret_cast<const float*>(srcData),
reinterpret_cast<const float*>(weightsData),
inDims,
outMemory);
}
case ov::element::i8: {
return processData<element_type_traits<ov::element::i8>::value_type>(
reinterpret_cast<const int8_t*>(srcData),
reinterpret_cast<const int8_t*>(weightsData),
inDims,
outMemory);
}
case ov::element::u8: {
return processData<element_type_traits<ov::element::u8>::value_type>(srcData, weightsData, inDims, outMemory);
}
case ov::element::i32: {
return processData<element_type_traits<ov::element::i32>::value_type>(
reinterpret_cast<const int32_t*>(srcData),
reinterpret_cast<const int32_t*>(weightsData),
inDims,
outMemory);
}
default: {
OPENVINO_THROW("EmbeddingBag layer does not support precision '" + std::string(srcPrc.get_type_name()) +
"'");
}
}
}
} // namespace node
} // namespace intel_cpu
} // namespace ov
} // namespace node
} // namespace intel_cpu
} // namespace ov

View File

@ -10,9 +10,10 @@ namespace ov {
namespace intel_cpu {
namespace node {
class EmbeddingBagSum {
class EmbeddingBag {
public:
EmbeddingBagSum(
enum class Reduction { SUM, MEAN };
EmbeddingBag(
const std::shared_ptr<ov::Node>&,
size_t requiredInputsNum,
size_t indicesIdx,
@ -22,7 +23,7 @@ public:
void execute(const uint8_t* srcData, const uint8_t* weightsData, const ov::element::Type &srcPrc,
const VectorDims& inDims, const MemoryPtr& outMemory);
~EmbeddingBagSum() = default;
~EmbeddingBag() = default;
protected:
virtual void initFromInputs() = 0;
@ -44,6 +45,7 @@ protected:
const size_t PER_SAMPLE_WEIGHTS_IDX;
const size_t DEFAULT_INDEX_IDX;
Reduction _reduction = Reduction::SUM;
bool _withWeights = false;
size_t _embDepth = 0;
std::string _layerName;

View File

@ -5,20 +5,21 @@
#include <cmath>
#include <vector>
#include <string>
#include "embedding_bag_offset_sum.h"
#include "openvino/opsets/opset3.hpp"
#include "embedding_bag_offsets.h"
#include "openvino/op/embeddingbag_offsets_sum.hpp"
#include "openvino/op/embeddingbag_offsets.hpp"
namespace ov {
namespace intel_cpu {
namespace node {
bool EmbeddingBagOffsetSum::isSupportedOperation(const std::shared_ptr<const ov::Node>& op, std::string& errorMessage) noexcept {
bool EmbeddingBagOffset::isSupportedOperation(const std::shared_ptr<const ov::Node>& op, std::string& errorMessage) noexcept {
try {
const auto embBagOffsetSumOp = ov::as_type_ptr<const ov::op::v3::EmbeddingBagOffsetsSum>(op);
if (!embBagOffsetSumOp) {
errorMessage = "Node is not an instance of the EmbeddingBagOffsetsSum operation from opset v3.";
const auto embBagOffsetOp = ov::as_type_ptr<const ov::op::v15::EmbeddingBagOffsets>(op);
if (!embBagOffsetSumOp && !embBagOffsetOp) {
errorMessage = "Node is not an instance of the v3::EmbeddingBagOffsetsSum or v15::EmbeddingBagOffsets operation.";
return false;
}
} catch (...) {
@ -27,14 +28,27 @@ bool EmbeddingBagOffsetSum::isSupportedOperation(const std::shared_ptr<const ov:
return true;
}
EmbeddingBagOffsetSum::EmbeddingBagOffsetSum(const std::shared_ptr<ov::Node>& op, const GraphContext::CPtr context)
EmbeddingBagOffset::EmbeddingBagOffset(const std::shared_ptr<ov::Node>& op, const GraphContext::CPtr context)
: Node(op, context, NgraphShapeInferFactory(op, EMPTY_PORT_MASK)),
EmbeddingBagSum(op, 3lu, 1lu, 4lu, 3lu) {
EmbeddingBag(op, 3lu, 1lu, 4lu, 3lu) {
std::string errorMessage;
if (!isSupportedOperation(op, errorMessage)) {
OPENVINO_THROW_NOT_IMPLEMENTED(errorMessage);
}
auto offsets_op = ov::as_type_ptr<ov::op::util::EmbeddingBagOffsetsBase>(op);
if (offsets_op) {
using OpReduction = ov::op::util::EmbeddingBagOffsetsBase::Reduction;
switch (offsets_op->get_reduction()) {
case OpReduction::SUM:
_reduction = Reduction::SUM;
break;
case OpReduction::MEAN:
_reduction = Reduction::MEAN;
break;
default:
THROW_CPU_NODE_ERR("EmbeddingBagOffsets does not support reduction mode: ", ov::as_string(offsets_op->get_reduction()));
}
}
if (getInputShapeAtPort(INDICES_IDX).getRank() != 1ul)
OPENVINO_THROW("'", _layerName, "' layer has indices data with invalid rank.");
@ -42,11 +56,11 @@ EmbeddingBagOffsetSum::EmbeddingBagOffsetSum(const std::shared_ptr<ov::Node>& op
OPENVINO_THROW("'", _layerName, "' layer's offsets data has invalid rank.");
}
void EmbeddingBagOffsetSum::initSupportedPrimitiveDescriptors() {
void EmbeddingBagOffset::initSupportedPrimitiveDescriptors() {
if (!supportedPrimitiveDescriptors.empty())
return;
std::string logPrefix = std::string("Layer EmbeddingBagSum with name '") + _layerName + "' ";
std::string logPrefix = std::string("Layer EmbeddingBag with name '") + _layerName + "' ";
static const std::set<ov::element::Type > supportedPrecisions =
{ov::element::f32, ov::element::i8, ov::element::u8, ov::element::i32};
@ -74,13 +88,13 @@ void EmbeddingBagOffsetSum::initSupportedPrimitiveDescriptors() {
addSupportedPrimDesc(inDataConfigurators, {{LayoutType::ncsp, inDataPrecision}}, impl_desc_type::ref_any);
}
void EmbeddingBagOffsetSum::prepareParams() {
void EmbeddingBagOffset::prepareParams() {
_indicesLen = getParentEdgeAt(INDICES_IDX)->getMemory().getStaticDims()[0];
_offsetsLen = getParentEdgeAt(OFFSETS_IDX)->getMemory().getStaticDims()[0];
EmbeddingBagSum::prepareParams(getParentEdgeAt(EMB_TABLE_IDX)->getMemory().getStaticDims());
EmbeddingBag::prepareParams(getParentEdgeAt(EMB_TABLE_IDX)->getMemory().getStaticDims());
}
void EmbeddingBagOffsetSum::initFromInputs() {
void EmbeddingBagOffset::initFromInputs() {
indicesData_ = getSrcDataAtPortAs<const int>(INDICES_IDX);
offsetsData_ = getSrcDataAtPortAs<const int>(OFFSETS_IDX);
@ -89,7 +103,7 @@ void EmbeddingBagOffsetSum::initFromInputs() {
}
}
void EmbeddingBagOffsetSum::getIndices(size_t embIndex, const int*& indices, size_t& size, int& weightsIdx, bool& withWeight) {
void EmbeddingBagOffset::getIndices(size_t embIndex, const int*& indices, size_t& size, int& weightsIdx, bool& withWeight) {
if (static_cast<size_t>(embIndex) >= _offsetsLen) {
OPENVINO_THROW("Invalid embedding bag index.");
}
@ -122,27 +136,27 @@ void EmbeddingBagOffsetSum::getIndices(size_t embIndex, const int*& indices, siz
weightsIdx = offsetsData_[embIndex];
}
void EmbeddingBagOffsetSum::executeDynamicImpl(dnnl::stream strm) {
void EmbeddingBagOffset::executeDynamicImpl(dnnl::stream strm) {
execute(strm);
}
bool EmbeddingBagOffsetSum::isExecutable() const {
bool EmbeddingBagOffset::isExecutable() const {
return !isInputTensorAtPortEmpty(0);
}
void EmbeddingBagOffsetSum::execute(dnnl::stream strm) {
void EmbeddingBagOffset::execute(dnnl::stream strm) {
const auto *srcData = getSrcDataAtPortAs<const uint8_t>(0);
const uint8_t* weightsData = nullptr;
if (_withWeights)
weightsData = getSrcDataAtPortAs<const uint8_t>(PER_SAMPLE_WEIGHTS_IDX);
const auto &inputMem = getParentEdgeAt(0)->getMemory();
EmbeddingBagSum::execute(srcData, weightsData, inputMem.getDesc().getPrecision(),
EmbeddingBag::execute(srcData, weightsData, inputMem.getDesc().getPrecision(),
inputMem.getStaticDims(), getDstMemoryAtPort(0));
}
bool EmbeddingBagOffsetSum::created() const {
return getType() == Type::EmbeddingBagOffsetsSum;
bool EmbeddingBagOffset::created() const {
return getType() == Type::EmbeddingBagOffsets;
}
} // namespace node

View File

@ -4,16 +4,16 @@
#pragma once
#include "embedding_bag_sum.h"
#include "embedding_bag.h"
#include "node.h"
namespace ov {
namespace intel_cpu {
namespace node {
class EmbeddingBagOffsetSum : public Node, public EmbeddingBagSum {
class EmbeddingBagOffset : public Node, public EmbeddingBag {
public:
EmbeddingBagOffsetSum(const std::shared_ptr<ov::Node>& op, const GraphContext::CPtr context);
EmbeddingBagOffset(const std::shared_ptr<ov::Node>& op, const GraphContext::CPtr context);
void getSupportedDescriptors() override {};
void initSupportedPrimitiveDescriptors() override;

View File

@ -5,18 +5,20 @@
#include <cmath>
#include <vector>
#include <string>
#include "embedding_bag_packed_sum.h"
#include "openvino/opsets/opset3.hpp"
#include "embedding_bag_packed.h"
#include "openvino/op/embeddingbag_packedsum.hpp"
#include "openvino/op/embeddingbag_packed.hpp"
namespace ov {
namespace intel_cpu {
namespace node {
bool EmbeddingBagPackedSum::isSupportedOperation(const std::shared_ptr<const ov::Node>& op, std::string& errorMessage) noexcept {
bool EmbeddingBagPacked::isSupportedOperation(const std::shared_ptr<const ov::Node>& op, std::string& errorMessage) noexcept {
try {
const auto embBagPackedSumOp = ov::as_type_ptr<const ov::op::v3::EmbeddingBagPackedSum>(op);
if (!embBagPackedSumOp) {
errorMessage = "Node is not an instance of the EmbeddingBagPackedSum operation from opset v3.";
const auto embBagPackedOp = ov::as_type_ptr<const ov::op::v15::EmbeddingBagPacked>(op);
if (!embBagPackedSumOp && !embBagPackedOp) {
errorMessage = "Node is not an instance of the v3::EmbeddingBagPackedSum or v15::EmbeddingBagPacked operations.";
return false;
}
} catch (...) {
@ -25,23 +27,36 @@ bool EmbeddingBagPackedSum::isSupportedOperation(const std::shared_ptr<const ov:
return true;
}
EmbeddingBagPackedSum::EmbeddingBagPackedSum(const std::shared_ptr<ov::Node>& op, const GraphContext::CPtr context)
EmbeddingBagPacked::EmbeddingBagPacked(const std::shared_ptr<ov::Node>& op, const GraphContext::CPtr context)
: Node(op, context, NgraphShapeInferFactory(op, EMPTY_PORT_MASK)),
EmbeddingBagSum(op, 2lu, 1lu, 2lu, 3lu) {
EmbeddingBag(op, 2lu, 1lu, 2lu, 3lu) {
std::string errorMessage;
if (!isSupportedOperation(op, errorMessage)) {
OPENVINO_THROW_NOT_IMPLEMENTED(errorMessage);
}
auto packed_op = ov::as_type_ptr<ov::op::util::EmbeddingBagPackedBase>(op);
if (packed_op) {
using OpReduction = ov::op::util::EmbeddingBagPackedBase::Reduction;
switch (packed_op->get_reduction()) {
case OpReduction::SUM:
_reduction = Reduction::SUM;
break;
case OpReduction::MEAN:
_reduction = Reduction::MEAN;
break;
default:
THROW_CPU_NODE_ERR("EmbeddingBagPacked does not support reduction mode: ", ov::as_string(packed_op->get_reduction()));
}
}
if (getInputShapeAtPort(INDICES_IDX).getRank() != 2ul)
OPENVINO_THROW("'", _layerName, "' layer has indices data with invalid rank.");
}
void EmbeddingBagPackedSum::initSupportedPrimitiveDescriptors() {
void EmbeddingBagPacked::initSupportedPrimitiveDescriptors() {
if (!supportedPrimitiveDescriptors.empty())
return;
std::string logPrefix = std::string("Layer EmbeddingBagSum with name '") + _layerName + "' ";
std::string logPrefix = std::string("Layer EmbeddingBag with name '") + _layerName + "' ";
static const std::set<ov::element::Type> supportedPrecisions =
{ov::element::f32, ov::element::i8, ov::element::u8, ov::element::i32};
@ -66,17 +81,17 @@ void EmbeddingBagPackedSum::initSupportedPrimitiveDescriptors() {
addSupportedPrimDesc(inDataConfigurators, {{LayoutType::ncsp, inDataPrecision}}, impl_desc_type::ref_any);
}
void EmbeddingBagPackedSum::prepareParams() {
void EmbeddingBagPacked::prepareParams() {
_batch = getParentEdgeAt(INDICES_IDX)->getMemory().getStaticDims()[0];
_indicesPerBag = getParentEdgeAt(INDICES_IDX)->getMemory().getStaticDims()[1];
EmbeddingBagSum::prepareParams(getParentEdgeAt(EMB_TABLE_IDX)->getMemory().getStaticDims());
EmbeddingBag::prepareParams(getParentEdgeAt(EMB_TABLE_IDX)->getMemory().getStaticDims());
}
void EmbeddingBagPackedSum::initFromInputs() {
void EmbeddingBagPacked::initFromInputs() {
_indices = getSrcDataAtPortAs<const int>(INDICES_IDX);
}
void EmbeddingBagPackedSum::getIndices(size_t embIndex, const int*& indices, size_t& size, int& weightsIdx, bool& withWeight) {
void EmbeddingBagPacked::getIndices(size_t embIndex, const int*& indices, size_t& size, int& weightsIdx, bool& withWeight) {
if (static_cast<size_t>(embIndex) >= _batch * _indicesPerBag)
OPENVINO_THROW("Invalid embedding bag index.");
@ -88,27 +103,27 @@ void EmbeddingBagPackedSum::getIndices(size_t embIndex, const int*& indices, siz
weightsIdx = embIndex * _indicesPerBag;
}
void EmbeddingBagPackedSum::executeDynamicImpl(dnnl::stream strm) {
void EmbeddingBagPacked::executeDynamicImpl(dnnl::stream strm) {
execute(strm);
}
bool EmbeddingBagPackedSum::isExecutable() const {
bool EmbeddingBagPacked::isExecutable() const {
return !isInputTensorAtPortEmpty(0);
}
void EmbeddingBagPackedSum::execute(dnnl::stream strm) {
void EmbeddingBagPacked::execute(dnnl::stream strm) {
const auto *srcData = getSrcDataAtPortAs<const uint8_t>(0);
const uint8_t* weightsData = nullptr;
if (_withWeights)
weightsData = getSrcDataAtPortAs<const uint8_t>(PER_SAMPLE_WEIGHTS_IDX);
const auto &inputMem = getParentEdgeAt(0)->getMemory();
EmbeddingBagSum::execute(srcData, weightsData, inputMem.getDesc().getPrecision(),
EmbeddingBag::execute(srcData, weightsData, inputMem.getDesc().getPrecision(),
inputMem.getStaticDims(), getDstMemoryAtPort(0));
}
bool EmbeddingBagPackedSum::created() const {
return getType() == Type::EmbeddingBagPackedSum;
bool EmbeddingBagPacked::created() const {
return getType() == Type::EmbeddingBagPacked;
}
} // namespace node

View File

@ -4,16 +4,16 @@
#pragma once
#include "embedding_bag_sum.h"
#include "embedding_bag.h"
#include "node.h"
namespace ov {
namespace intel_cpu {
namespace node {
class EmbeddingBagPackedSum : public Node, public EmbeddingBagSum {
class EmbeddingBagPacked : public Node, public EmbeddingBag {
public:
EmbeddingBagPackedSum(const std::shared_ptr<ov::Node>& op, const GraphContext::CPtr context);
EmbeddingBagPacked(const std::shared_ptr<ov::Node>& op, const GraphContext::CPtr context);
void getSupportedDescriptors() override {};
void initSupportedPrimitiveDescriptors() override;

View File

@ -27,12 +27,12 @@ bool EmbeddingSegmentsSum::isSupportedOperation(const std::shared_ptr<const ov::
EmbeddingSegmentsSum::EmbeddingSegmentsSum(const std::shared_ptr<ov::Node>& op, const GraphContext::CPtr context)
: Node(op, context, NgraphShapeInferFactory(op, PortMask(NUM_SEGMENTS_IDX))),
EmbeddingBagSum(op, 4lu, 1lu, 5lu, 4lu) {
EmbeddingBag(op, 4lu, 1lu, 5lu, 4lu) {
std::string errorMessage;
if (!isSupportedOperation(op, errorMessage)) {
OPENVINO_THROW_NOT_IMPLEMENTED(errorMessage);
}
_reduction = Reduction::SUM;
std::string errPrefix = std::string("EmbeddingSegmentsSum layer with name '") + _layerName + "' ";
if (getInputShapeAtPort(INDICES_IDX).getRank() != 1ul)
OPENVINO_THROW(errPrefix, "has indices data with invalid rank: ", getInputShapeAtPort(INDICES_IDX).getRank());
@ -45,7 +45,7 @@ void EmbeddingSegmentsSum::initSupportedPrimitiveDescriptors() {
if (!supportedPrimitiveDescriptors.empty())
return;
std::string logPrefix = std::string("Layer EmbeddingBagSum with name '") + _layerName + "' ";
std::string logPrefix = std::string("Layer EmbeddingBag with name '") + _layerName + "' ";
static const std::set<ov::element::Type> supportedPrecisions =
{ov::element::f32, ov::element::i8, ov::element::u8, ov::element::i32};
@ -75,7 +75,7 @@ void EmbeddingSegmentsSum::initSupportedPrimitiveDescriptors() {
}
void EmbeddingSegmentsSum::prepareParams() {
EmbeddingBagSum::prepareParams(getParentEdgeAt(EMB_TABLE_IDX)->getMemory().getStaticDims());
EmbeddingBag::prepareParams(getParentEdgeAt(EMB_TABLE_IDX)->getMemory().getStaticDims());
}
void EmbeddingSegmentsSum::initFromInputs() {
@ -149,7 +149,7 @@ void EmbeddingSegmentsSum::execute(dnnl::stream strm) {
weightsData = getSrcDataAtPortAs<const uint8_t>(PER_SAMPLE_WEIGHTS_IDX);
const auto &inputMem = getParentEdgeAt(0)->getMemory();
EmbeddingBagSum::execute(srcData, weightsData, inputMem.getDesc().getPrecision(),
EmbeddingBag::execute(srcData, weightsData, inputMem.getDesc().getPrecision(),
inputMem.getStaticDims(), getDstMemoryAtPort(0));
}

View File

@ -4,14 +4,14 @@
#pragma once
#include "embedding_bag_sum.h"
#include "embedding_bag.h"
#include "node.h"
namespace ov {
namespace intel_cpu {
namespace node {
class EmbeddingSegmentsSum : public Node, public EmbeddingBagSum {
class EmbeddingSegmentsSum : public Node, public EmbeddingBag {
public:
EmbeddingSegmentsSum(const std::shared_ptr<ov::Node>& op, const GraphContext::CPtr context);

View File

@ -21,8 +21,8 @@
#include "nodes/detection_output.h"
#include "nodes/dft.h"
#include "nodes/eltwise.h"
#include "nodes/embedding_bag_offset_sum.h"
#include "nodes/embedding_bag_packed_sum.h"
#include "nodes/embedding_bag_offsets.h"
#include "nodes/embedding_bag_packed.h"
#include "nodes/embedding_segments_sum.h"
#include "nodes/experimental_detectron_detection_output.h"
#include "nodes/experimental_detectron_generate_proposals_single_image.h"
@ -124,7 +124,8 @@ Node::NodesFactory::NodesFactory() : Factory("NodesFactory") {
INTEL_CPU_NODE(Pooling, Type::Pooling);
INTEL_CPU_NODE(Eltwise, Type::Eltwise);
INTEL_CPU_NODE(SoftMax, Type::Softmax);
INTEL_CPU_NODE(EmbeddingBagPackedSum, Type::EmbeddingBagPackedSum);
INTEL_CPU_NODE(EmbeddingBagPacked, Type::EmbeddingBagPackedSum);
INTEL_CPU_NODE(EmbeddingBagPacked, Type::EmbeddingBagPacked);
INTEL_CPU_NODE(Input, Type::Input);
INTEL_CPU_NODE(Input, Type::Output);
INTEL_CPU_NODE(MemoryInput, Type::MemoryInput);
@ -158,7 +159,8 @@ Node::NodesFactory::NodesFactory() : Factory("NodesFactory") {
INTEL_CPU_NODE(MultiClassNms, Type::MulticlassNms);
INTEL_CPU_NODE(Convert, Type::Convert);
INTEL_CPU_NODE(ColorConvert, Type::ColorConvert);
INTEL_CPU_NODE(EmbeddingBagOffsetSum, Type::EmbeddingBagOffsetsSum);
INTEL_CPU_NODE(EmbeddingBagOffset, Type::EmbeddingBagOffsetsSum);
INTEL_CPU_NODE(EmbeddingBagOffset, Type::EmbeddingBagOffsets);
INTEL_CPU_NODE(Roll, Type::Roll);
INTEL_CPU_NODE(Pad, Type::Pad);
INTEL_CPU_NODE(Reshape, Type::Reshape);

View File

@ -402,6 +402,8 @@ using IStaticShapeInferFactory =
template <>
const IStaticShapeInferFactory::TRegistry IStaticShapeInferFactory::registry{
// opset15
_OV_OP_SHAPE_INFER_MASK_REG(opset15::EmbeddingBagOffsets, ShapeInferTA, util::bit::mask()),
_OV_OP_SHAPE_INFER_MASK_REG(opset15::EmbeddingBagPacked, ShapeInferTA, util::bit::mask()),
_OV_OP_SHAPE_INFER_MASK_REG(op::v15::Col2Im, ShapeInferTA, util::bit::mask(1, 2)),
// opset14
_OV_OP_SHAPE_INFER_MASK_REG(opset14::Inverse, ShapeInferTA, util::bit::mask()),

View File

@ -0,0 +1,166 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "common_test_utils/node_builders/embedding_bag_offsets.hpp"
#include "shared_test_classes/base/ov_subgraph.hpp"
#include "utils/cpu_test_utils.hpp"
using namespace CPUTestUtils;
namespace ov {
namespace test {
typedef std::tuple<InputShape, // input_shapes
std::vector<size_t>, // indices
std::vector<size_t>, // offsets
size_t, // default_index
bool, // with_weights
bool, // with_def_index
ov::op::util::EmbeddingBagOffsetsBase::Reduction // reduction
>
embeddingBagOffsetsParams;
typedef std::tuple<embeddingBagOffsetsParams,
ElementType, // embedding table
ElementType, // indices
ov::test::TargetDevice>
embeddingBagOffsetsLayerTestParamsSet;
class EmbeddingBagOffsetsLayerCPUTest : public testing::WithParamInterface<embeddingBagOffsetsLayerTestParamsSet>,
virtual public SubgraphBaseTest,
public CPUTestsBase {
public:
using Reduction = ov::op::util::EmbeddingBagOffsetsBase::Reduction;
static std::string getTestCaseName(const testing::TestParamInfo<embeddingBagOffsetsLayerTestParamsSet>& obj) {
embeddingBagOffsetsParams params;
ElementType netPrecision, indPrecision;
std::string targetDevice;
std::tie(params, netPrecision, indPrecision, targetDevice) = obj.param;
InputShape inputShapes;
std::vector<size_t> indices, offsets;
size_t defaultIndex;
bool withWeights, withDefIndex;
Reduction reduction;
std::tie(inputShapes, indices, offsets, defaultIndex, withWeights, withDefIndex, reduction) = params;
std::ostringstream result;
result << "IS=" << inputShapes << "_";
result << "I" << ov::test::utils::vec2str(indices) << "_";
result << "O" << ov::test::utils::vec2str(offsets) << "_";
result << "DI" << defaultIndex << "_";
result << "WW" << withWeights << "_";
result << "WDI" << withDefIndex << "_";
result << "R" << ov::as_string(reduction) << "_";
result << "netPRC=" << netPrecision << "_";
result << "indPRC=" << indPrecision << "_";
result << "targetDevice=" << targetDevice;
return result.str();
}
void SetUp() override {
embeddingBagOffsetsParams embParams;
ElementType indPrecision;
std::tie(embParams, inType, indPrecision, targetDevice) = this->GetParam();
InputShape inputShapes;
std::vector<size_t> indices, offsets;
bool withWeights, withDefIndex;
Reduction reduction;
size_t defaultIndex;
std::tie(inputShapes, indices, offsets, defaultIndex, withWeights, withDefIndex, reduction) = embParams;
selectedType = makeSelectedTypeStr("ref", inType);
targetDevice = ov::test::utils::DEVICE_CPU;
init_input_shapes({inputShapes});
auto emb_table_node = std::make_shared<ov::op::v0::Parameter>(inType, inputShapes.first);
ov::ParameterVector params = {emb_table_node};
auto embBag = std::dynamic_pointer_cast<ov::op::v15::EmbeddingBagOffsets>(
ov::test::utils::make_embedding_bag_offsets(inType,
indPrecision,
emb_table_node,
indices,
offsets,
defaultIndex,
withWeights,
withDefIndex,
reduction));
ov::ResultVector results{std::make_shared<ov::op::v0::Result>(embBag)};
function = std::make_shared<ov::Model>(results, params, "embeddingBagOffsets");
}
};
TEST_P(EmbeddingBagOffsetsLayerCPUTest, CompareWithRefs) {
run();
CheckPluginRelatedResults(compiledModel, "embeddingBagOffsets");
}
namespace {
const std::vector<ElementType> netPrecisions = {ElementType::f32, ElementType::i32, ElementType::u8};
const std::vector<ElementType> indPrecisions = {ElementType::i64, ElementType::i32};
const std::vector<InputShape> input_shapes = {
// dynamic input shapes
{// input model dynamic shapes
{ov::Dimension::dynamic(), ov::Dimension::dynamic()},
// input tensor shapes
{{5, 6}, {10, 35}}},
{// input model dynamic shapes
{ov::Dimension::dynamic(), ov::Dimension::dynamic(), ov::Dimension::dynamic()},
// input tensor shapes
{{5, 4, 16}, {10, 12, 8}}},
{// input model dynamic shapes with limits
{{5, 10}, {6, 35}, {4, 8}},
// input tensor shapes
{{5, 6, 4}, {10, 35, 8}, {5, 6, 4}}},
// static shapes
{{5, 6}, {{5, 6}}},
{{10, 35}, {{10, 35}}},
{{5, 4, 16}, {{5, 4, 16}}},
};
const std::vector<std::vector<size_t>> indices = {{0, 1, 2, 2, 3}, {4, 4, 3, 1, 0}, {1, 2, 1, 2, 1, 2, 1, 2, 1, 2}};
const std::vector<std::vector<size_t>> offsets = {{0, 2}, {0, 0, 2, 2}, {2, 4}};
const std::vector<size_t> default_index = {0, 4};
const std::vector<bool> with_default_index = {false, true};
const std::vector<ov::op::util::EmbeddingBagOffsetsBase::Reduction> reduction = {
ov::op::util::EmbeddingBagOffsetsBase::Reduction::SUM,
ov::op::util::EmbeddingBagOffsetsBase::Reduction::MEAN};
const auto embBagOffsetArgSetWthWeights = ::testing::Combine(::testing::ValuesIn(input_shapes),
::testing::ValuesIn(indices),
::testing::ValuesIn(offsets),
::testing::ValuesIn(default_index),
::testing::Values(true),
::testing::ValuesIn(with_default_index),
::testing::Values(ov::op::util::EmbeddingBagOffsetsBase::Reduction::SUM));
const auto embBagOffsetArgSetNoWeights = ::testing::Combine(::testing::ValuesIn(input_shapes),
::testing::ValuesIn(indices),
::testing::ValuesIn(offsets),
::testing::ValuesIn(default_index),
::testing::Values(false),
::testing::ValuesIn(with_default_index),
::testing::ValuesIn(reduction));
INSTANTIATE_TEST_SUITE_P(smoke_EmbeddingBagOffsets_With_Weights,
EmbeddingBagOffsetsLayerCPUTest,
::testing::Combine(embBagOffsetArgSetWthWeights,
::testing::ValuesIn(netPrecisions),
::testing::ValuesIn(indPrecisions),
::testing::Values(ov::test::utils::DEVICE_CPU)),
EmbeddingBagOffsetsLayerCPUTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(smoke_EmbeddingBagOffsets_No_Weights,
EmbeddingBagOffsetsLayerCPUTest,
::testing::Combine(embBagOffsetArgSetNoWeights,
::testing::ValuesIn(netPrecisions),
::testing::ValuesIn(indPrecisions),
::testing::Values(ov::test::utils::DEVICE_CPU)),
EmbeddingBagOffsetsLayerCPUTest::getTestCaseName);
} // namespace
} // namespace test
} // namespace ov

View File

@ -0,0 +1,153 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "common_test_utils/node_builders/embedding_bag_packed.hpp"
#include "openvino/op/util/embeddingbag_packed_base.hpp"
#include "shared_test_classes/base/ov_subgraph.hpp"
#include "utils/cpu_test_utils.hpp"
using namespace CPUTestUtils;
namespace ov {
namespace test {
typedef std::tuple<InputShape, // input_shapes
std::vector<std::vector<size_t>>, // indices
bool, // with_weights
ov::op::util::EmbeddingBagPackedBase::Reduction // reduction
>
embeddingBagPackedParams;
typedef std::tuple<embeddingBagPackedParams,
ElementType, // embedding table
ElementType, // indices
ov::test::TargetDevice>
embeddingBagPackedLayerTestParamsSet;
class EmbeddingBagPackedLayerCPUTest : public testing::WithParamInterface<embeddingBagPackedLayerTestParamsSet>,
virtual public SubgraphBaseTest,
public CPUTestsBase {
public:
using Reduction = ov::op::util::EmbeddingBagPackedBase::Reduction;
static std::string getTestCaseName(const testing::TestParamInfo<embeddingBagPackedLayerTestParamsSet>& obj) {
embeddingBagPackedParams params;
ElementType netPrecision, indPrecision;
std::string targetDevice;
std::tie(params, netPrecision, indPrecision, targetDevice) = obj.param;
InputShape inputShapes;
std::vector<std::vector<size_t>> indices;
bool withWeights;
Reduction reduction;
std::tie(inputShapes, indices, withWeights, reduction) = params;
std::ostringstream result;
result << "IS=" << inputShapes << "_";
result << "I" << ov::test::utils::vec2str(indices) << "_";
result << "WW" << withWeights << "_";
result << "R" << ov::as_string(reduction) << "_";
result << "netPRC=" << netPrecision << "_";
result << "indPRC=" << indPrecision << "_";
result << "targetDevice=" << targetDevice;
return result.str();
}
protected:
void SetUp() override {
embeddingBagPackedParams embParams;
ElementType indPrecision;
std::tie(embParams, inType, indPrecision, targetDevice) = this->GetParam();
InputShape inputShapes;
std::vector<std::vector<size_t>> indices;
bool withWeights;
Reduction reduction;
std::tie(inputShapes, indices, withWeights, reduction) = embParams;
selectedType = makeSelectedTypeStr("ref", inType);
targetDevice = ov::test::utils::DEVICE_CPU;
init_input_shapes({inputShapes});
auto emb_table_node = std::make_shared<ov::op::v0::Parameter>(inType, inputShapes.first);
ov::ParameterVector params = {emb_table_node};
auto embBag = std::dynamic_pointer_cast<ov::op::v15::EmbeddingBagPacked>(
ov::test::utils::make_embedding_bag_packed(inType,
indPrecision,
emb_table_node,
indices,
withWeights,
reduction));
ov::ResultVector results{std::make_shared<ov::op::v0::Result>(embBag)};
function = std::make_shared<ov::Model>(results, params, "embeddingBagPacked");
}
};
TEST_P(EmbeddingBagPackedLayerCPUTest, CompareWithRefs) {
run();
CheckPluginRelatedResults(compiledModel, "embeddingBagPacked");
}
namespace {
const std::vector<ElementType> netPrecisions = {ElementType::f32, ElementType::i32, ElementType::u8};
const std::vector<ElementType> indPrecisions = {ElementType::i64, ElementType::i32};
const std::vector<InputShape> input_shapes = {
// dynamic input shapes
{// input model dynamic shapes
{ov::Dimension::dynamic(), ov::Dimension::dynamic()},
// input tensor shapes
{{{5, 6}}, {10, 35}}},
{// input model dynamic shapes
{ov::Dimension::dynamic(), ov::Dimension::dynamic(), ov::Dimension::dynamic()},
// input tensor shapes
{{5, 4, 16}, {10, 12, 8}}},
{// input model dynamic shapes with limits
{{5, 10}, {6, 35}, {4, 8}},
// input tensor shapes
{{5, 6, 4}, {10, 35, 8}, {5, 6, 4}}},
// static shapes
{{5, 6}, {{5, 6}}},
{{10, 35}, {{10, 35}}},
{{5, 4, 16}, {{5, 4, 16}}},
};
const std::vector<std::vector<std::vector<size_t>>> indices = {{{0, 1}, {2, 2}, {3, 4}},
{{4, 4, 3}, {1, 0, 2}},
{{1, 2, 1, 2}, {1, 2, 1, 2}}};
const std::vector<ov::op::util::EmbeddingBagPackedBase::Reduction> reduction = {
ov::op::util::EmbeddingBagPackedBase::Reduction::SUM,
ov::op::util::EmbeddingBagPackedBase::Reduction::MEAN};
const auto embBagPackedArgSetWthWeights = ::testing::Combine(::testing::ValuesIn(input_shapes),
::testing::ValuesIn(indices),
::testing::Values(true),
::testing::Values(ov::op::util::EmbeddingBagPackedBase::Reduction::SUM));
const auto embBagPackedArgSetNoWeights = ::testing::Combine(::testing::ValuesIn(input_shapes),
::testing::ValuesIn(indices),
::testing::Values(false),
::testing::ValuesIn(reduction));
INSTANTIATE_TEST_SUITE_P(smoke_EmbeddingBagPacked_With_Weights,
EmbeddingBagPackedLayerCPUTest,
::testing::Combine(embBagPackedArgSetWthWeights,
::testing::ValuesIn(netPrecisions),
::testing::ValuesIn(indPrecisions),
::testing::Values(ov::test::utils::DEVICE_CPU)),
EmbeddingBagPackedLayerCPUTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(smoke_EmbeddingBagPacked_No_Weights,
EmbeddingBagPackedLayerCPUTest,
::testing::Combine(embBagPackedArgSetNoWeights,
::testing::ValuesIn(netPrecisions),
::testing::ValuesIn(indPrecisions),
::testing::Values(ov::test::utils::DEVICE_CPU)),
EmbeddingBagPackedLayerCPUTest::getTestCaseName);
} // namespace
} // namespace test
} // namespace ov

View File

@ -0,0 +1,89 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "openvino/reference/embedding_bag_offsets.hpp"
#include "evaluate_node.hpp"
namespace embedding_bag_offsets_v15 {
template <ov::element::Type_t t1, ov::element::Type_t t2>
inline void evaluate(const std::shared_ptr<ov::op::v15::EmbeddingBagOffsets>& op,
ov::TensorVector& outputs,
const ov::TensorVector& inputs) {
using T1 = typename ov::element_type_traits<t1>::value_type;
using T2 = typename ov::element_type_traits<t2>::value_type;
ov::reference::embeddingBagOffsets<T1, T2>(inputs[0].data<T1>(),
inputs[1].data<T2>(),
inputs[2].data<T2>(),
inputs.size() > 3 ? inputs[3].data<T2>() : nullptr,
inputs.size() > 4 ? inputs[4].data<T1>() : nullptr,
outputs[0].data<T1>(),
ov::shape_size(inputs[1].get_shape()),
outputs[0].get_shape(),
op->get_reduction());
}
} // namespace embedding_bag_offsets_v15
template <ov::element::Type_t ET>
bool evaluate(const std::shared_ptr<ov::op::v15::EmbeddingBagOffsets>& op,
ov::TensorVector& outputs,
const ov::TensorVector& inputs) {
switch (inputs[1].get_element_type()) {
case ov::element::i32:
embedding_bag_offsets_v15::evaluate<ET, ov::element::i32>(op, outputs, inputs);
break;
case ov::element::i64:
embedding_bag_offsets_v15::evaluate<ET, ov::element::i64>(op, outputs, inputs);
break;
default:
return false;
}
return true;
}
template <>
bool evaluate_node<ov::op::v15::EmbeddingBagOffsets>(std::shared_ptr<ov::Node> node,
ov::TensorVector& outputs,
const ov::TensorVector& inputs) {
auto element_type = node->get_output_element_type(0);
if (ov::is_type<ov::op::v1::Select>(node) || ov::is_type<ov::op::util::BinaryElementwiseComparison>(node))
element_type = node->get_input_element_type(1);
switch (element_type) {
case ov::element::boolean:
return evaluate<ov::element::boolean>(ov::as_type_ptr<ov::op::v15::EmbeddingBagOffsets>(node), outputs, inputs);
case ov::element::bf16:
return evaluate<ov::element::bf16>(ov::as_type_ptr<ov::op::v15::EmbeddingBagOffsets>(node), outputs, inputs);
case ov::element::f16:
return evaluate<ov::element::f16>(ov::as_type_ptr<ov::op::v15::EmbeddingBagOffsets>(node), outputs, inputs);
case ov::element::f64:
return evaluate<ov::element::f64>(ov::as_type_ptr<ov::op::v15::EmbeddingBagOffsets>(node), outputs, inputs);
case ov::element::f32:
return evaluate<ov::element::f32>(ov::as_type_ptr<ov::op::v15::EmbeddingBagOffsets>(node), outputs, inputs);
case ov::element::i4:
return evaluate<ov::element::i4>(ov::as_type_ptr<ov::op::v15::EmbeddingBagOffsets>(node), outputs, inputs);
case ov::element::i8:
return evaluate<ov::element::i8>(ov::as_type_ptr<ov::op::v15::EmbeddingBagOffsets>(node), outputs, inputs);
case ov::element::i16:
return evaluate<ov::element::i16>(ov::as_type_ptr<ov::op::v15::EmbeddingBagOffsets>(node), outputs, inputs);
case ov::element::i32:
return evaluate<ov::element::i32>(ov::as_type_ptr<ov::op::v15::EmbeddingBagOffsets>(node), outputs, inputs);
case ov::element::i64:
return evaluate<ov::element::i64>(ov::as_type_ptr<ov::op::v15::EmbeddingBagOffsets>(node), outputs, inputs);
case ov::element::u1:
return evaluate<ov::element::u1>(ov::as_type_ptr<ov::op::v15::EmbeddingBagOffsets>(node), outputs, inputs);
case ov::element::u4:
return evaluate<ov::element::u4>(ov::as_type_ptr<ov::op::v15::EmbeddingBagOffsets>(node), outputs, inputs);
case ov::element::u8:
return evaluate<ov::element::u8>(ov::as_type_ptr<ov::op::v15::EmbeddingBagOffsets>(node), outputs, inputs);
case ov::element::u16:
return evaluate<ov::element::u16>(ov::as_type_ptr<ov::op::v15::EmbeddingBagOffsets>(node), outputs, inputs);
case ov::element::u32:
return evaluate<ov::element::u32>(ov::as_type_ptr<ov::op::v15::EmbeddingBagOffsets>(node), outputs, inputs);
case ov::element::u64:
return evaluate<ov::element::u64>(ov::as_type_ptr<ov::op::v15::EmbeddingBagOffsets>(node), outputs, inputs);
default:
OPENVINO_THROW("Unhandled data type ", node->get_element_type().get_type_name(), " in evaluate_node()");
}
}

View File

@ -2,9 +2,8 @@
// SPDX-License-Identifier: Apache-2.0
//
#include "openvino/reference/embedding_bag_offsets_sum.hpp"
#include "evaluate_node.hpp"
#include "openvino/reference/embedding_bag_offsets.hpp"
namespace embedding_bag_offsets_sum_v3 {
template <ov::element::Type_t t1, ov::element::Type_t t2>
@ -13,14 +12,15 @@ inline void evaluate(const std::shared_ptr<ov::op::v3::EmbeddingBagOffsetsSum>&
const ov::TensorVector& inputs) {
using T1 = typename ov::element_type_traits<t1>::value_type;
using T2 = typename ov::element_type_traits<t2>::value_type;
ov::reference::embeddingBagOffsetsSum<T1, T2>(inputs[0].data<T1>(),
inputs[1].data<T2>(),
inputs[2].data<T2>(),
inputs.size() > 3 ? inputs[3].data<T2>() : nullptr,
inputs.size() > 4 ? inputs[4].data<T1>() : nullptr,
outputs[0].data<T1>(),
ov::shape_size(inputs[1].get_shape()),
outputs[0].get_shape());
ov::reference::embeddingBagOffsets<T1, T2>(inputs[0].data<T1>(),
inputs[1].data<T2>(),
inputs[2].data<T2>(),
inputs.size() > 3 ? inputs[3].data<T2>() : nullptr,
inputs.size() > 4 ? inputs[4].data<T1>() : nullptr,
outputs[0].data<T1>(),
ov::shape_size(inputs[1].get_shape()),
outputs[0].get_shape(),
ov::op::v3::EmbeddingBagOffsetsSum::Reduction::SUM);
}
} // namespace embedding_bag_offsets_sum_v3

View File

@ -0,0 +1,88 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "openvino/reference/embedding_bag_packed.hpp"
#include "evaluate_node.hpp"
namespace embedding_bag_packed_v15 {
template <ov::element::Type_t t1, ov::element::Type_t t2>
inline void evaluate(const std::shared_ptr<ov::op::v15::EmbeddingBagPacked>& op,
ov::TensorVector& outputs,
const ov::TensorVector& inputs) {
using T1 = typename ov::element_type_traits<t1>::value_type;
using T2 = typename ov::element_type_traits<t2>::value_type;
ov::reference::embeddingBagPacked<T1, T2>(inputs[0].data<T1>(),
inputs[1].data<T2>(),
inputs.size() > 2 ? inputs[2].data<T1>() : nullptr,
outputs[0].data<T1>(),
inputs[1].get_shape(),
outputs[0].get_shape(),
op->get_reduction());
}
} // namespace embedding_bag_packed_v15
template <ov::element::Type_t ET>
bool evaluate(const std::shared_ptr<ov::op::v15::EmbeddingBagPacked>& op,
ov::TensorVector& outputs,
const ov::TensorVector& inputs) {
switch (inputs[1].get_element_type()) {
case ov::element::i32:
embedding_bag_packed_v15::evaluate<ET, ov::element::i32>(op, outputs, inputs);
break;
case ov::element::i64:
embedding_bag_packed_v15::evaluate<ET, ov::element::i64>(op, outputs, inputs);
break;
default:
return false;
}
return true;
}
template <>
bool evaluate_node<ov::op::v15::EmbeddingBagPacked>(std::shared_ptr<ov::Node> node,
ov::TensorVector& outputs,
const ov::TensorVector& inputs) {
auto element_type = node->get_output_element_type(0);
if (ov::is_type<ov::op::v1::Select>(node) || ov::is_type<ov::op::util::BinaryElementwiseComparison>(node))
element_type = node->get_input_element_type(1);
switch (element_type) {
case ov::element::boolean:
return evaluate<ov::element::boolean>(ov::as_type_ptr<ov::op::v15::EmbeddingBagPacked>(node), outputs, inputs);
case ov::element::bf16:
return evaluate<ov::element::bf16>(ov::as_type_ptr<ov::op::v15::EmbeddingBagPacked>(node), outputs, inputs);
case ov::element::f16:
return evaluate<ov::element::f16>(ov::as_type_ptr<ov::op::v15::EmbeddingBagPacked>(node), outputs, inputs);
case ov::element::f64:
return evaluate<ov::element::f64>(ov::as_type_ptr<ov::op::v15::EmbeddingBagPacked>(node), outputs, inputs);
case ov::element::f32:
return evaluate<ov::element::f32>(ov::as_type_ptr<ov::op::v15::EmbeddingBagPacked>(node), outputs, inputs);
case ov::element::i4:
return evaluate<ov::element::i4>(ov::as_type_ptr<ov::op::v15::EmbeddingBagPacked>(node), outputs, inputs);
case ov::element::i8:
return evaluate<ov::element::i8>(ov::as_type_ptr<ov::op::v15::EmbeddingBagPacked>(node), outputs, inputs);
case ov::element::i16:
return evaluate<ov::element::i16>(ov::as_type_ptr<ov::op::v15::EmbeddingBagPacked>(node), outputs, inputs);
case ov::element::i32:
return evaluate<ov::element::i32>(ov::as_type_ptr<ov::op::v15::EmbeddingBagPacked>(node), outputs, inputs);
case ov::element::i64:
return evaluate<ov::element::i64>(ov::as_type_ptr<ov::op::v15::EmbeddingBagPacked>(node), outputs, inputs);
case ov::element::u1:
return evaluate<ov::element::u1>(ov::as_type_ptr<ov::op::v15::EmbeddingBagPacked>(node), outputs, inputs);
case ov::element::u4:
return evaluate<ov::element::u4>(ov::as_type_ptr<ov::op::v15::EmbeddingBagPacked>(node), outputs, inputs);
case ov::element::u8:
return evaluate<ov::element::u8>(ov::as_type_ptr<ov::op::v15::EmbeddingBagPacked>(node), outputs, inputs);
case ov::element::u16:
return evaluate<ov::element::u16>(ov::as_type_ptr<ov::op::v15::EmbeddingBagPacked>(node), outputs, inputs);
case ov::element::u32:
return evaluate<ov::element::u32>(ov::as_type_ptr<ov::op::v15::EmbeddingBagPacked>(node), outputs, inputs);
case ov::element::u64:
return evaluate<ov::element::u64>(ov::as_type_ptr<ov::op::v15::EmbeddingBagPacked>(node), outputs, inputs);
default:
OPENVINO_THROW("Unhandled data type ", node->get_element_type().get_type_name(), " in evaluate_node()");
}
}

View File

@ -2,9 +2,8 @@
// SPDX-License-Identifier: Apache-2.0
//
#include "openvino/reference/embedding_bag_packed_sum.hpp"
#include "evaluate_node.hpp"
#include "openvino/reference/embedding_bag_packed.hpp"
namespace embedding_bag_packed_sum_v3 {
template <ov::element::Type_t t1, ov::element::Type_t t2>
@ -13,12 +12,13 @@ inline void evaluate(const std::shared_ptr<ov::op::v3::EmbeddingBagPackedSum>& o
const ov::TensorVector& inputs) {
using T1 = typename ov::element_type_traits<t1>::value_type;
using T2 = typename ov::element_type_traits<t2>::value_type;
ov::reference::embeddingBagPackedSum<T1, T2>(inputs[0].data<T1>(),
inputs[1].data<T2>(),
inputs.size() > 2 ? inputs[2].data<T1>() : nullptr,
outputs[0].data<T1>(),
inputs[1].get_shape(),
outputs[0].get_shape());
ov::reference::embeddingBagPacked<T1, T2>(inputs[0].data<T1>(),
inputs[1].data<T2>(),
inputs.size() > 2 ? inputs[2].data<T1>() : nullptr,
outputs[0].data<T1>(),
inputs[1].get_shape(),
outputs[0].get_shape(),
ov::op::v3::EmbeddingBagPackedSum::Reduction::SUM);
}
} // namespace embedding_bag_packed_sum_v3

View File

@ -498,6 +498,13 @@ extern template bool evaluate_node<ov::op::v14::ROIAlignRotated>(std::shared_ptr
ov::TensorVector& outputs,
const ov::TensorVector& inputs);
extern template bool evaluate_node<ov::op::v15::EmbeddingBagOffsets>(std::shared_ptr<ov::Node> node,
ov::TensorVector& outputs,
const ov::TensorVector& inputs);
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::internal::AUGRUCell>(std::shared_ptr<ov::Node> node,
ov::TensorVector& outputs,
const ov::TensorVector& inputs);

View File

@ -164,6 +164,9 @@ _OPENVINO_OP_REG(AvgPool, ov::op::v14)
_OPENVINO_OP_REG(MaxPool, ov::op::v14)
_OPENVINO_OP_REG(ROIAlignRotated, ov::op::v14)
_OPENVINO_OP_REG(EmbeddingBagOffsets, op::v15)
_OPENVINO_OP_REG(EmbeddingBagPacked, op::v15)
_OPENVINO_OP_REG(AUGRUCell, ov::op::internal)
_OPENVINO_OP_REG(AUGRUSequence, ov::op::internal)
_OPENVINO_OP_REG(RMSNorm, ov::op::internal)

View File

@ -0,0 +1,275 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "openvino/op/embeddingbag_offsets.hpp"
#include <gtest/gtest.h>
#include "base_reference_test.hpp"
#include "openvino/op/constant.hpp"
using namespace reference_tests;
using namespace ov;
struct EmbeddingBagOffsetsParams {
template <class IT>
EmbeddingBagOffsetsParams(const ov::Shape& iShape,
const ov::element::Type& iType,
const std::vector<IT>& iValues,
const ov::Shape& oShape,
const ov::element::Type& oType,
const std::vector<IT>& oValues,
const std::shared_ptr<ov::op::v0::Constant>& indices,
const std::shared_ptr<ov::op::v0::Constant>& offsets,
const ov::op::v15::EmbeddingBagOffsets::Reduction reduction,
const std::shared_ptr<ov::op::v0::Constant>& default_index = nullptr,
const std::shared_ptr<ov::op::v0::Constant>& per_sample_weights = nullptr)
: _iShape(iShape),
_iType(iType),
_iData(CreateTensor(iShape, iType, iValues)),
_refShape(oShape),
_refType(oType),
_refData(CreateTensor(oShape, oType, oValues)) {
_indices = indices;
_offsets = offsets;
_reduction = reduction;
_defaultIndex = default_index;
_perSampleWeights = per_sample_weights;
}
ov::Shape _iShape;
ov::element::Type _iType;
ov::Tensor _iData;
ov::Shape _refShape;
ov::element::Type _refType;
ov::Tensor _refData;
std::shared_ptr<ov::op::v0::Constant> _indices;
std::shared_ptr<ov::op::v0::Constant> _offsets;
ov::op::v15::EmbeddingBagOffsets::Reduction _reduction;
std::shared_ptr<ov::op::v0::Constant> _defaultIndex; // Optional, default filled zero.
std::shared_ptr<ov::op::v0::Constant> _perSampleWeights; // Optional, default is tensor of ones.
};
class ReferenceEmbeddingBagOffsetsLayerTest : public testing::TestWithParam<EmbeddingBagOffsetsParams>,
public CommonReferenceTest {
public:
void SetUp() override {
auto params = GetParam();
function = CreateFunction(params._iShape,
params._iType,
params._indices,
params._offsets,
params._reduction,
params._defaultIndex,
params._perSampleWeights);
inputData = {params._iData};
refOutData = {params._refData};
}
static std::string getTestCaseName(const testing::TestParamInfo<EmbeddingBagOffsetsParams>& obj) {
auto param = obj.param;
std::ostringstream result;
result << "_iShape=" << param._iShape << "_";
result << "_iType=" << param._iType << "_";
result << "_refShape=" << param._refShape << "_";
result << "_refType=" << param._refType << "_";
result << "_reduction=" << param._reduction;
return result.str();
}
private:
static std::shared_ptr<ov::Model> CreateFunction(const Shape& input_shape,
const element::Type& input_type,
const std::shared_ptr<ov::op::v0::Constant> indices,
const std::shared_ptr<ov::op::v0::Constant> offsets,
const ov::op::v15::EmbeddingBagOffsets::Reduction reduction,
const std::shared_ptr<ov::op::v0::Constant> default_index,
const std::shared_ptr<ov::op::v0::Constant> per_sample_weights) {
const auto in = std::make_shared<op::v0::Parameter>(input_type, input_shape);
if (default_index) {
if (per_sample_weights) {
const auto ess = std::make_shared<op::v15::EmbeddingBagOffsets>(in,
indices,
offsets,
default_index,
per_sample_weights,
reduction);
return std::make_shared<Model>(NodeVector{ess}, ParameterVector{in});
} else {
const auto ess =
std::make_shared<op::v15::EmbeddingBagOffsets>(in, indices, offsets, default_index, reduction);
return std::make_shared<Model>(NodeVector{ess}, ParameterVector{in});
}
} else {
const auto ess = std::make_shared<op::v15::EmbeddingBagOffsets>(in, indices, offsets, reduction);
return std::make_shared<Model>(NodeVector{ess}, ParameterVector{in});
}
}
};
TEST_P(ReferenceEmbeddingBagOffsetsLayerTest, CompareWithRefs) {
Exec();
}
INSTANTIATE_TEST_SUITE_P(
smoke_EmbeddingBagOffsets_With_Hardcoded_Refs,
ReferenceEmbeddingBagOffsetsLayerTest,
::testing::Values(
EmbeddingBagOffsetsParams(
ov::Shape{5, 2},
ov::element::f32,
std::vector<float>{-0.2, -0.6, -0.1, -0.4, -1.9, -1.8, -1., 1.5, 0.8, -0.7},
ov::Shape{3, 2},
ov::element::f32,
{-1.05f, -1.2f, -0.2f, -0.6f, -0.1f, 0.4f},
std::make_shared<ov::op::v0::Constant>(element::i32, ov::Shape({4}), std::vector<int32_t>{0, 2, 3, 4}),
std::make_shared<ov::op::v0::Constant>(element::i32, ov::Shape({3}), std::vector<int32_t>{0, 2, 2}),
ov::op::v15::EmbeddingBagOffsets::Reduction::SUM,
std::make_shared<ov::op::v0::Constant>(element::i32, ov::Shape(), std::vector<int32_t>{0}),
std::make_shared<ov::op::v0::Constant>(element::f32,
ov::Shape({4}),
std::vector<float>{0.5, 0.5, 0.5, 0.5})),
EmbeddingBagOffsetsParams(
ov::Shape{5, 2},
ov::element::f64,
std::vector<double>{-0.2, -0.6, -0.1, -0.4, -1.9, -1.8, -1., 1.5, 0.8, -0.7},
ov::Shape{3, 2},
ov::element::f64,
std::vector<double>{-2.1, -2.4, -0.2, -0.6, -0.2, 0.8},
std::make_shared<ov::op::v0::Constant>(element::i32, ov::Shape({4}), std::vector<int32_t>{0, 2, 3, 4}),
std::make_shared<ov::op::v0::Constant>(element::i32, ov::Shape({3}), std::vector<int32_t>{0, 2, 2}),
ov::op::v15::EmbeddingBagOffsets::Reduction::SUM,
std::make_shared<ov::op::v0::Constant>(element::i32, ov::Shape(), std::vector<int32_t>{0})),
EmbeddingBagOffsetsParams(
ov::Shape{5, 2},
ov::element::i32,
std::vector<int32_t>{-1, 2, 3, 4, -5, -6, -7, 8, 9, 10},
ov::Shape{3, 2},
ov::element::i32,
std::vector<int32_t>{-6, -4, 0, 0, 2, 18},
std::make_shared<ov::op::v0::Constant>(element::i32, ov::Shape({4}), std::vector<int32_t>{0, 2, 3, 4}),
std::make_shared<ov::op::v0::Constant>(element::i32, ov::Shape({3}), std::vector<int32_t>{0, 2, 2}),
ov::op::v15::EmbeddingBagOffsets::Reduction::SUM),
EmbeddingBagOffsetsParams(
ov::Shape{5, 2},
ov::element::u32,
std::vector<uint32_t>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
ov::Shape{3, 2},
ov::element::u32,
std::vector<uint32_t>{6, 8, 3, 4, 16, 18},
std::make_shared<ov::op::v0::Constant>(element::i32, ov::Shape({4}), std::vector<int32_t>{0, 2, 3, 4}),
std::make_shared<ov::op::v0::Constant>(element::i32, ov::Shape({3}), std::vector<int32_t>{0, 2, 2}),
ov::op::v15::EmbeddingBagOffsets::Reduction::SUM,
std::make_shared<ov::op::v0::Constant>(element::i32, ov::Shape(), std::vector<int32_t>{1})),
EmbeddingBagOffsetsParams(
ov::Shape{5, 2},
ov::element::f16,
std::vector<float16>{-0.2, -0.6, -0.1, -0.4, -1.9, -1.8, -1., 1.5, 0.8, -0.7},
ov::Shape{3, 2},
ov::element::f16,
std::vector<float16>{-2.1, -2.4, 0, 0, -0.2, 0.8},
std::make_shared<ov::op::v0::Constant>(element::i64, ov::Shape({4}), std::vector<int64_t>{0, 2, 3, 4}),
std::make_shared<ov::op::v0::Constant>(element::i64, ov::Shape({3}), std::vector<int64_t>{0, 2, 2}),
ov::op::v15::EmbeddingBagOffsets::Reduction::SUM),
EmbeddingBagOffsetsParams(
ov::Shape{5, 2},
ov::element::i64,
std::vector<int64_t>{-1, 2, 3, 4, -5, -6, -7, 8, 9, 10},
ov::Shape{3, 2},
ov::element::i64,
std::vector<int64_t>{-6, -4, -1, 2, 2, 18},
std::make_shared<ov::op::v0::Constant>(element::i64, ov::Shape({4}), std::vector<int64_t>{0, 2, 3, 4}),
std::make_shared<ov::op::v0::Constant>(element::i64, ov::Shape({3}), std::vector<int64_t>{0, 2, 2}),
ov::op::v15::EmbeddingBagOffsets::Reduction::SUM,
std::make_shared<ov::op::v0::Constant>(element::i64, ov::Shape(), std::vector<int64_t>{0})),
EmbeddingBagOffsetsParams(
ov::Shape{5, 2},
ov::element::i8,
std::vector<int8_t>{-1, 2, 3, 4, -5, -6, -7, 8, 9, 10},
ov::Shape{3, 2},
ov::element::i8,
std::vector<int8_t>{-12, -8, -1, 2, 4, 36},
std::make_shared<ov::op::v0::Constant>(element::i64, ov::Shape({4}), std::vector<int64_t>{0, 2, 3, 4}),
std::make_shared<ov::op::v0::Constant>(element::i64, ov::Shape({3}), std::vector<int64_t>{0, 2, 2}),
ov::op::v15::EmbeddingBagOffsets::Reduction::SUM,
std::make_shared<ov::op::v0::Constant>(element::i64, ov::Shape(), std::vector<int64_t>{0}),
std::make_shared<ov::op::v0::Constant>(element::i8, ov::Shape({4}), std::vector<int8_t>{2, 2, 2, 2})),
EmbeddingBagOffsetsParams(
ov::Shape{5, 2},
ov::element::u8,
std::vector<uint8_t>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
ov::Shape{3, 2},
ov::element::u8,
std::vector<uint8_t>{6, 8, 1, 2, 16, 18},
std::make_shared<ov::op::v0::Constant>(element::i32, ov::Shape({4}), std::vector<int32_t>{0, 2, 3, 4}),
std::make_shared<ov::op::v0::Constant>(element::i32, ov::Shape({3}), std::vector<int32_t>{0, 2, 2}),
ov::op::v15::EmbeddingBagOffsets::Reduction::SUM,
std::make_shared<ov::op::v0::Constant>(element::i32, ov::Shape(), std::vector<int32_t>{0})),
// Reduction MEAN
EmbeddingBagOffsetsParams(
ov::Shape{5, 2},
ov::element::f64,
std::vector<double>{-0.2, -0.6, -0.1, -0.4, -1.9, -1.8, -1., 1.5, 0.8, -0.7},
ov::Shape{3, 2},
ov::element::f64,
std::vector<double>{-1.05, -1.2, -0.2, -0.6, -0.1, 0.4},
std::make_shared<ov::op::v0::Constant>(element::i32, ov::Shape({4}), std::vector<int32_t>{0, 2, 3, 4}),
std::make_shared<ov::op::v0::Constant>(element::i32, ov::Shape({3}), std::vector<int32_t>{0, 2, 2}),
ov::op::v15::EmbeddingBagOffsets::Reduction::MEAN,
std::make_shared<ov::op::v0::Constant>(element::i32, ov::Shape(), std::vector<int32_t>{0})),
EmbeddingBagOffsetsParams(
ov::Shape{5, 2},
ov::element::i32,
std::vector<int32_t>{-1, 2, 3, 4, -5, -6, -7, 8, 9, 10},
ov::Shape{3, 2},
ov::element::i32,
std::vector<int32_t>{-3, -2, 0, 0, 1, 9},
std::make_shared<ov::op::v0::Constant>(element::i32, ov::Shape({4}), std::vector<int32_t>{0, 2, 3, 4}),
std::make_shared<ov::op::v0::Constant>(element::i32, ov::Shape({3}), std::vector<int32_t>{0, 2, 2}),
ov::op::v15::EmbeddingBagOffsets::Reduction::MEAN),
EmbeddingBagOffsetsParams(
ov::Shape{5, 2},
ov::element::u32,
std::vector<uint32_t>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
ov::Shape{3, 2},
ov::element::u32,
std::vector<uint32_t>{3, 4, 3, 4, 8, 9},
std::make_shared<ov::op::v0::Constant>(element::i32, ov::Shape({4}), std::vector<int32_t>{0, 2, 3, 4}),
std::make_shared<ov::op::v0::Constant>(element::i32, ov::Shape({3}), std::vector<int32_t>{0, 2, 2}),
ov::op::v15::EmbeddingBagOffsets::Reduction::MEAN,
std::make_shared<ov::op::v0::Constant>(element::i32, ov::Shape(), std::vector<int32_t>{1})),
EmbeddingBagOffsetsParams(
ov::Shape{5, 2},
ov::element::f16,
std::vector<float16>{-0.2, -0.6, -0.1, -0.4, -1.9, -1.8, -1., 1.5, 0.8, -0.7},
ov::Shape{3, 2},
ov::element::f16,
std::vector<float16>{-1.05, -1.2, 0, 0, -0.1, 0.4},
std::make_shared<ov::op::v0::Constant>(element::i64, ov::Shape({4}), std::vector<int64_t>{0, 2, 3, 4}),
std::make_shared<ov::op::v0::Constant>(element::i64, ov::Shape({3}), std::vector<int64_t>{0, 2, 2}),
ov::op::v15::EmbeddingBagOffsets::Reduction::MEAN),
EmbeddingBagOffsetsParams(
ov::Shape{5, 2},
ov::element::i64,
std::vector<int64_t>{-1, 2, 3, 4, -5, -6, -7, 8, 9, 10},
ov::Shape{3, 2},
ov::element::i64,
std::vector<int64_t>{-3, -2, -1, 2, 1, 9},
std::make_shared<ov::op::v0::Constant>(element::i64, ov::Shape({4}), std::vector<int64_t>{0, 2, 3, 4}),
std::make_shared<ov::op::v0::Constant>(element::i64, ov::Shape({3}), std::vector<int64_t>{0, 2, 2}),
ov::op::v15::EmbeddingBagOffsets::Reduction::MEAN,
std::make_shared<ov::op::v0::Constant>(element::i64, ov::Shape(), std::vector<int64_t>{0})),
EmbeddingBagOffsetsParams(
ov::Shape{5, 2},
ov::element::u8,
std::vector<uint8_t>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
ov::Shape{3, 2},
ov::element::u8,
std::vector<uint8_t>{3, 4, 1, 2, 8, 9},
std::make_shared<ov::op::v0::Constant>(element::i32, ov::Shape({4}), std::vector<int32_t>{0, 2, 3, 4}),
std::make_shared<ov::op::v0::Constant>(element::i32, ov::Shape({3}), std::vector<int32_t>{0, 2, 2}),
ov::op::v15::EmbeddingBagOffsets::Reduction::MEAN,
std::make_shared<ov::op::v0::Constant>(element::i32, ov::Shape(), std::vector<int32_t>{0}))),
ReferenceEmbeddingBagOffsetsLayerTest::getTestCaseName);

View File

@ -0,0 +1,232 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "openvino/op/embeddingbag_packed.hpp"
#include <gtest/gtest.h>
#include "base_reference_test.hpp"
#include "openvino/op/constant.hpp"
using namespace reference_tests;
using namespace ov;
struct EmbeddingBagPackedParams {
template <class IT>
EmbeddingBagPackedParams(const ov::Shape& iShape,
const ov::element::Type& iType,
const std::vector<IT>& iValues,
const ov::Shape& oShape,
const ov::element::Type& oType,
const std::vector<IT>& oValues,
const std::shared_ptr<ov::op::v0::Constant>& indices,
const ov::op::v15::EmbeddingBagPacked::Reduction reduction,
const std::shared_ptr<ov::op::v0::Constant>& per_sample_weights = nullptr)
: _iShape(iShape),
_iType(iType),
_iData(CreateTensor(iShape, iType, iValues)),
_refShape(oShape),
_refType(oType),
_refData(CreateTensor(oShape, oType, oValues)) {
_indices = indices;
_reduction = reduction;
_perSampleWeights = per_sample_weights;
}
ov::Shape _iShape;
ov::element::Type _iType;
ov::Tensor _iData;
ov::Shape _refShape;
ov::element::Type _refType;
ov::Tensor _refData;
std::shared_ptr<ov::op::v0::Constant> _indices;
ov::op::v15::EmbeddingBagPacked::Reduction _reduction;
std::shared_ptr<ov::op::v0::Constant> _perSampleWeights; // Optional, default is tensor of ones.
};
class ReferenceEmbeddingBagPackedLayerTest : public testing::TestWithParam<EmbeddingBagPackedParams>,
public CommonReferenceTest {
public:
void SetUp() override {
auto params = GetParam();
function =
CreateFunction(params._iShape, params._iType, params._indices, params._reduction, params._perSampleWeights);
inputData = {params._iData};
refOutData = {params._refData};
}
static std::string getTestCaseName(const testing::TestParamInfo<EmbeddingBagPackedParams>& obj) {
auto param = obj.param;
std::ostringstream result;
result << "_iShape=" << param._iShape << "_";
result << "_iType=" << param._iType << "_";
result << "_refShape=" << param._refShape << "_";
result << "_refType=" << param._refType << "_";
result << "_reduction=" << param._reduction;
return result.str();
}
private:
static std::shared_ptr<Model> CreateFunction(const Shape& input_shape,
const element::Type& input_type,
const std::shared_ptr<ov::op::v0::Constant> indices,
const ov::op::v15::EmbeddingBagPacked::Reduction reduction,
const std::shared_ptr<ov::op::v0::Constant> per_sample_weights) {
const auto in = std::make_shared<op::v0::Parameter>(input_type, input_shape);
if (per_sample_weights) {
const auto ess = std::make_shared<op::v15::EmbeddingBagPacked>(in, indices, per_sample_weights, reduction);
return std::make_shared<Model>(NodeVector{ess}, ParameterVector{in});
} else {
const auto ess = std::make_shared<op::v15::EmbeddingBagPacked>(in, indices, reduction);
return std::make_shared<Model>(NodeVector{ess}, ParameterVector{in});
}
}
};
TEST_P(ReferenceEmbeddingBagPackedLayerTest, CompareWithRefs) {
Exec();
}
template <class T>
inline std::shared_ptr<ov::op::v0::Constant> CreateConstant(const std::vector<std::vector<T>>& val,
const ov::element::Type& element_type) {
if (val.size() > 0) {
ov::Shape i_shape({val.size(), val[0].size()});
size_t i_size = ov::shape_size(i_shape);
std::vector<T> i_values(i_size);
for (size_t i = 0; i < i_shape[0]; i++) {
for (size_t j = 0; j < i_shape[1]; j++) {
i_values[i * i_shape[1] + j] = val[i][j];
}
}
return std::make_shared<ov::op::v0::Constant>(element_type, i_shape, i_values);
} else {
return std::make_shared<ov::op::v0::Constant>(element_type, ov::Shape(), std::vector<T>());
}
}
INSTANTIATE_TEST_SUITE_P(
smoke_EmbeddingBagPacked_With_Hardcoded_Refs,
ReferenceEmbeddingBagPackedLayerTest,
::testing::Values(
EmbeddingBagPackedParams(ov::Shape{5, 2},
ov::element::f32,
std::vector<float>{-0.2, -0.6, -0.1, -0.4, -1.9, -1.8, -1., 1.5, 0.8, -0.7},
ov::Shape{3, 2},
ov::element::f32,
std::vector<float>{-1.05f, -1.2f, -1.f, -1.1f, -0.1f, 0.4f},
CreateConstant<int32_t>({{0, 2}, {1, 2}, {3, 4}}, element::i32),
ov::op::v15::EmbeddingBagPacked::Reduction::SUM,
CreateConstant<float>({{0.5, 0.5}, {0.5, 0.5}, {0.5, 0.5}}, element::f32)),
EmbeddingBagPackedParams(ov::Shape{5, 2},
ov::element::f64,
std::vector<double>{-0.2, -0.6, -0.1, -0.4, -1.9, -1.8, -1., 1.5, 0.8, -0.7},
ov::Shape{3, 2},
ov::element::f64,
std::vector<double>{-2.1, -2.4, -2.0, -2.2, -0.2, 0.8},
CreateConstant<int32_t>({{0, 2}, {1, 2}, {3, 4}}, element::i32),
ov::op::v15::EmbeddingBagPacked::Reduction::SUM),
EmbeddingBagPackedParams(ov::Shape{5, 2},
ov::element::i32,
std::vector<int32_t>{-1, 2, 3, 4, -5, -6, -7, 8, 9, 10},
ov::Shape{3, 2},
ov::element::i32,
std::vector<int32_t>{-6, -4, -2, -2, 2, 18},
CreateConstant<int32_t>({{0, 2}, {1, 2}, {3, 4}}, element::i32),
ov::op::v15::EmbeddingBagPacked::Reduction::SUM),
EmbeddingBagPackedParams(ov::Shape{5, 2},
ov::element::u32,
std::vector<uint32_t>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
ov::Shape{3, 2},
ov::element::u32,
std::vector<uint32_t>{6, 8, 8, 10, 16, 18},
CreateConstant<int32_t>({{0, 2}, {1, 2}, {3, 4}}, element::i32),
ov::op::v15::EmbeddingBagPacked::Reduction::SUM),
EmbeddingBagPackedParams(ov::Shape{5, 2},
ov::element::f16,
std::vector<float16>{-0.2, -0.6, -0.1, -0.4, -1.9, -1.8, -1., 1.5, 0.8, -0.7},
ov::Shape{3, 2},
ov::element::f16,
std::vector<float16>{-2.1, -2.4, -2.0, -2.2, -0.2, 0.8},
CreateConstant<int64_t>({{0, 2}, {1, 2}, {3, 4}}, element::i64),
ov::op::v15::EmbeddingBagPacked::Reduction::SUM),
EmbeddingBagPackedParams(ov::Shape{5, 2},
ov::element::i64,
std::vector<int64_t>{-1, 2, 3, 4, -5, -6, -7, 8, 9, 10},
ov::Shape{3, 2},
ov::element::i64,
std::vector<int64_t>{-6, -4, -2, -2, 2, 18},
CreateConstant<int64_t>({{0, 2}, {1, 2}, {3, 4}}, element::i64),
ov::op::v15::EmbeddingBagPacked::Reduction::SUM),
EmbeddingBagPackedParams(ov::Shape{5, 2},
ov::element::i8,
std::vector<int8_t>{-1, 2, 3, 4, -5, -6, -7, 8, 9, 10},
ov::Shape{3, 2},
ov::element::i8,
std::vector<int8_t>{-12, -8, -4, -4, 4, 36},
CreateConstant<int64_t>({{0, 2}, {1, 2}, {3, 4}}, element::i64),
ov::op::v15::EmbeddingBagPacked::Reduction::SUM,
CreateConstant<int8_t>({{2, 2}, {2, 2}, {2, 2}}, element::i8)),
EmbeddingBagPackedParams(ov::Shape{5, 2},
ov::element::u8,
std::vector<uint8_t>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
ov::Shape{3, 2},
ov::element::u8,
std::vector<uint8_t>{6, 8, 8, 10, 16, 18},
CreateConstant<int64_t>({{0, 2}, {1, 2}, {3, 4}}, element::i64),
ov::op::v15::EmbeddingBagPacked::Reduction::SUM),
// Reduction MEAN
EmbeddingBagPackedParams(ov::Shape{5, 2},
ov::element::f64,
std::vector<double>{-0.2, -0.6, -0.1, -0.4, -1.9, -1.8, -1., 1.5, 0.8, -0.7},
ov::Shape{3, 2},
ov::element::f64,
std::vector<double>{-1.05, -1.2, -1., -1.1, -0.1, 0.4},
CreateConstant<int32_t>({{0, 2}, {1, 2}, {3, 4}}, element::i32),
ov::op::v15::EmbeddingBagPacked::Reduction::MEAN),
EmbeddingBagPackedParams(ov::Shape{5, 2},
ov::element::i32,
std::vector<int32_t>{-1, 2, 3, 4, -5, -6, -7, 8, 9, 10},
ov::Shape{3, 2},
ov::element::i32,
std::vector<int32_t>{-3, -2, -1, -1, 1, 9},
CreateConstant<int32_t>({{0, 2}, {1, 2}, {3, 4}}, element::i32),
ov::op::v15::EmbeddingBagPacked::Reduction::MEAN),
EmbeddingBagPackedParams(ov::Shape{5, 2},
ov::element::u32,
std::vector<uint32_t>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
ov::Shape{3, 2},
ov::element::u32,
std::vector<uint32_t>{3, 4, 4, 5, 8, 9},
CreateConstant<int32_t>({{0, 2}, {1, 2}, {3, 4}}, element::i32),
ov::op::v15::EmbeddingBagPacked::Reduction::MEAN),
EmbeddingBagPackedParams(ov::Shape{5, 2},
ov::element::f16,
std::vector<float16>{-0.2, -0.6, -0.1, -0.4, -1.9, -1.8, -1., 1.5, 0.8, -0.7},
ov::Shape{3, 2},
ov::element::f16,
std::vector<float16>{-1.05, -1.2, -1.0, -1.1, -0.1, 0.4},
CreateConstant<int64_t>({{0, 2}, {1, 2}, {3, 4}}, element::i64),
ov::op::v15::EmbeddingBagPacked::Reduction::MEAN),
EmbeddingBagPackedParams(ov::Shape{5, 2},
ov::element::i64,
std::vector<int64_t>{-1, 2, 3, 4, -5, -6, -7, 8, 9, 10},
ov::Shape{3, 2},
ov::element::i64,
std::vector<int64_t>{-3, -2, -1, -1, 1, 9},
CreateConstant<int64_t>({{0, 2}, {1, 2}, {3, 4}}, element::i64),
ov::op::v15::EmbeddingBagPacked::Reduction::MEAN),
EmbeddingBagPackedParams(ov::Shape{5, 2},
ov::element::u8,
std::vector<uint8_t>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
ov::Shape{3, 2},
ov::element::u8,
std::vector<uint8_t>{3, 4, 4, 5, 8, 9},
CreateConstant<int64_t>({{0, 2}, {1, 2}, {3, 4}}, element::i64),
ov::op::v15::EmbeddingBagPacked::Reduction::MEAN)),
ReferenceEmbeddingBagPackedLayerTest::getTestCaseName);

View File

@ -1790,14 +1790,17 @@ std::shared_ptr<ov::Model> generateEmbeddingBagOffsetsBase(const std::shared_ptr
const auto offsets = std::make_shared<ov::op::v0::Constant>(utils::create_and_fill_tensor(ov::element::i32, ov::Shape{3}));
const auto default_index = std::make_shared<ov::op::v0::Constant>(ov::element::i32, ov::Shape(), std::vector<int32_t>{0});
std::shared_ptr<ov::Node> EmbeddingBagOffsetsSumNode;
std::shared_ptr<ov::Node> EmbeddingBagOffsetsNode;
if (ov::is_type<ov::op::v3::EmbeddingBagOffsetsSum>(node)) {
EmbeddingBagOffsetsSumNode = std::make_shared<ov::op::v3::EmbeddingBagOffsetsSum>(params.at(0), indices, offsets, default_index);
EmbeddingBagOffsetsNode = std::make_shared<ov::op::v3::EmbeddingBagOffsetsSum>(params.at(0), indices, offsets, default_index);
} else if (ov::is_type<ov::op::v15::EmbeddingBagOffsets>(node)) {
const auto reduction = ov::op::v15::EmbeddingBagOffsets::Reduction::MEAN;
EmbeddingBagOffsetsNode = std::make_shared<ov::op::v15::EmbeddingBagOffsets>(params.at(0), indices, offsets, default_index, reduction);
} else {
return nullptr;
}
ov::ResultVector results{std::make_shared<ov::op::v0::Result>(EmbeddingBagOffsetsSumNode)};
ov::ResultVector results{std::make_shared<ov::op::v0::Result>(EmbeddingBagOffsetsNode)};
return std::make_shared<ov::Model>(results, params, "EmbeddingBagOffsetsBaseGraph");
}
@ -1805,14 +1808,17 @@ std::shared_ptr<ov::Model> generateEmbeddingBagPackedBase(const std::shared_ptr<
ov::ParameterVector params{std::make_shared<ov::op::v0::Parameter>(ov::element::f32, ov::Shape{{5, 2}})};
const auto indices = std::make_shared<ov::op::v0::Constant>(utils::create_and_fill_tensor(ov::element::i32, ov::Shape{2, 3}));
std::shared_ptr<ov::Node> EmbeddingBagPackedSumNode;
std::shared_ptr<ov::Node> EmbeddingBagPackedNode;
if (ov::is_type<ov::op::v3::EmbeddingBagPackedSum>(node)) {
EmbeddingBagPackedSumNode = std::make_shared<ov::op::v3::EmbeddingBagPackedSum>(params.at(0), indices);
EmbeddingBagPackedNode = std::make_shared<ov::op::v3::EmbeddingBagPackedSum>(params.at(0), indices);
} else if (ov::is_type<ov::op::v15::EmbeddingBagPacked>(node)) {
const auto reduction = ov::op::v15::EmbeddingBagPacked::Reduction::SUM;
EmbeddingBagPackedNode = std::make_shared<ov::op::v15::EmbeddingBagPacked>(params.at(0), indices, reduction);
} else {
return nullptr;
}
ov::ResultVector results{std::make_shared<ov::op::v0::Result>(EmbeddingBagPackedSumNode)};
ov::ResultVector results{std::make_shared<ov::op::v0::Result>(EmbeddingBagPackedNode)};
return std::make_shared<ov::Model>(results, params, "EmbeddingBagPackedBaseGraph");
}

View File

@ -204,6 +204,7 @@ CompareMap getCompareMap() {
#include "openvino/opsets/opset12_tbl.hpp"
#include "openvino/opsets/opset13_tbl.hpp"
#include "openvino/opsets/opset14_tbl.hpp"
#include "openvino/opsets/opset15_tbl.hpp"
#include "ov_ops/opset_private_tbl.hpp"
#undef _OPENVINO_OP_REG

View File

@ -1124,6 +1124,8 @@ InputsMap getInputMap() {
#include "openvino/opsets/opset11_tbl.hpp"
#include "openvino/opsets/opset12_tbl.hpp"
#include "openvino/opsets/opset13_tbl.hpp"
#include "openvino/opsets/opset14_tbl.hpp"
#include "openvino/opsets/opset15_tbl.hpp"
#include "ov_ops/opset_private_tbl.hpp"
#undef _OPENVINO_OP_REG

View File

@ -0,0 +1,25 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#pragma once
#include "openvino/core/node.hpp"
#include "openvino/op/util/embeddingbag_offsets_base.hpp"
namespace ov {
namespace test {
namespace utils {
std::shared_ptr<ov::Node> make_embedding_bag_offsets(const element::Type& data_type,
const ov::element::Type& indices_type,
const ov::Output<Node>& emb_table_node,
const std::vector<size_t>& indices,
const std::vector<size_t>& offsets,
size_t default_index,
bool with_weights,
bool with_default_index,
ov::op::util::EmbeddingBagOffsetsBase::Reduction reduction);
} // namespace utils
} // namespace test
} // namespace ov

View File

@ -0,0 +1,22 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#pragma once
#include "openvino/core/node.hpp"
#include "openvino/op/util/embeddingbag_packed_base.hpp"
namespace ov {
namespace test {
namespace utils {
std::shared_ptr<ov::Node> make_embedding_bag_packed(const ov::element::Type& data_type,
const ov::element::Type& indices_type,
const ov::Output<Node>& emb_table_node,
const std::vector<std::vector<size_t>>& indices,
bool with_weights,
ov::op::util::EmbeddingBagPackedBase::Reduction reduction);
} // namespace utils
} // namespace test
} // namespace ov

View File

@ -0,0 +1,56 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "common_test_utils/node_builders/embedding_bag_offsets.hpp"
#include "common_test_utils/ov_tensor_utils.hpp"
#include "openvino/op/constant.hpp"
#include "openvino/op/embeddingbag_offsets.hpp"
namespace ov {
namespace test {
namespace utils {
std::shared_ptr<ov::Node> make_embedding_bag_offsets(const element::Type& data_type,
const ov::element::Type& indices_type,
const ov::Output<Node>& emb_table_node,
const std::vector<size_t>& indices,
const std::vector<size_t>& offsets,
size_t default_index,
bool with_weights,
bool with_default_index,
ov::op::util::EmbeddingBagOffsetsBase::Reduction reduction) {
ov::Shape i_shape = {indices.size()};
auto indices_node = std::make_shared<ov::op::v0::Constant>(indices_type, i_shape, indices);
ov::Shape o_shape = {offsets.size()};
auto offsetsNode = std::make_shared<ov::op::v0::Constant>(indices_type, o_shape, offsets);
std::shared_ptr<Node> embBag;
if (with_default_index) {
auto defIdxNode = std::make_shared<ov::op::v0::Constant>(indices_type, ov::Shape{}, default_index);
if (with_weights) {
auto tensor = create_and_fill_tensor(data_type, ov::Shape{indices.size()});
auto weights_node = std::make_shared<ov::op::v0::Constant>(tensor);
embBag = std::make_shared<ov::op::v15::EmbeddingBagOffsets>(emb_table_node,
indices_node,
offsetsNode,
defIdxNode,
weights_node,
reduction);
} else {
embBag = std::make_shared<ov::op::v15::EmbeddingBagOffsets>(emb_table_node,
indices_node,
offsetsNode,
defIdxNode,
reduction);
}
} else {
embBag =
std::make_shared<ov::op::v15::EmbeddingBagOffsets>(emb_table_node, indices_node, offsetsNode, reduction);
}
return embBag;
}
} // namespace utils
} // namespace test
} // namespace ov

View File

@ -0,0 +1,41 @@
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "common_test_utils/node_builders/embedding_bag_packed.hpp"
#include "common_test_utils/ov_tensor_utils.hpp"
#include "openvino/op/constant.hpp"
#include "openvino/op/embeddingbag_packed.hpp"
namespace ov {
namespace test {
namespace utils {
std::shared_ptr<ov::Node> make_embedding_bag_packed(const ov::element::Type& data_type,
const ov::element::Type& indices_type,
const ov::Output<Node>& emb_table_node,
const std::vector<std::vector<size_t>>& indices,
bool with_weights,
ov::op::util::EmbeddingBagPackedBase::Reduction reduction) {
ov::Shape i_shape({indices.size(), indices[0].size()});
size_t i_size = ov::shape_size(i_shape);
std::vector<size_t> i_values(i_size);
for (int i = 0; i < indices.size(); i++)
memcpy(i_values.data() + indices[0].size() * i, indices[i].data(), indices[0].size() * sizeof(size_t));
auto indicesNode = std::make_shared<ov::op::v0::Constant>(indices_type, i_shape, i_values);
std::shared_ptr<Node> embBag;
if (with_weights) {
auto tensor = create_and_fill_tensor(data_type, i_shape);
auto weights_node = std::make_shared<ov::op::v0::Constant>(tensor);
embBag =
std::make_shared<ov::op::v15::EmbeddingBagPacked>(emb_table_node, indicesNode, weights_node, reduction);
} else {
embBag = std::make_shared<ov::op::v15::EmbeddingBagPacked>(emb_table_node, indicesNode, reduction);
}
return embBag;
}
} // namespace utils
} // namespace test
} // namespace ov

View File

@ -11,89 +11,228 @@ from pytorch_layer_test_class import PytorchLayerTest
class TestEmbeddingBag1dOffsets(PytorchLayerTest):
def _prepare_input(self, indicies_dtype, per_sample_weights=False):
import numpy as np
indices = np.array([2, 2, 2, 2, 4, 3, 2, 9]).astype(indicies_dtype)
weights = np.random.randn(10, 10).astype(np.float32)
offsets = np.array([0, 4]).astype(indicies_dtype)
if per_sample_weights:
per_sample_weights = np.random.randn(
*indices.shape).astype(np.float32)
per_sample_weights = np.random.randn(*indices.shape).astype(np.float32)
return (indices, weights, offsets, per_sample_weights)
return (indices, weights, offsets)
def create_model(self, per_sample_weights):
def create_model(self, mode, per_sample_weights):
import torch
import torch.nn.functional as F
class aten_embedding_bag(torch.nn.Module):
def __init__(self, per_sample_weights=False) -> None:
def __init__(self, mode=None, per_sample_weights=False) -> None:
super().__init__()
self.mode = mode
if per_sample_weights:
self.forward = self.forward_offsets_per_sample_weights
def forward(self, indicies, weight, offsets):
return F.embedding_bag(indicies, weight, offsets, mode="sum")
return F.embedding_bag(indicies, weight, offsets, mode=self.mode)
def forward_offsets_per_sample_weights(self, indicies, weight, offsets, per_sample_wights):
return F.embedding_bag(indicies, weight, offsets, mode="sum", per_sample_weights=per_sample_wights)
def forward_offsets_per_sample_weights(
self, indicies, weight, offsets, per_sample_wights
):
return F.embedding_bag(
indicies,
weight,
offsets,
mode=self.mode,
per_sample_weights=per_sample_wights,
)
ref_net = None
return aten_embedding_bag(per_sample_weights), ref_net, "aten::embedding_bag"
return (
aten_embedding_bag(mode, per_sample_weights),
ref_net,
"aten::embedding_bag",
)
@pytest.mark.nightly
@pytest.mark.precommit
@pytest.mark.precommit_fx_backend
@pytest.mark.parametrize("indicies_dtype", ["int", "int32"])
@pytest.mark.parametrize("per_sample_weights", [True, False])
@pytest.mark.xfail(condition=platform.system() == 'Darwin' and platform.machine() == 'arm64',
reason='Ticket - 122715')
def test_embedding_bag(self, ie_device, precision, ir_version, indicies_dtype, per_sample_weights):
self._test(*self.create_model(per_sample_weights), ie_device, precision, ir_version,
kwargs_to_prepare_input={"indicies_dtype": indicies_dtype, "per_sample_weights": per_sample_weights},
trace_model=True, dynamic_shapes=not per_sample_weights and ie_device != "GPU")
@pytest.mark.parametrize(
"mode, per_sample_weights", [("mean", False), ("sum", False), ("sum", True)]
)
@pytest.mark.xfail(
condition=platform.system() == "Darwin" and platform.machine() == "arm64",
reason="Ticket - 122715",
)
def test_embedding_bag(
self, ie_device, precision, ir_version, indicies_dtype, mode, per_sample_weights
):
self._test(
*self.create_model(mode, per_sample_weights),
ie_device,
precision,
ir_version,
kwargs_to_prepare_input={
"indicies_dtype": indicies_dtype,
"per_sample_weights": per_sample_weights,
},
trace_model=True,
dynamic_shapes=not per_sample_weights and ie_device != "GPU"
)
class TestEmbeddingBag2d(PytorchLayerTest):
def _prepare_input(self, indicies_size, indicies_dtype, per_sample_weights):
import numpy as np
indices = np.random.randint(
0, 9, size=indicies_size).astype(indicies_dtype)
indices = np.random.randint(0, 9, size=indicies_size).astype(indicies_dtype)
weights = np.random.randn(10, 10).astype(np.float32)
if per_sample_weights:
per_sample_weights = np.random.randn(
*indices.shape).astype(np.float32)
per_sample_weights = np.random.randn(*indices.shape).astype(np.float32)
return (indices, weights, per_sample_weights)
return (indices, weights)
def create_model(self, per_sample_weights):
def create_model(self, mode, per_sample_weights):
import torch
import torch.nn.functional as F
class aten_embedding_bag(torch.nn.Module):
def __init__(self, per_sample_weights=False) -> None:
def __init__(self, mode=None, per_sample_weights=False) -> None:
super().__init__()
self.mode = mode
if per_sample_weights:
self.forward = self.forward_per_sample_weights
def forward(self, indicies, weight):
return F.embedding_bag(indicies, weight, mode="sum")
return F.embedding_bag(indicies, weight, mode=self.mode)
def forward_per_sample_weights(self, indicies, weight, per_sample_wights):
return F.embedding_bag(indicies, weight, mode="sum", per_sample_weights=per_sample_wights)
return F.embedding_bag(
indicies,
weight,
mode=self.mode,
per_sample_weights=per_sample_wights,
)
ref_net = None
return aten_embedding_bag(per_sample_weights), ref_net, "aten::embedding_bag"
return (
aten_embedding_bag(mode, per_sample_weights),
ref_net,
"aten::embedding_bag",
)
@pytest.mark.nightly
@pytest.mark.precommit
@pytest.mark.precommit_fx_backend
@pytest.mark.parametrize("indicies_size", [[1, 1], [2, 5], [3, 10], [4, 7]])
@pytest.mark.parametrize("indicies_dtype", ["int", "int32"])
@pytest.mark.parametrize("per_sample_weights", [True, False])
@pytest.mark.xfail(condition=platform.system() == 'Darwin' and platform.machine() == 'arm64',
reason='Ticket - 122715')
def test_embedding_bag(self, ie_device, precision, ir_version, indicies_dtype, indicies_size, per_sample_weights):
self._test(*self.create_model(per_sample_weights), ie_device, precision, ir_version,
kwargs_to_prepare_input={"indicies_size": indicies_size, "indicies_dtype": indicies_dtype, "per_sample_weights": per_sample_weights},
trace_model=True, dynamic_shapes=not per_sample_weights and ie_device != "GPU")
@pytest.mark.parametrize(
"mode, per_sample_weights", [("mean", False), ("sum", False), ("sum", True)]
)
@pytest.mark.xfail(
condition=platform.system() == "Darwin" and platform.machine() == "arm64",
reason="Ticket - 122715",
)
def test_embedding_bag(
self,
ie_device,
precision,
ir_version,
indicies_dtype,
indicies_size,
mode,
per_sample_weights,
):
self._test(
*self.create_model(mode, per_sample_weights),
ie_device,
precision,
ir_version,
kwargs_to_prepare_input={
"indicies_size": indicies_size,
"indicies_dtype": indicies_dtype,
"per_sample_weights": per_sample_weights,
},
trace_model=True,
dynamic_shapes=not per_sample_weights and ie_device != "GPU"
)
class TestEmbeddingBagPretrained(PytorchLayerTest):
def _prepare_input(self, indicies_size, indicies_dtype, per_sample_weights):
import numpy as np
indices = np.random.randint(0, 9, size=indicies_size).astype(indicies_dtype)
if per_sample_weights:
per_sample_weights = np.random.randn(*indices.shape).astype(np.float32)
return (indices, per_sample_weights)
return (indices,)
def create_model(self, mode, per_sample_weights):
import torch
import numpy as np
class aten_embedding_bag(torch.nn.Module):
def __init__(self, mode=None, per_sample_weights=False) -> None:
super().__init__()
self.mode = mode
weights = torch.from_numpy(np.random.randn(10, 10).astype(np.float32))
self.embeddings = torch.nn.EmbeddingBag.from_pretrained(
weights, mode=mode
)
if per_sample_weights:
self.forward = self.forward_per_sample_weights
def forward(self, indicies):
return self.embeddings(indicies)
def forward_per_sample_weights(self, indicies, per_sample_wights):
return (
self.embeddings(indicies, per_sample_weights=per_sample_wights),
)
ref_net = None
return (
aten_embedding_bag(mode, per_sample_weights),
ref_net,
"aten::embedding_bag",
)
@pytest.mark.nightly
@pytest.mark.precommit
@pytest.mark.precommit_fx_backend
@pytest.mark.parametrize("indicies_size", [[1, 1], [2, 5], [3, 10], [4, 7]])
@pytest.mark.parametrize("indicies_dtype", ["int", "int32"])
@pytest.mark.parametrize(
"mode, per_sample_weights", [("mean", False), ("sum", False), ("sum", True)]
)
@pytest.mark.xfail(
condition=platform.system() == "Darwin" and platform.machine() == "arm64",
reason="Ticket - 122715",
)
def test_embedding_bag(
self,
ie_device,
precision,
ir_version,
indicies_dtype,
indicies_size,
mode,
per_sample_weights,
):
self._test(
*self.create_model(mode, per_sample_weights),
ie_device,
precision,
ir_version,
kwargs_to_prepare_input={
"indicies_size": indicies_size,
"indicies_dtype": indicies_dtype,
"per_sample_weights": per_sample_weights,
},
trace_model=True,
dynamic_shapes=not per_sample_weights and ie_device != "GPU"
)