[Op][Core] Add ScatterNDUpdate-14 core and reference (#23754)

### Details:
 - *Add core implementation for ScatterNDUpdates-14*
 - *Add reference implementation for ScatterNDUpdates-14*

### Tickets:
 - *111098*
 - *111091*
 - *111093*
This commit is contained in:
Mateusz Mikolajczyk 2024-04-17 12:48:40 +02:00 committed by GitHub
parent 9331eb54da
commit 345a31ce7e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 858 additions and 146 deletions

View File

@ -29,5 +29,55 @@ public:
bool has_evaluate() const override;
};
} // namespace v3
namespace v14 {
/// \brief Add updates to slices from inputs addressed by indices
/// \ingroup ov_ops_cpp_api
class OPENVINO_API ScatterNDUpdate : public util::ScatterNDBase {
public:
OPENVINO_OP("ScatterNDUpdate", "opset14", util::ScatterNDBase);
/// \brief Lists the supported reduction types for this version of the operator.
/// See the specification for the description of how reduction works with ScatterNDUpdate.
enum class Reduction { NONE, SUM, SUB, PROD, MIN, MAX };
ScatterNDUpdate() = default;
/// \param inputs Tensor
/// \param indices Index tensor: Data type must be `element::i32` or `element::i64`
/// \param updates Tensor: Must have same type as inputs
/// \param reduction Reduction: Type of operation to perform on inputs
ScatterNDUpdate(const Output<Node>& inputs,
const Output<Node>& indices,
const Output<Node>& updates,
const Reduction reduction = Reduction::NONE);
std::shared_ptr<Node> clone_with_new_inputs(const OutputVector& new_args) const override;
bool visit_attributes(AttributeVisitor& visitor) override;
bool evaluate(TensorVector& outputs, const TensorVector& inputs) const override;
bool evaluate_lower(TensorVector& output_values) const override;
bool evaluate_upper(TensorVector& output_values) const override;
bool evaluate_symbol(TensorSymbolVector& output_symbols) const override;
bool has_evaluate() const override;
Reduction get_reduction() const;
void set_reduction(const Reduction reduction);
private:
Reduction m_reduction = Reduction::NONE;
};
} // namespace v14
} // namespace op
OPENVINO_API
std::ostream& operator<<(std::ostream& s, const op::v14::ScatterNDUpdate::Reduction& reduction);
template <>
class OPENVINO_API AttributeAdapter<op::v14::ScatterNDUpdate::Reduction>
: public EnumAttributeAdapterBase<op::v14::ScatterNDUpdate::Reduction> {
public:
AttributeAdapter(op::v14::ScatterNDUpdate::Reduction& value)
: EnumAttributeAdapterBase<op::v14::ScatterNDUpdate::Reduction>(value) {}
OPENVINO_RTTI("AttributeAdapter<v14::ScatterNDUpdate::Reduction>");
};
} // namespace ov

View File

@ -87,7 +87,6 @@ _OPENVINO_OP_REG(Reshape, ov::op::v1)
_OPENVINO_OP_REG(Result, ov::op::v0)
_OPENVINO_OP_REG(ReverseSequence, ov::op::v0)
_OPENVINO_OP_REG(ROIPooling, ov::op::v0)
_OPENVINO_OP_REG(ScatterNDUpdate, ov::op::v3)
_OPENVINO_OP_REG(Select, ov::op::v1)
_OPENVINO_OP_REG(Selu, ov::op::v0)
_OPENVINO_OP_REG(Sign, ov::op::v0)
@ -221,3 +220,4 @@ _OPENVINO_OP_REG(FakeConvert, ov::op::v13)
// New operations added in opset14
_OPENVINO_OP_REG(ConvertPromoteTypes, ov::op::v14)
_OPENVINO_OP_REG(Inverse, ov::op::v14)
_OPENVINO_OP_REG(ScatterNDUpdate, ov::op::v14)

View File

@ -8,10 +8,82 @@
#include <numeric>
#include "openvino/core/shape.hpp"
#include "openvino/op/scatter_nd_update.hpp"
#include "openvino/reference/maximum.hpp"
#include "openvino/reference/minimum.hpp"
#include "openvino/reference/multiply.hpp"
#include "openvino/reference/xor.hpp"
#include "utils/span.hpp"
namespace ov {
namespace reference {
using Reduction = ov::op::v14::ScatterNDUpdate::Reduction;
template <typename T>
using reduction_function = T (*)(const T, const T);
namespace func {
// TODO move this functions to other reference implementations to reduce binary size. Binary for
// ScatterElementsUpdate-12 can also be updated. Ticket: CVS-138266
template <class T>
constexpr T add(const T a, const T b) {
return a + b;
}
template <class T>
constexpr T subtract(const T a, const T b) {
return a - b;
}
template <class T>
constexpr T logical_and(const T a, const T b) {
return static_cast<bool>(a) && static_cast<bool>(b);
}
template <class T>
constexpr T logical_or(const T a, const T b) {
return static_cast<bool>(a) || static_cast<bool>(b);
}
} // namespace func
template <typename T,
typename std::enable_if<!std::is_same<typename std::decay<T>::type, char>::value>::type* = nullptr>
reduction_function<T> reduction_functor_for(const Reduction reduction_type) {
using U = typename std::decay<T>::type;
switch (reduction_type) {
case Reduction::MAX:
return func::max<U>;
case Reduction::MIN:
return func::min<U>;
case Reduction::PROD:
return func::multiply<U>;
case Reduction::SUM:
return func::add<U>;
case Reduction::SUB:
return func::subtract<U>;
case Reduction::NONE:
default:
return nullptr;
}
}
template <typename T, typename std::enable_if<std::is_same<typename std::decay<T>::type, char>::value>::type* = nullptr>
reduction_function<T> reduction_functor_for(const Reduction reduction_type) {
using U = typename std::decay<T>::type;
switch (reduction_type) {
case Reduction::MIN:
case Reduction::PROD:
return func::logical_and<U>;
case Reduction::SUM:
case Reduction::MAX:
return func::logical_or<U>;
case Reduction::SUB:
return func::logical_xor<U>;
case Reduction::NONE:
default:
return nullptr;
}
}
template <typename dataType, typename indicesType>
void scatterNdUpdate(const dataType* const inputData,
const indicesType* const indices,
@ -19,7 +91,8 @@ void scatterNdUpdate(const dataType* const inputData,
dataType* const outBuf,
const Shape& dataShape,
const Shape& indicesShape,
const Shape& updatesShape) {
const Shape& updatesShape,
const Reduction reduction_type = Reduction::NONE) {
const auto update_chunk_shape = span(dataShape).drop_front(indicesShape.back());
const auto update_el_number = shape_size(update_chunk_shape);
@ -32,9 +105,8 @@ void scatterNdUpdate(const dataType* const inputData,
};
return padding;
}();
const auto reduction = reduction_functor_for<dataType>(reduction_type);
std::vector<indicesType> indicesCopy(indices, indices + shape_size(indicesShape));
const auto num_of_updates = shape_size(span(indicesShape).drop_back(1));
for (size_t i = 0; i != num_of_updates; ++i) {
const auto indices_coord = indicesCopy.data() + i * indicesShape.back();
@ -52,10 +124,17 @@ void scatterNdUpdate(const dataType* const inputData,
const auto out_index = std::inner_product(begin(coord), end(coord), begin(input_data_dim_pading), uint64_t(0));
const auto update_data = updates + i * update_el_number;
const auto update_mem_size = update_el_number * sizeof(dataType);
OPENVINO_ASSERT(out_index >= 0 && out_index + update_el_number <= shape_size(dataShape),
"Index is out of bounds");
std::memcpy(outBuf + out_index, update_data, update_mem_size);
if (reduction) {
std::transform(outBuf + out_index,
outBuf + out_index + update_el_number,
update_data,
outBuf + out_index,
reduction);
} else {
std::memcpy(outBuf + out_index, update_data, update_el_number * sizeof(dataType));
}
}
}
} // namespace reference

View File

@ -22,7 +22,8 @@ struct Evaluate : public element::NoAction<bool> {
Tensor& output,
const Shape& data_shape,
const Shape& indices_shape,
const Shape& updates_shape) {
const Shape& updates_shape,
const v14::ScatterNDUpdate::Reduction reduction) {
using namespace ov::element;
return IF_TYPE_OF(sctter_nd_eval_idx_type,
OV_PP_ET_LIST(i32, i64),
@ -34,7 +35,8 @@ struct Evaluate : public element::NoAction<bool> {
output.data<DT>(),
data_shape,
indices_shape,
updates_shape);
updates_shape,
reduction);
}
private:
@ -48,31 +50,25 @@ private:
DT* const output,
const Shape& data_shape,
const Shape& indices_shape,
const Shape& updates_shape) {
const Shape& updates_shape,
const v14::ScatterNDUpdate::Reduction reduction) {
reference::scatterNdUpdate(data,
indices.data<IT>(),
updates,
output,
data_shape,
indices_shape,
updates_shape);
updates_shape,
reduction);
return true;
}
};
};
} // namespace scatter_nd_update
namespace v3 {
std::shared_ptr<Node> ScatterNDUpdate::clone_with_new_inputs(const OutputVector& new_args) const {
OV_OP_SCOPE(v3_ScatterNDUpdate_clone_with_new_inputs);
check_new_args_count(this, new_args);
return std::make_shared<ScatterNDUpdate>(new_args.at(util::ScatterNDBase::INPUTS),
new_args.at(util::ScatterNDBase::INDICES),
new_args.at(util::ScatterNDBase::UPDATES));
}
bool ScatterNDUpdate::evaluate(TensorVector& outputs, const TensorVector& inputs) const {
OV_OP_SCOPE(v3_ScatterNDUpdate_evaluate);
namespace {
bool evaluate(const op::util::ScatterNDBase* node,
TensorVector& outputs,
const TensorVector& inputs,
const op::v14::ScatterNDUpdate::Reduction reduction) {
OPENVINO_ASSERT(inputs.size() == 3);
OPENVINO_ASSERT(outputs.size() == 1);
@ -85,8 +81,8 @@ bool ScatterNDUpdate::evaluate(TensorVector& outputs, const TensorVector& inputs
const auto& updates_shape = updates.get_shape();
output.set_shape(data_shape);
using namespace ov::element;
return IF_TYPE_OF_CONVERT_TENSORS(v3_ScatterNDUpdate_evaluate,
this,
return IF_TYPE_OF_CONVERT_TENSORS(scatter_evaluate,
node,
outputs,
inputs,
OV_PP_ET_LIST(boolean, f32, i32, i64, u32, u64),
@ -98,13 +94,11 @@ bool ScatterNDUpdate::evaluate(TensorVector& outputs, const TensorVector& inputs
output,
data_shape,
indices_shape,
updates_shape);
updates_shape,
reduction);
}
bool ScatterNDUpdate::has_evaluate() const {
OV_OP_SCOPE(v3_ScatterNDUpdate_has_evaluate);
switch (get_output_element_type(0)) {
bool has_evaluate(const op::util::ScatterNDBase* node) {
switch (node->get_output_element_type(0)) {
case element::boolean:
case element::f16:
case element::f32:
@ -116,7 +110,7 @@ bool ScatterNDUpdate::has_evaluate() const {
default:
return false;
}
switch (get_input_element_type(1)) {
switch (node->get_input_element_type(1)) {
case element::i32:
case element::i64:
return true;
@ -124,6 +118,27 @@ bool ScatterNDUpdate::has_evaluate() const {
return false;
}
}
} // namespace
} // namespace scatter_nd_update
namespace v3 {
std::shared_ptr<Node> ScatterNDUpdate::clone_with_new_inputs(const OutputVector& new_args) const {
OV_OP_SCOPE(v3_ScatterNDUpdate_clone_with_new_inputs);
check_new_args_count(this, new_args);
return std::make_shared<ScatterNDUpdate>(new_args.at(util::ScatterNDBase::INPUTS),
new_args.at(util::ScatterNDBase::INDICES),
new_args.at(util::ScatterNDBase::UPDATES));
}
bool ScatterNDUpdate::evaluate(TensorVector& outputs, const TensorVector& inputs) const {
OV_OP_SCOPE(v3_ScatterNDUpdate_evaluate);
constexpr auto reduction = op::v14::ScatterNDUpdate::Reduction::NONE;
return scatter_nd_update::evaluate(this, outputs, inputs, reduction);
}
bool ScatterNDUpdate::has_evaluate() const {
OV_OP_SCOPE(v3_ScatterNDUpdate_has_evaluate);
return scatter_nd_update::has_evaluate(this);
}
bool ScatterNDUpdate::evaluate_lower(TensorVector& output_values) const {
OV_OP_SCOPE(v3_ScatterNDUpdate_evaluate_lower);
@ -140,5 +155,75 @@ bool ScatterNDUpdate::evaluate_symbol(TensorSymbolVector& output_symbols) const
return default_symbol_evaluator(this, {0, 2}, output_symbols);
}
} // namespace v3
namespace v14 {
ScatterNDUpdate::ScatterNDUpdate(const Output<Node>& inputs,
const Output<Node>& indices,
const Output<Node>& updates,
const ScatterNDUpdate::Reduction reduction)
: op::util::ScatterNDBase(inputs, indices, updates),
m_reduction{reduction} {
constructor_validate_and_infer_types();
}
std::shared_ptr<Node> ScatterNDUpdate::clone_with_new_inputs(const OutputVector& new_args) const {
OV_OP_SCOPE(v14_ScatterNDUpdate_clone_with_new_inputs);
check_new_args_count(this, new_args);
return std::make_shared<ScatterNDUpdate>(new_args.at(0), new_args.at(1), new_args.at(2), m_reduction);
}
bool ScatterNDUpdate::visit_attributes(AttributeVisitor& visitor) {
OV_OP_SCOPE(v14_ScatterNDUpdate_visit_attributes);
visitor.on_attribute("reduction", m_reduction);
return true;
}
bool ScatterNDUpdate::evaluate(TensorVector& outputs, const TensorVector& inputs) const {
OV_OP_SCOPE(v14_ScatterNDUpdate_evaluate);
return scatter_nd_update::evaluate(this, outputs, inputs, m_reduction);
}
bool ScatterNDUpdate::has_evaluate() const {
OV_OP_SCOPE(v14_ScatterNDUpdate_has_evaluate);
return scatter_nd_update::has_evaluate(this);
}
ScatterNDUpdate::Reduction ScatterNDUpdate::get_reduction() const {
return m_reduction;
}
void ScatterNDUpdate::set_reduction(const ScatterNDUpdate::Reduction reduction) {
m_reduction = reduction;
}
bool ScatterNDUpdate::evaluate_lower(TensorVector& output_values) const {
OV_OP_SCOPE(v14_ScatterNDUpdate_evaluate_lower);
return get_input_tensor(1).has_and_set_bound() && default_lower_bound_evaluator(this, output_values);
}
bool ScatterNDUpdate::evaluate_upper(TensorVector& output_values) const {
OV_OP_SCOPE(v14_ScatterNDUpdate_evaluate_upper);
return get_input_tensor(1).has_and_set_bound() && default_upper_bound_evaluator(this, output_values);
}
bool ScatterNDUpdate::evaluate_symbol(TensorSymbolVector& output_symbols) const {
OV_OP_SCOPE(v14_ScatterNDUpdate_evaluate_symbol);
return default_symbol_evaluator(this, {0, 2}, output_symbols);
}
} // namespace v14
} // namespace op
std::ostream& operator<<(std::ostream& s, const op::v14::ScatterNDUpdate::Reduction& reduction) {
return s << as_string(reduction);
}
template <>
OPENVINO_API EnumNames<op::v14::ScatterNDUpdate::Reduction>& EnumNames<op::v14::ScatterNDUpdate::Reduction>::get() {
static auto enum_names =
EnumNames<op::v14::ScatterNDUpdate::Reduction>("op::v14::ScatterNDUpdate::Reduction",
{{"none", op::v14::ScatterNDUpdate::Reduction::NONE},
{"sum", op::v14::ScatterNDUpdate::Reduction::SUM},
{"sub", op::v14::ScatterNDUpdate::Reduction::SUB},
{"prod", op::v14::ScatterNDUpdate::Reduction::PROD},
{"min", op::v14::ScatterNDUpdate::Reduction::MIN},
{"max", op::v14::ScatterNDUpdate::Reduction::MAX}});
return enum_names;
}
} // namespace ov

View File

@ -5,21 +5,33 @@
#include "openvino/op/scatter_nd_update.hpp"
#include "common_test_utils/type_prop.hpp"
#include "openvino/op/broadcast.hpp"
#include "openvino/op/constant.hpp"
#include "openvino/op/shape_of.hpp"
#include "openvino/opsets/opset10.hpp"
using namespace std;
using namespace ov;
using namespace testing;
TEST(type_prop, scatter_nd_update_v3_fail_indices_element_type) {
template <class T>
class TypePropScatterNDUpdateTest : public TypePropOpTest<T> {
protected:
void SetUp() override {
set_shape_symbols(data_3d_dynamic);
}
PartialShape data_3d_dynamic{{2, 5}, 2, {4, 10}};
};
TYPED_TEST_SUITE_P(TypePropScatterNDUpdateTest);
TYPED_TEST_P(TypePropScatterNDUpdateTest, scatter_nd_update_v3_fail_indices_element_type) {
Shape ref_shape{2, 3, 4};
Shape indices_shape{2, 1};
Shape updates_shape{2, 2, 1, 4};
auto R = make_shared<ov::op::v0::Parameter>(element::f32, ref_shape);
auto I = make_shared<ov::op::v0::Parameter>(element::f16, indices_shape);
auto U = make_shared<ov::op::v0::Parameter>(element::f32, updates_shape);
auto R = std::make_shared<op::v0::Parameter>(element::f32, ref_shape);
auto I = std::make_shared<op::v0::Parameter>(element::f16, indices_shape);
auto U = std::make_shared<op::v0::Parameter>(element::f32, updates_shape);
try {
auto G = make_shared<op::v3::ScatterNDUpdate>(R, I, U);
auto G = this->make_op(R, I, U);
// Should have thrown, so fail if it didn't
FAIL() << "Incorrect indices element type";
} catch (const NodeValidationFailure& error) {
@ -29,16 +41,16 @@ TEST(type_prop, scatter_nd_update_v3_fail_indices_element_type) {
}
}
TEST(type_prop, scatter_nd_update_v3_fail_updates_rank) {
TYPED_TEST_P(TypePropScatterNDUpdateTest, scatter_nd_update_v3_fail_updates_rank) {
Shape ref_shape{3, 3, 3};
Shape indices_shape{1};
Shape updates_shape{3, 3, 3};
Shape out_shape{3, 3, 3};
auto R = make_shared<ov::op::v0::Parameter>(element::f32, ref_shape);
auto I = make_shared<ov::op::v0::Parameter>(element::i32, indices_shape);
auto U = make_shared<ov::op::v0::Parameter>(element::f32, updates_shape);
auto R = std::make_shared<op::v0::Parameter>(element::f32, ref_shape);
auto I = std::make_shared<op::v0::Parameter>(element::i32, indices_shape);
auto U = std::make_shared<op::v0::Parameter>(element::f32, updates_shape);
try {
auto G = make_shared<op::v3::ScatterNDUpdate>(R, I, U);
auto G = this->make_op(R, I, U);
// Should have thrown, so fail if it didn't
FAIL() << "Incorrect updates rank";
} catch (const NodeValidationFailure& error) {
@ -50,16 +62,16 @@ TEST(type_prop, scatter_nd_update_v3_fail_updates_rank) {
}
}
TEST(type_prop, scatter_nd_update_fail_updates_element_type) {
TYPED_TEST_P(TypePropScatterNDUpdateTest, scatter_nd_update_fail_updates_element_type) {
Shape ref_shape{3, 3, 3};
Shape indices_shape{1};
Shape updates_shape{3, 3};
Shape out_shape{3, 3, 3};
auto R = make_shared<ov::op::v0::Parameter>(element::f32, ref_shape);
auto I = make_shared<ov::op::v0::Parameter>(element::i32, indices_shape);
auto U = make_shared<ov::op::v0::Parameter>(element::i32, updates_shape);
auto R = std::make_shared<op::v0::Parameter>(element::f32, ref_shape);
auto I = std::make_shared<op::v0::Parameter>(element::i32, indices_shape);
auto U = std::make_shared<op::v0::Parameter>(element::i32, updates_shape);
try {
auto G = make_shared<op::v3::ScatterNDUpdate>(R, I, U);
auto G = this->make_op(R, I, U);
// Should have thrown, so fail if it didn't
FAIL() << "Created ScatterND op with incorrect updates element type.";
} catch (const NodeValidationFailure& error) {
@ -69,16 +81,16 @@ TEST(type_prop, scatter_nd_update_fail_updates_element_type) {
}
}
TEST(type_prop, scatter_nd_update_fail_updates_shape) {
TYPED_TEST_P(TypePropScatterNDUpdateTest, scatter_nd_update_fail_updates_shape) {
Shape ref_shape{3, 3, 3};
Shape indices_shape{1};
Shape updates_shape{2, 3};
Shape out_shape{3, 3, 3};
auto R = make_shared<ov::op::v0::Parameter>(element::f32, ref_shape);
auto I = make_shared<ov::op::v0::Parameter>(element::i32, indices_shape);
auto U = make_shared<ov::op::v0::Parameter>(element::f32, updates_shape);
auto R = std::make_shared<op::v0::Parameter>(element::f32, ref_shape);
auto I = std::make_shared<op::v0::Parameter>(element::i32, indices_shape);
auto U = std::make_shared<op::v0::Parameter>(element::f32, updates_shape);
try {
auto G = make_shared<op::v3::ScatterNDUpdate>(R, I, U);
auto G = this->make_op(R, I, U);
// Should have thrown, so fail if it didn't
FAIL() << "Incorrect updates shape";
} catch (const NodeValidationFailure& error) {
@ -90,16 +102,16 @@ TEST(type_prop, scatter_nd_update_fail_updates_shape) {
}
}
TEST(type_prop, scatter_nd_update_fail_indices_last_dim) {
TYPED_TEST_P(TypePropScatterNDUpdateTest, scatter_nd_update_fail_indices_last_dim) {
Shape ref_shape{3, 3, 3};
Shape indices_shape{2, 4};
Shape updates_shape{2, 3, 3};
Shape out_shape{3, 3, 3};
auto R = make_shared<ov::op::v0::Parameter>(element::f32, ref_shape);
auto I = make_shared<ov::op::v0::Parameter>(element::i32, indices_shape);
auto U = make_shared<ov::op::v0::Parameter>(element::f32, updates_shape);
auto R = std::make_shared<op::v0::Parameter>(element::f32, ref_shape);
auto I = std::make_shared<op::v0::Parameter>(element::i32, indices_shape);
auto U = std::make_shared<op::v0::Parameter>(element::f32, updates_shape);
try {
auto G = make_shared<op::v3::ScatterNDUpdate>(R, I, U);
auto G = this->make_op(R, I, U);
// Should have thrown, so fail if it didn't
FAIL() << "Incorrect indices innermost dim";
} catch (const NodeValidationFailure& error) {
@ -109,84 +121,73 @@ TEST(type_prop, scatter_nd_update_fail_indices_last_dim) {
}
}
using namespace ov::opset10;
using namespace testing;
TYPED_TEST_P(TypePropScatterNDUpdateTest, data_input_partial_shape_and_symbols_propagation) {
const auto d = std::make_shared<op::v0::Parameter>(element::f32, this->data_3d_dynamic);
const auto i = std::make_shared<op::v0::Parameter>(element::i32, PartialShape{3, 2});
const auto u = std::make_shared<op::v0::Parameter>(element::f32, PartialShape{3, 5});
class TypePropScatterUpdateNDV3Test : public TypePropOpTest<op::v3::ScatterNDUpdate> {
protected:
void SetUp() override {
set_shape_symbols(data_3d_dynamic);
}
PartialShape data_3d_dynamic{{2, 5}, 2, {4, 10}};
};
TEST_F(TypePropScatterUpdateNDV3Test, data_input_partial_shape_and_symbols_propagation) {
const auto d = std::make_shared<Parameter>(element::f32, data_3d_dynamic);
const auto i = std::make_shared<Parameter>(element::i32, PartialShape{3, 2});
const auto u = std::make_shared<Parameter>(element::f32, PartialShape{3, 5});
const auto op = make_op(d, i, u);
const auto op = this->make_op(d, i, u);
EXPECT_EQ(op->get_input_size(), 3);
EXPECT_EQ(op->get_output_size(), 1);
EXPECT_EQ(op->get_output_element_type(0), element::f32);
EXPECT_EQ(op->get_output_partial_shape(0), data_3d_dynamic);
EXPECT_THAT(get_shape_symbols(op->get_output_partial_shape(0)), get_shape_symbols(data_3d_dynamic));
EXPECT_EQ(op->get_output_partial_shape(0), this->data_3d_dynamic);
EXPECT_THAT(get_shape_symbols(op->get_output_partial_shape(0)), get_shape_symbols(this->data_3d_dynamic));
}
TEST_F(TypePropScatterUpdateNDV3Test, indicies_input_is_dynamic) {
const auto d = std::make_shared<Parameter>(element::f64, data_3d_dynamic);
const auto i = std::make_shared<Parameter>(element::i32, PartialShape::dynamic());
const auto u = std::make_shared<Parameter>(element::f64, PartialShape{3, 5});
TYPED_TEST_P(TypePropScatterNDUpdateTest, indicies_input_is_dynamic) {
const auto d = std::make_shared<op::v0::Parameter>(element::f64, this->data_3d_dynamic);
const auto i = std::make_shared<op::v0::Parameter>(element::i32, PartialShape::dynamic());
const auto u = std::make_shared<op::v0::Parameter>(element::f64, PartialShape{3, 5});
const auto op = make_op(d, i, u);
const auto op = this->make_op(d, i, u);
EXPECT_EQ(op->get_output_element_type(0), element::f64);
EXPECT_EQ(op->get_output_partial_shape(0), data_3d_dynamic);
EXPECT_THAT(get_shape_symbols(op->get_output_partial_shape(0)), get_shape_symbols(data_3d_dynamic));
EXPECT_EQ(op->get_output_partial_shape(0), this->data_3d_dynamic);
EXPECT_THAT(get_shape_symbols(op->get_output_partial_shape(0)), get_shape_symbols(this->data_3d_dynamic));
}
TEST_F(TypePropScatterUpdateNDV3Test, updates_input_is_dynamic) {
const auto d = std::make_shared<Parameter>(element::f64, data_3d_dynamic);
const auto i = std::make_shared<Parameter>(element::i32, PartialShape{3, 2});
const auto u = std::make_shared<Parameter>(element::f64, PartialShape::dynamic());
TYPED_TEST_P(TypePropScatterNDUpdateTest, updates_input_is_dynamic) {
const auto d = std::make_shared<op::v0::Parameter>(element::f64, this->data_3d_dynamic);
const auto i = std::make_shared<op::v0::Parameter>(element::i32, PartialShape{3, 2});
const auto u = std::make_shared<op::v0::Parameter>(element::f64, PartialShape::dynamic());
const auto op = make_op(d, i, u);
const auto op = this->make_op(d, i, u);
EXPECT_EQ(op->get_output_element_type(0), element::f64);
EXPECT_EQ(op->get_output_partial_shape(0), data_3d_dynamic);
EXPECT_THAT(get_shape_symbols(op->get_output_partial_shape(0)), get_shape_symbols(data_3d_dynamic));
EXPECT_EQ(op->get_output_partial_shape(0), this->data_3d_dynamic);
EXPECT_THAT(get_shape_symbols(op->get_output_partial_shape(0)), get_shape_symbols(this->data_3d_dynamic));
}
TEST_F(TypePropScatterUpdateNDV3Test, indicies_input_has_interval_dimensions) {
const auto d = std::make_shared<Parameter>(element::i64, data_3d_dynamic);
const auto i = std::make_shared<Parameter>(element::i32, PartialShape{{0, 3}, 1});
const auto u = std::make_shared<Parameter>(element::i64, PartialShape{3, 2, {8, 10}});
TYPED_TEST_P(TypePropScatterNDUpdateTest, indicies_input_has_interval_dimensions) {
const auto d = std::make_shared<op::v0::Parameter>(element::i64, this->data_3d_dynamic);
const auto i = std::make_shared<op::v0::Parameter>(element::i32, PartialShape{{0, 3}, 1});
const auto u = std::make_shared<op::v0::Parameter>(element::i64, PartialShape{3, 2, {8, 10}});
const auto op = make_op(d, i, u);
const auto op = this->make_op(d, i, u);
EXPECT_EQ(op->get_output_element_type(0), element::i64);
EXPECT_EQ(op->get_output_partial_shape(0), data_3d_dynamic);
EXPECT_THAT(get_shape_symbols(op->get_output_partial_shape(0)), get_shape_symbols(data_3d_dynamic));
EXPECT_EQ(op->get_output_partial_shape(0), this->data_3d_dynamic);
EXPECT_THAT(get_shape_symbols(op->get_output_partial_shape(0)), get_shape_symbols(this->data_3d_dynamic));
}
TEST_F(TypePropScatterUpdateNDV3Test, updates_input_is_scalar) {
const auto d = std::make_shared<Parameter>(element::i8, data_3d_dynamic);
const auto i = std::make_shared<Parameter>(element::i32, PartialShape{3});
const auto u = std::make_shared<Parameter>(element::i8, PartialShape{});
TYPED_TEST_P(TypePropScatterNDUpdateTest, updates_input_is_scalar) {
const auto d = std::make_shared<op::v0::Parameter>(element::i8, this->data_3d_dynamic);
const auto i = std::make_shared<op::v0::Parameter>(element::i32, PartialShape{3});
const auto u = std::make_shared<op::v0::Parameter>(element::i8, PartialShape{});
const auto op = make_op(d, i, u);
const auto op = this->make_op(d, i, u);
EXPECT_EQ(op->get_output_element_type(0), element::i8);
EXPECT_EQ(op->get_output_partial_shape(0), data_3d_dynamic);
EXPECT_EQ(op->get_output_partial_shape(0), this->data_3d_dynamic);
}
TEST_F(TypePropScatterUpdateNDV3Test, default_ctor) {
const auto d = std::make_shared<Parameter>(element::i64, PartialShape{2, 3, 5, 1});
const auto i = std::make_shared<Parameter>(element::i32, PartialShape{1, 3});
const auto u = std::make_shared<Parameter>(element::i64, PartialShape{1, 1});
TYPED_TEST_P(TypePropScatterNDUpdateTest, default_ctor) {
const auto d = std::make_shared<op::v0::Parameter>(element::i64, PartialShape{2, 3, 5, 1});
const auto i = std::make_shared<op::v0::Parameter>(element::i32, PartialShape{1, 3});
const auto u = std::make_shared<op::v0::Parameter>(element::i64, PartialShape{1, 1});
const auto op = make_op();
const auto op = this->make_op();
op->set_arguments(OutputVector{d, i, u});
op->validate_and_infer_types();
@ -195,16 +196,17 @@ TEST_F(TypePropScatterUpdateNDV3Test, default_ctor) {
EXPECT_THAT(get_shape_symbols(op->get_output_partial_shape(0)), Each(nullptr));
}
TEST_F(TypePropScatterUpdateNDV3Test, preserve_partial_values_and_symbols_via_evaluates_bounds) {
const auto d = Constant::create(element::i64, Shape{4}, {2, 3, 15, 4});
const auto i = Constant::create(element::i64, Shape{2, 1}, {2, 0});
TYPED_TEST_P(TypePropScatterNDUpdateTest, preserve_partial_values_and_symbols_via_evaluates_bounds) {
const auto d = op::v0::Constant::create(element::i64, Shape{4}, {2, 3, 15, 4});
const auto i = op::v0::Constant::create(element::i64, Shape{2, 1}, {2, 0});
auto u_shape = PartialShape{{10, 20}, {3, 4}};
auto symbols = set_shape_symbols(u_shape);
const auto shape_of_u = std::make_shared<op::v0::ShapeOf>(std::make_shared<Parameter>(element::i64, u_shape));
const auto op = make_op(d, i, shape_of_u);
const auto shape_of_u =
std::make_shared<op::v0::ShapeOf>(std::make_shared<op::v0::Parameter>(element::i64, u_shape));
const auto op = this->make_op(d, i, shape_of_u);
auto param = std::make_shared<ov::op::v0::Parameter>(element::f32, PartialShape{1});
auto param = std::make_shared<op::v0::Parameter>(element::f32, PartialShape{1});
auto bc = std::make_shared<op::v3::Broadcast>(param, op, op::BroadcastType::BIDIRECTIONAL);
EXPECT_EQ(bc->get_output_partial_shape(0), PartialShape({{3, 4}, 3, {10, 20}, 4}));
@ -212,35 +214,98 @@ TEST_F(TypePropScatterUpdateNDV3Test, preserve_partial_values_and_symbols_via_ev
ElementsAre(symbols[1], nullptr, symbols[0], nullptr));
}
TEST_F(TypePropScatterUpdateNDV3Test, indices_dynamic_type) {
const auto d = std::make_shared<Parameter>(element::f32, data_3d_dynamic);
const auto i = std::make_shared<Parameter>(element::dynamic, PartialShape{3, 2});
const auto u = std::make_shared<Parameter>(element::f32, PartialShape{3, 5});
TYPED_TEST_P(TypePropScatterNDUpdateTest, indices_dynamic_type) {
const auto d = std::make_shared<op::v0::Parameter>(element::f32, this->data_3d_dynamic);
const auto i = std::make_shared<op::v0::Parameter>(element::dynamic, PartialShape{3, 2});
const auto u = std::make_shared<op::v0::Parameter>(element::f32, PartialShape{3, 5});
const auto op = make_op(d, i, u);
const auto op = this->make_op(d, i, u);
EXPECT_EQ(op->get_output_element_type(0), element::f32);
EXPECT_EQ(op->get_output_partial_shape(0), data_3d_dynamic);
EXPECT_EQ(op->get_output_partial_shape(0), this->data_3d_dynamic);
}
TEST_F(TypePropScatterUpdateNDV3Test, updates_dynamic_type) {
const auto d = std::make_shared<Parameter>(element::i64, data_3d_dynamic);
const auto i = std::make_shared<Parameter>(element::i32, PartialShape{3, 2});
const auto u = std::make_shared<Parameter>(element::dynamic, PartialShape{3, 5});
TYPED_TEST_P(TypePropScatterNDUpdateTest, updates_dynamic_type) {
const auto d = std::make_shared<op::v0::Parameter>(element::i64, this->data_3d_dynamic);
const auto i = std::make_shared<op::v0::Parameter>(element::i32, PartialShape{3, 2});
const auto u = std::make_shared<op::v0::Parameter>(element::dynamic, PartialShape{3, 5});
const auto op = make_op(d, i, u);
const auto op = this->make_op(d, i, u);
EXPECT_EQ(op->get_output_element_type(0), element::i64);
EXPECT_EQ(op->get_output_partial_shape(0), data_3d_dynamic);
EXPECT_EQ(op->get_output_partial_shape(0), this->data_3d_dynamic);
}
TEST_F(TypePropScatterUpdateNDV3Test, all_dynamic_type) {
const auto d = std::make_shared<Parameter>(element::dynamic, data_3d_dynamic);
const auto i = std::make_shared<Parameter>(element::i64, PartialShape{3, 2});
const auto u = std::make_shared<Parameter>(element::dynamic, PartialShape{3, 5});
TYPED_TEST_P(TypePropScatterNDUpdateTest, all_dynamic_type) {
const auto d = std::make_shared<op::v0::Parameter>(element::dynamic, this->data_3d_dynamic);
const auto i = std::make_shared<op::v0::Parameter>(element::i64, PartialShape{3, 2});
const auto u = std::make_shared<op::v0::Parameter>(element::dynamic, PartialShape{3, 5});
const auto op = make_op(d, i, u);
const auto op = this->make_op(d, i, u);
EXPECT_EQ(op->get_output_element_type(0), element::dynamic);
EXPECT_EQ(op->get_output_partial_shape(0), data_3d_dynamic);
EXPECT_EQ(op->get_output_partial_shape(0), this->data_3d_dynamic);
}
TEST(type_prop, scatter_nd_update_v14_default_attribute) {
const auto d = std::make_shared<op::v0::Parameter>(element::i64, PartialShape{2, 3, 5, 1});
const auto i = std::make_shared<op::v0::Parameter>(element::i32, PartialShape{1, 3});
const auto u = std::make_shared<op::v0::Parameter>(element::i64, PartialShape{1, 1});
const auto op = std::make_shared<op::v14::ScatterNDUpdate>();
op->set_arguments(OutputVector{d, i, u});
op->validate_and_infer_types();
EXPECT_EQ(op->get_output_element_type(0), element::i64);
EXPECT_EQ(op->get_reduction(), op::v14::ScatterNDUpdate::Reduction::NONE);
EXPECT_EQ(op->get_output_partial_shape(0), PartialShape({2, 3, 5, 1}));
EXPECT_THAT(get_shape_symbols(op->get_output_partial_shape(0)), Each(nullptr));
}
TEST(type_prop, scatter_nd_update_v14_attribute_setter_enum) {
const auto d = std::make_shared<op::v0::Parameter>(element::i64, PartialShape{2, 3, 5, 1});
const auto i = std::make_shared<op::v0::Parameter>(element::i32, PartialShape{1, 3});
const auto u = std::make_shared<op::v0::Parameter>(element::i64, PartialShape{1, 1});
const auto op = std::make_shared<op::v14::ScatterNDUpdate>();
op->set_arguments(OutputVector{d, i, u});
op->set_reduction(op::v14::ScatterNDUpdate::Reduction::PROD);
op->validate_and_infer_types();
EXPECT_EQ(op->get_output_element_type(0), element::i64);
EXPECT_EQ(op->get_reduction(), op::v14::ScatterNDUpdate::Reduction::PROD);
EXPECT_EQ(op->get_output_partial_shape(0), PartialShape({2, 3, 5, 1}));
EXPECT_THAT(get_shape_symbols(op->get_output_partial_shape(0)), Each(nullptr));
}
TEST(type_prop, scatter_nd_update_v14_attribute_constructor) {
const auto d = std::make_shared<op::v0::Parameter>(element::i64, PartialShape{2, 3, 5, 1});
const auto i = std::make_shared<op::v0::Parameter>(element::i32, PartialShape{1, 3});
const auto u = std::make_shared<op::v0::Parameter>(element::i64, PartialShape{1, 1});
const auto op = std::make_shared<op::v14::ScatterNDUpdate>(d, i, u, op::v14::ScatterNDUpdate::Reduction::MAX);
EXPECT_EQ(op->get_output_element_type(0), element::i64);
EXPECT_EQ(op->get_reduction(), op::v14::ScatterNDUpdate::Reduction::MAX);
EXPECT_EQ(op->get_output_partial_shape(0), PartialShape({2, 3, 5, 1}));
EXPECT_THAT(get_shape_symbols(op->get_output_partial_shape(0)), Each(nullptr));
}
REGISTER_TYPED_TEST_SUITE_P(TypePropScatterNDUpdateTest,
default_ctor,
indices_dynamic_type,
indicies_input_has_interval_dimensions,
data_input_partial_shape_and_symbols_propagation,
indicies_input_is_dynamic,
preserve_partial_values_and_symbols_via_evaluates_bounds,
scatter_nd_update_fail_indices_last_dim,
scatter_nd_update_fail_updates_element_type,
scatter_nd_update_fail_updates_shape,
scatter_nd_update_v3_fail_indices_element_type,
scatter_nd_update_v3_fail_updates_rank,
updates_dynamic_type,
updates_input_is_dynamic,
updates_input_is_scalar,
all_dynamic_type);
using OpVersions = ::testing::Types<op::v3::ScatterNDUpdate, op::v14::ScatterNDUpdate>;
INSTANTIATE_TYPED_TEST_SUITE_P(type_prop, TypePropScatterNDUpdateTest, OpVersions);

View File

@ -25,3 +25,22 @@ TEST(attributes, scatter_nd_update) {
const auto expected_attr_count = 0;
EXPECT_EQ(builder.get_value_map_size(), expected_attr_count);
}
TEST(attributes, scatter_nd_update_v14) {
NodeBuilder::opset().insert<ov::op::v14::ScatterNDUpdate>();
auto data = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{1000, 256, 10, 15});
auto indices = std::make_shared<ov::op::v0::Parameter>(element::i32, Shape{25, 125, 3});
auto updates = std::make_shared<ov::op::v0::Parameter>(element::f32, Shape{25, 125, 15});
auto scatter = std::make_shared<ov::op::v14::ScatterNDUpdate>(data,
indices,
updates,
op::v14::ScatterNDUpdate::Reduction::PROD);
NodeBuilder builder(scatter, {data, indices, updates});
const auto g_scatter = ov::as_type_ptr<ov::op::v14::ScatterNDUpdate>(builder.create());
const auto expected_attr_count = 1;
EXPECT_EQ(builder.get_value_map_size(), expected_attr_count);
EXPECT_EQ(g_scatter->get_reduction(), scatter->get_reduction());
}

View File

@ -11,6 +11,7 @@
using namespace reference_tests;
using namespace ov;
using Reduction = ov::op::v14::ScatterNDUpdate::Reduction;
namespace {
struct ScatterNDUpdateParams {
@ -23,25 +24,41 @@ struct ScatterNDUpdateParams {
indexTensor(indexTensor),
updateTensor(updateTensor),
expectedTensor(expectedTensor),
reduction(Reduction::NONE),
testcaseName(testcaseName) {}
ScatterNDUpdateParams(const reference_tests::Tensor& dataTensor,
const reference_tests::Tensor& indexTensor,
const reference_tests::Tensor& updateTensor,
const reference_tests::Tensor& expectedTensor,
const Reduction paramReduction,
const std::string& testcaseName)
: dataTensor(dataTensor),
indexTensor(indexTensor),
updateTensor(updateTensor),
expectedTensor(expectedTensor),
reduction{paramReduction},
testcaseName(testcaseName) {}
reference_tests::Tensor dataTensor;
reference_tests::Tensor indexTensor;
reference_tests::Tensor updateTensor;
reference_tests::Tensor expectedTensor;
Reduction reduction;
std::string testcaseName;
};
class ReferenceScatterNDUpdateLayerTest : public testing::TestWithParam<ScatterNDUpdateParams>,
public CommonReferenceTest {
public:
class ReferenceScatterNDUpdateV3LayerTest : public testing::TestWithParam<ScatterNDUpdateParams>,
public CommonReferenceTest {
protected:
void SetUp() override {
auto params = GetParam();
const auto& params = GetParam();
function = CreateFunction(params);
inputData = {params.dataTensor.data};
refOutData = {params.expectedTensor.data};
}
public:
static std::string getTestCaseName(const testing::TestParamInfo<ScatterNDUpdateParams>& obj) {
auto param = obj.param;
std::ostringstream result;
@ -75,7 +92,44 @@ private:
}
};
TEST_P(ReferenceScatterNDUpdateLayerTest, CompareWithRefs) {
class ReferenceScatterNDUpdateV14LayerTest : public testing::TestWithParam<ScatterNDUpdateParams>,
public CommonReferenceTest {
protected:
void SetUp() override {
const auto& params = GetParam();
function = CreateFunction(params);
inputData = {params.dataTensor.data};
refOutData = {params.expectedTensor.data};
}
public:
static std::string getTestCaseName(const testing::TestParamInfo<ScatterNDUpdateParams>& obj) {
const auto& param = obj.param;
std::ostringstream result;
result << ReferenceScatterNDUpdateV3LayerTest::getTestCaseName(obj);
result << "_reduction=" << param.reduction;
return result.str();
}
private:
static std::shared_ptr<Model> CreateFunction(const ScatterNDUpdateParams& params) {
const auto data = std::make_shared<op::v0::Parameter>(params.dataTensor.type, params.dataTensor.shape);
const auto indices = std::make_shared<op::v0::Constant>(params.indexTensor.type,
params.indexTensor.shape,
params.indexTensor.data.data());
const auto updates = std::make_shared<op::v0::Constant>(params.updateTensor.type,
params.updateTensor.shape,
params.updateTensor.data.data());
const auto scatter = std::make_shared<op::v14::ScatterNDUpdate>(data, indices, updates, params.reduction);
return std::make_shared<ov::Model>(NodeVector{scatter}, ParameterVector{data});
}
};
TEST_P(ReferenceScatterNDUpdateV3LayerTest, CompareWithRefs) {
Exec();
}
TEST_P(ReferenceScatterNDUpdateV14LayerTest, CompareWithRefs) {
Exec();
}
@ -87,8 +141,8 @@ std::vector<ScatterNDUpdateParams> generateScatterNDUpdateParams() {
// scatter_nd_update_1x1
ScatterNDUpdateParams(reference_tests::Tensor({1}, IN_ET, std::vector<T>{1}),
reference_tests::Tensor({1}, IU_ET, std::vector<U>{0}),
reference_tests::Tensor({1}, IN_ET, std::vector<T>{20}),
reference_tests::Tensor({1}, IN_ET, std::vector<T>{20}),
reference_tests::Tensor({1}, IN_ET, std::vector<T>{40}),
reference_tests::Tensor({1}, IN_ET, std::vector<T>{40}),
"scatter_nd_update_1x1"),
// scatter_nd_update_2x2_by_1
ScatterNDUpdateParams(reference_tests::Tensor({2, 2}, IN_ET, std::vector<T>{1, 2, 3, 4}),
@ -189,7 +243,335 @@ std::vector<ScatterNDUpdateParams> generateScatterNDUpdateParams() {
return scatterParams;
}
std::vector<ScatterNDUpdateParams> generateScatterNDUpdateCombinedParams() {
template <element::Type_t IN_ET, element::Type_t IU_ET>
std::vector<ScatterNDUpdateParams> generateScatterNDUpdateV14Params() {
using T = typename element_type_traits<IN_ET>::value_type;
using U = typename element_type_traits<IU_ET>::value_type;
std::vector<ScatterNDUpdateParams> scatterParams{
// Duplicated indices tests:
ScatterNDUpdateParams(reference_tests::Tensor({1}, IN_ET, std::vector<T>{1}),
reference_tests::Tensor({2, 1}, IU_ET, std::vector<U>{0, 0}),
reference_tests::Tensor({2}, IN_ET, std::vector<T>{40, 50}),
reference_tests::Tensor({1}, IN_ET, std::vector<T>{50}),
"scatter_nd_update_1x1_duplicated_indices"),
ScatterNDUpdateParams(reference_tests::Tensor({3, 2}, IN_ET, std::vector<T>{1, 1, 1, 1, 1, 1}),
reference_tests::Tensor({2, 2}, IU_ET, std::vector<U>{0, 1, 0, 1}),
reference_tests::Tensor({2}, IN_ET, std::vector<T>{5, 10}),
reference_tests::Tensor({3, 2}, IN_ET, std::vector<T>{1, 10, 1, 1, 1, 1}),
"scatter_nd_update_tf_example_duplicated_indices"),
ScatterNDUpdateParams(
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{8, 12, 1, 5, 3, 19, 2, 4, 13,
7, 6, 25, 5, 12, 11, 23, 17, 2,
18, 23, 16, 17, 11, 22, 0, 10, 20}),
reference_tests::Tensor({2, 1}, IU_ET, std::vector<U>{2, 2}),
reference_tests::Tensor({2, 3, 3},
IN_ET,
std::vector<T>{4, 15, 11, 13, 15, 23, 1, 4, 4, 11, 2, 10, 1, 25, 25, 19, 23, 10}),
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{8, 12, 1, 5, 3, 19, 2, 4, 13,
7, 6, 25, 5, 12, 11, 23, 17, 2,
11, 2, 10, 1, 25, 25, 19, 23, 10}),
"scatter_nd_update_3x3_by_1_duplicated_indices"),
ScatterNDUpdateParams(
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{11, 12, 13, 14, 15, 16, 17, 18, 19,
21, 22, 23, 24, 25, 26, 27, 28, 29,
31, 32, 33, 34, 35, 36, 37, 38, 39}),
reference_tests::Tensor({3, 3}, IU_ET, std::vector<U>{0, 0, 0, 2, -1, 2, -1, 2, -1}),
reference_tests::Tensor({3}, IN_ET, std::vector<T>{91, 99, 100}),
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{91, 12, 13, 14, 15, 16, 17, 18, 19,
21, 22, 23, 24, 25, 26, 27, 28, 29,
31, 32, 33, 34, 35, 36, 37, 38, 100}),
"scatter_nd_update_3x3_by_3_duplicated_indices"),
ScatterNDUpdateParams(reference_tests::Tensor({8}, IN_ET, std::vector<T>{1, 2, 3, 4, 5, 6, 7, 8}),
reference_tests::Tensor({5, 1}, IU_ET, std::vector<U>{4, 3, 1, 7, 1}),
reference_tests::Tensor({5}, IN_ET, std::vector<T>{9, 10, 11, 12, 22}),
reference_tests::Tensor({8}, IN_ET, std::vector<T>{1, 22, 3, 10, 9, 6, 7, 12}),
"scatter_nd_update_1d_from_examples_duplicated_indices"),
ScatterNDUpdateParams(
reference_tests::Tensor({4, 4, 4}, IN_ET, std::vector<T>{1, 2, 3, 4, 5, 6, 7, 8, 8, 7, 6, 5, 4, 3, 2, 1,
1, 2, 3, 4, 5, 6, 7, 8, 8, 7, 6, 5, 4, 3, 2, 1,
8, 7, 6, 5, 4, 3, 2, 1, 1, 2, 3, 4, 5, 6, 7, 8,
8, 7, 6, 5, 4, 3, 2, 1, 1, 2, 3, 4, 5, 6, 7, 8}),
reference_tests::Tensor({3, 1}, IU_ET, std::vector<U>{0, 2, -2}),
reference_tests::Tensor({3, 4, 4}, IN_ET, std::vector<T>{5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7,
8, 8, 8, 8, 1, 1, 1, 1, 2, 2, 2, 2,
3, 3, 3, 3, 4, 4, 4, 4, 10, 10, 10, 10,
11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13}),
reference_tests::Tensor({4, 4, 4}, IN_ET, std::vector<T>{5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8,
8, 8, 8, 1, 2, 3, 4, 5, 6, 7, 8, 8, 7,
6, 5, 4, 3, 2, 1, 10, 10, 10, 10, 11, 11, 11,
11, 12, 12, 12, 12, 13, 13, 13, 13, 8, 7, 6, 5,
4, 3, 2, 1, 1, 2, 3, 4, 5, 6, 7, 8}),
"scatter_nd_update_4x4_shape_from_examples_duplicated_indices"),
ScatterNDUpdateParams(
reference_tests::Tensor({4, 4, 4}, IN_ET, std::vector<T>{1, 2, 3, 4, 5, 6, 7, 8, 8, 7, 6, 5, 4, 3, 2, 1,
1, 2, 3, 4, 5, 6, 7, 8, 8, 7, 6, 5, 4, 3, 2, 1,
8, 7, 6, 5, 4, 3, 2, 1, 1, 2, 3, 4, 5, 6, 7, 8,
8, 7, 6, 5, 4, 3, 2, 1, 1, 2, 3, 4, 5, 6, 7, 8}),
reference_tests::Tensor({3, 2, 2}, IU_ET, std::vector<U>{0, 0, 2, 2, 1, 1, 3, 3, 0, 0, 2, 2}),
reference_tests::Tensor({3, 2, 4}, IN_ET, std::vector<T>{15, 16, 17, 18, 25, 26, 27, 28, 35, 36, 37, 38,
45, 46, 47, 48, 55, 56, 57, 58, 65, 66, 67, 68}),
reference_tests::Tensor({4, 4, 4}, IN_ET, std::vector<T>{55, 56, 57, 58, 5, 6, 7, 8, 8, 7, 6, 5, 4,
3, 2, 1, 1, 2, 3, 4, 35, 36, 37, 38, 8, 7,
6, 5, 4, 3, 2, 1, 8, 7, 6, 5, 4, 3, 2,
1, 65, 66, 67, 68, 5, 6, 7, 8, 8, 7, 6, 5,
4, 3, 2, 1, 1, 2, 3, 4, 45, 46, 47, 48}),
"scatter_nd_update_4x4_v2_duplicated_indices"),
// Reduction tests:
// scatter_nd_update_1x1
ScatterNDUpdateParams(reference_tests::Tensor({1}, IN_ET, std::vector<T>{1}),
reference_tests::Tensor({1}, IU_ET, std::vector<U>{0}),
reference_tests::Tensor({1}, IN_ET, std::vector<T>{40}),
reference_tests::Tensor({1}, IN_ET, std::vector<T>{41}),
Reduction::SUM,
"scatter_nd_update_1x1_SUM"),
ScatterNDUpdateParams(reference_tests::Tensor({1}, IN_ET, std::vector<T>{40}),
reference_tests::Tensor({1}, IU_ET, std::vector<U>{0}),
reference_tests::Tensor({1}, IN_ET, std::vector<T>{40}),
reference_tests::Tensor({1}, IN_ET, std::vector<T>{0}),
Reduction::SUB,
"scatter_nd_update_1x1_SUB"),
ScatterNDUpdateParams(reference_tests::Tensor({1}, IN_ET, std::vector<T>{2}),
reference_tests::Tensor({1}, IU_ET, std::vector<U>{0}),
reference_tests::Tensor({1}, IN_ET, std::vector<T>{40}),
reference_tests::Tensor({1}, IN_ET, std::vector<T>{80}),
Reduction::PROD,
"scatter_nd_update_1x1_PROD"),
ScatterNDUpdateParams(reference_tests::Tensor({1}, IN_ET, std::vector<T>{2}),
reference_tests::Tensor({1}, IU_ET, std::vector<U>{0}),
reference_tests::Tensor({1}, IN_ET, std::vector<T>{40}),
reference_tests::Tensor({1}, IN_ET, std::vector<T>{40}),
Reduction::MAX,
"scatter_nd_update_1x1_MAX"),
ScatterNDUpdateParams(reference_tests::Tensor({1}, IN_ET, std::vector<T>{2}),
reference_tests::Tensor({1}, IU_ET, std::vector<U>{0}),
reference_tests::Tensor({1}, IN_ET, std::vector<T>{40}),
reference_tests::Tensor({1}, IN_ET, std::vector<T>{2}),
Reduction::MIN,
"scatter_nd_update_1x1_MIN"),
// scatter_nd_update_tf_example
ScatterNDUpdateParams(reference_tests::Tensor({3, 2}, IN_ET, std::vector<T>{1, 1, 1, 1, 1, 1}),
reference_tests::Tensor({2, 2}, IU_ET, std::vector<U>{0, 1, 2, 0}),
reference_tests::Tensor({2}, IN_ET, std::vector<T>{5, 10}),
reference_tests::Tensor({3, 2}, IN_ET, std::vector<T>{1, 6, 1, 1, 11, 1}),
Reduction::SUM,
"scatter_nd_update_tf_example"),
ScatterNDUpdateParams(reference_tests::Tensor({3, 2}, IN_ET, std::vector<T>{1, 6, 1, 1, 11, 1}),
reference_tests::Tensor({2, 2}, IU_ET, std::vector<U>{0, 1, 2, 0}),
reference_tests::Tensor({2}, IN_ET, std::vector<T>{5, 10}),
reference_tests::Tensor({3, 2}, IN_ET, std::vector<T>{1, 1, 1, 1, 1, 1}),
Reduction::SUB,
"scatter_nd_update_tf_example"),
ScatterNDUpdateParams(reference_tests::Tensor({3, 2}, IN_ET, std::vector<T>{1, 2, 1, 1, 2, 1}),
reference_tests::Tensor({2, 2}, IU_ET, std::vector<U>{0, 1, 2, 0}),
reference_tests::Tensor({2}, IN_ET, std::vector<T>{5, 10}),
reference_tests::Tensor({3, 2}, IN_ET, std::vector<T>{1, 10, 1, 1, 20, 1}),
Reduction::PROD,
"scatter_nd_update_tf_example"),
ScatterNDUpdateParams(reference_tests::Tensor({3, 2}, IN_ET, std::vector<T>{1, 1, 1, 1, 1, 1}),
reference_tests::Tensor({2, 2}, IU_ET, std::vector<U>{0, 1, 2, 0}),
reference_tests::Tensor({2}, IN_ET, std::vector<T>{5, 10}),
reference_tests::Tensor({3, 2}, IN_ET, std::vector<T>{1, 5, 1, 1, 10, 1}),
Reduction::MAX,
"scatter_nd_update_tf_example"),
ScatterNDUpdateParams(reference_tests::Tensor({3, 2}, IN_ET, std::vector<T>{15, 15, 15, 15, 15, 15}),
reference_tests::Tensor({2, 2}, IU_ET, std::vector<U>{0, 1, 2, 0}),
reference_tests::Tensor({2}, IN_ET, std::vector<T>{5, 10}),
reference_tests::Tensor({3, 2}, IN_ET, std::vector<T>{15, 5, 15, 15, 10, 15}),
Reduction::MIN,
"scatter_nd_update_tf_example"),
// scatter_nd_update_3x3_by_1
ScatterNDUpdateParams(
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{8, 12, 1, 5, 3, 19, 2, 4, 13,
7, 6, 25, 5, 12, 11, 23, 17, 2,
18, 23, 16, 17, 11, 22, 0, 10, 20}),
reference_tests::Tensor({2, 1}, IU_ET, std::vector<U>{0, 2}),
reference_tests::Tensor({2, 3, 3},
IN_ET,
std::vector<T>{4, 15, 11, 13, 15, 23, 1, 4, 4, 11, 2, 10, 1, 25, 25, 19, 23, 10}),
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{12, 27, 12, 18, 18, 42, 3, 8, 17,
7, 6, 25, 5, 12, 11, 23, 17, 2,
29, 25, 26, 18, 36, 47, 19, 33, 30}),
Reduction::SUM,
"scatter_nd_update_3x3_by_1"),
ScatterNDUpdateParams(
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{8, 12, 1, 5, 3, 19, 2, 4, 13,
7, 6, 25, 5, 12, 11, 23, 17, 2,
18, 23, 16, 17, 11, 22, 0, 10, 20}),
reference_tests::Tensor({2, 1}, IU_ET, std::vector<U>{0, 2}),
reference_tests::Tensor({2, 3, 3},
IN_ET,
std::vector<T>{4, 15, 11, 13, 15, 23, 1, 4, 4, 11, 2, 10, 1, 25, 25, 19, 23, 10}),
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{32, 180, 11, 65, 45, 437, 2, 16, 52,
7, 6, 25, 5, 12, 11, 23, 17, 2,
198, 46, 160, 17, 275, 550, 0, 230, 200}),
Reduction::PROD,
"scatter_nd_update_3x3_by_1"),
ScatterNDUpdateParams(
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{8, 12, 1, 5, 3, 19, 2, 4, 13,
7, 6, 25, 5, 12, 11, 23, 17, 2,
18, 23, 16, 17, 11, 22, 0, 10, 20}),
reference_tests::Tensor({2, 1}, IU_ET, std::vector<U>{0, 2}),
reference_tests::Tensor({2, 3, 3},
IN_ET,
std::vector<T>{4, 15, 11, 13, 15, 23, 1, 4, 4, 11, 2, 10, 1, 25, 25, 19, 23, 10}),
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{8, 15, 11, 13, 15, 23, 2, 4, 13,
7, 6, 25, 5, 12, 11, 23, 17, 2,
18, 23, 16, 17, 25, 25, 19, 23, 20}),
Reduction::MAX,
"scatter_nd_update_3x3_by_1"),
ScatterNDUpdateParams(
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{8, 12, 1, 5, 3, 19, 2, 4, 13,
7, 6, 25, 5, 12, 11, 23, 17, 2,
18, 23, 16, 17, 11, 22, 0, 10, 20}),
reference_tests::Tensor({2, 1}, IU_ET, std::vector<U>{0, 2}),
reference_tests::Tensor({2, 3, 3},
IN_ET,
std::vector<T>{4, 15, 11, 13, 15, 23, 1, 4, 4, 11, 2, 10, 1, 25, 25, 19, 23, 10}),
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{4, 12, 1, 5, 3, 19, 1, 4, 4, 7, 6, 25, 5, 12,
11, 23, 17, 2, 11, 2, 10, 1, 11, 22, 0, 10, 10}),
Reduction::MIN,
"scatter_nd_update_3x3_by_1"),
ScatterNDUpdateParams(
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{37, 29, 48, 48, 27, 29, 26, 42, 42,
48, 49, 25, 39, 36, 47, 34, 49, 42,
35, 37, 49, 42, 46, 26, 41, 31, 41}),
reference_tests::Tensor({2, 1}, IU_ET, std::vector<U>{0, 2}),
reference_tests::Tensor(
{2, 3, 3},
IN_ET,
std::vector<T>{18, 13, 13, 19, 13, 1, 25, 24, 15, 6, 12, 17, 12, 10, 8, 18, 16, 19}),
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{19, 16, 35, 29, 14, 28, 1, 18, 27,
48, 49, 25, 39, 36, 47, 34, 49, 42,
29, 25, 32, 30, 36, 18, 23, 15, 22}),
Reduction::SUB,
"scatter_nd_update_3x3_by_1"),
ScatterNDUpdateParams(
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{11, 12, 13, 14, 15, 16, 17, 18, 19,
21, 22, 23, 24, 25, 26, 27, 28, 29,
31, 32, 33, 34, 35, 36, 37, 38, 39}),
reference_tests::Tensor({3, 3}, IU_ET, std::vector<U>{0, 0, 0, 2, -1, 2, -1, 2, -1}),
reference_tests::Tensor({3}, IN_ET, std::vector<T>{2, 4, 6}),
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{13, 12, 13, 14, 15, 16, 17, 18, 19,
21, 22, 23, 24, 25, 26, 27, 28, 29,
31, 32, 33, 34, 35, 36, 37, 38, 49}),
Reduction::SUM,
"scatter_nd_update_3x3_by_3_duplicated_indices"),
ScatterNDUpdateParams(
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{11, 12, 13, 14, 15, 16, 17, 18, 19,
21, 22, 23, 24, 25, 26, 27, 28, 29,
31, 32, 33, 34, 35, 36, 37, 38, 39}),
reference_tests::Tensor({3, 3}, IU_ET, std::vector<U>{0, 0, 0, 2, -1, 2, -1, 2, -1}),
reference_tests::Tensor({3}, IN_ET, std::vector<T>{2, 4, 6}),
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{9, 12, 13, 14, 15, 16, 17, 18, 19,
21, 22, 23, 24, 25, 26, 27, 28, 29,
31, 32, 33, 34, 35, 36, 37, 38, 29}),
Reduction::SUB,
"scatter_nd_update_3x3_by_3_duplicated_indices"),
ScatterNDUpdateParams(
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{11, 12, 13, 14, 15, 16, 17, 18, 19,
21, 22, 23, 24, 25, 26, 27, 28, 29,
31, 32, 33, 34, 35, 36, 37, 38, 39}),
reference_tests::Tensor({3, 3}, IU_ET, std::vector<U>{0, 0, 0, 2, -1, 2, -1, 2, -1}),
reference_tests::Tensor({3}, IN_ET, std::vector<T>{2, 4, 6}),
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{22, 12, 13, 14, 15, 16, 17, 18, 19,
21, 22, 23, 24, 25, 26, 27, 28, 29,
31, 32, 33, 34, 35, 36, 37, 38, 936}),
Reduction::PROD,
"scatter_nd_update_3x3_by_3_duplicated_indices"),
ScatterNDUpdateParams(
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{11, 12, 13, 14, 15, 16, 17, 18, 19,
21, 22, 23, 24, 25, 26, 27, 28, 29,
31, 32, 33, 34, 35, 36, 37, 38, 39}),
reference_tests::Tensor({3, 3}, IU_ET, std::vector<U>{0, 0, 0, 2, -1, 2, -1, 2, -1}),
reference_tests::Tensor({3}, IN_ET, std::vector<T>{2, 4, 6}),
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{11, 12, 13, 14, 15, 16, 17, 18, 19,
21, 22, 23, 24, 25, 26, 27, 28, 29,
31, 32, 33, 34, 35, 36, 37, 38, 39}),
Reduction::MAX,
"scatter_nd_update_3x3_by_3_duplicated_indices"),
ScatterNDUpdateParams(
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{11, 12, 13, 14, 15, 16, 17, 18, 19,
21, 22, 23, 24, 25, 26, 27, 28, 29,
31, 32, 33, 34, 35, 36, 37, 38, 39}),
reference_tests::Tensor({3, 3}, IU_ET, std::vector<U>{0, 0, 0, 2, -1, 2, -1, 2, -1}),
reference_tests::Tensor({3}, IN_ET, std::vector<T>{2, 4, 6}),
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{2, 12, 13, 14, 15, 16, 17, 18, 19,
21, 22, 23, 24, 25, 26, 27, 28, 29,
31, 32, 33, 34, 35, 36, 37, 38, 4}),
Reduction::MIN,
"scatter_nd_update_3x3_by_3_duplicated_indices"),
};
return scatterParams;
}
template <element::Type_t IU_ET>
std::vector<ScatterNDUpdateParams> generateScatterNDUpdateV14ParamsReductionsBoolean() {
const auto IN_ET = element::Type_t::boolean;
using T = typename element_type_traits<IN_ET>::value_type;
using U = typename element_type_traits<IU_ET>::value_type;
std::vector<ScatterNDUpdateParams> scatterParams{
// scatter_nd_update_3x3_by_1
ScatterNDUpdateParams(
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0,
1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0}),
reference_tests::Tensor({2, 1}, IU_ET, std::vector<U>{0, 2}),
reference_tests::Tensor({2, 3, 3},
IN_ET,
std::vector<T>{0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0}),
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0,
1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0}),
Reduction::SUM,
"scatter_nd_update_3x3_by_1"),
ScatterNDUpdateParams(
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0,
1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0}),
reference_tests::Tensor({2, 1}, IU_ET, std::vector<U>{0, 2}),
reference_tests::Tensor({2, 3, 3},
IN_ET,
std::vector<T>{0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0}),
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0,
1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0}),
Reduction::PROD,
"scatter_nd_update_3x3_by_1"),
ScatterNDUpdateParams(
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0,
1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0}),
reference_tests::Tensor({2, 1}, IU_ET, std::vector<U>{0, 2}),
reference_tests::Tensor({2, 3, 3},
IN_ET,
std::vector<T>{0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0}),
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0,
1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0}),
Reduction::MAX,
"scatter_nd_update_3x3_by_1"),
ScatterNDUpdateParams(
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0,
1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0}),
reference_tests::Tensor({2, 1}, IU_ET, std::vector<U>{0, 2}),
reference_tests::Tensor({2, 3, 3},
IN_ET,
std::vector<T>{0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0}),
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0,
1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0}),
Reduction::MIN,
"scatter_nd_update_3x3_by_1"),
ScatterNDUpdateParams(
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0,
1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0}),
reference_tests::Tensor({2, 1}, IU_ET, std::vector<U>{0, 2}),
reference_tests::Tensor({2, 3, 3},
IN_ET,
std::vector<T>{0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0}),
reference_tests::Tensor({3, 3, 3}, IN_ET, std::vector<T>{1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0,
1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0}),
Reduction::SUB,
"scatter_nd_update_3x3_by_1"),
};
return scatterParams;
}
std::vector<ScatterNDUpdateParams> generateScatterNDUpdateV3CombinedParams() {
const std::vector<std::vector<ScatterNDUpdateParams>> scatterTypeParams{
generateScatterNDUpdateParams<element::Type_t::i32, element::Type_t::i32>(),
generateScatterNDUpdateParams<element::Type_t::i64, element::Type_t::i32>(),
@ -214,12 +596,42 @@ std::vector<ScatterNDUpdateParams> generateScatterNDUpdateCombinedParams() {
return combinedParams;
}
INSTANTIATE_TEST_SUITE_P(smoke_ScatterNDUpdate_With_Hardcoded_Refs,
ReferenceScatterNDUpdateLayerTest,
testing::ValuesIn(generateScatterNDUpdateCombinedParams()),
ReferenceScatterNDUpdateLayerTest::getTestCaseName);
std::vector<ScatterNDUpdateParams> generateScatterNDUpdateV14CombinedParams() {
const std::vector<std::vector<ScatterNDUpdateParams>> scatterTypeParams{
generateScatterNDUpdateV14Params<element::Type_t::i32, element::Type_t::i32>(),
generateScatterNDUpdateV14Params<element::Type_t::i64, element::Type_t::i32>(),
generateScatterNDUpdateV14Params<element::Type_t::u32, element::Type_t::i32>(),
generateScatterNDUpdateV14Params<element::Type_t::u64, element::Type_t::i32>(),
generateScatterNDUpdateV14Params<element::Type_t::f16, element::Type_t::i32>(),
generateScatterNDUpdateV14Params<element::Type_t::f32, element::Type_t::i32>(),
generateScatterNDUpdateV14Params<element::Type_t::i32, element::Type_t::i64>(),
generateScatterNDUpdateV14Params<element::Type_t::i64, element::Type_t::i64>(),
generateScatterNDUpdateV14Params<element::Type_t::u32, element::Type_t::i64>(),
generateScatterNDUpdateV14Params<element::Type_t::u64, element::Type_t::i64>(),
generateScatterNDUpdateV14Params<element::Type_t::f16, element::Type_t::i64>(),
generateScatterNDUpdateV14Params<element::Type_t::f32, element::Type_t::i64>(),
generateScatterNDUpdateV14ParamsReductionsBoolean<element::Type_t::i32>(),
generateScatterNDUpdateV14ParamsReductionsBoolean<element::Type_t::i64>(),
};
std::vector<ScatterNDUpdateParams> combinedParams = generateScatterNDUpdateV3CombinedParams();
class ReferenceScatterNDUpdateLayerNegativeTest : public ReferenceScatterNDUpdateLayerTest {};
for (const auto& params : scatterTypeParams) {
combinedParams.insert(combinedParams.end(), params.begin(), params.end());
}
return combinedParams;
}
INSTANTIATE_TEST_SUITE_P(smoke_ScatterNDUpdate_With_Hardcoded_Refs,
ReferenceScatterNDUpdateV3LayerTest,
testing::ValuesIn(generateScatterNDUpdateV3CombinedParams()),
ReferenceScatterNDUpdateV3LayerTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(smoke_ScatterNDUpdate_With_Hardcoded_Refs,
ReferenceScatterNDUpdateV14LayerTest,
testing::ValuesIn(generateScatterNDUpdateV14CombinedParams()),
ReferenceScatterNDUpdateV14LayerTest::getTestCaseName);
class ReferenceScatterNDUpdateLayerNegativeTest : public ReferenceScatterNDUpdateV3LayerTest {};
TEST_P(ReferenceScatterNDUpdateLayerNegativeTest, CompareWithRefsNegative) {
LoadNetwork();

View File

@ -1426,6 +1426,8 @@ std::shared_ptr<ov::Model> generateScatterNDBase(const std::shared_ptr<ov::op::O
std::shared_ptr<ov::Node> scatterNode;
if (ov::is_type<ov::op::v3::ScatterNDUpdate>(node)) {
scatterNode = std::make_shared<ov::op::v3::ScatterNDUpdate>(data, indices, updates);
} else if (ov::is_type<ov::op::v14::ScatterNDUpdate>(node)) {
scatterNode = std::make_shared<ov::op::v14::ScatterNDUpdate>(data, indices, updates, ov::op::v14::ScatterNDUpdate::Reduction::SUM);
} else {
return nullptr;
}