diff --git a/docs/template_plugin/tests/functional/op_reference/scatter_update.cpp b/docs/template_plugin/tests/functional/op_reference/scatter_update.cpp new file mode 100644 index 00000000000000..9cf8bfa6940aaf --- /dev/null +++ b/docs/template_plugin/tests/functional/op_reference/scatter_update.cpp @@ -0,0 +1,1007 @@ +// Copyright (C) 2018-2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include +#include +#include +#include +#include + +#include "base_reference_test.hpp" +#include "ngraph_functions/builders.hpp" + +using namespace ngraph; +using namespace InferenceEngine; +using namespace reference_tests; + +namespace reference_tests { + +namespace { + +// ---------------------- V3 ------------------------------ + +struct ScatterUpdate3Params { + Tensor data; + Tensor indices; + Tensor updates; + Tensor axis; + Tensor expected; +}; + +struct Builder : ParamsBuilder { + REFERENCE_TESTS_ADD_SET_PARAM(Builder, data); + REFERENCE_TESTS_ADD_SET_PARAM(Builder, indices); + REFERENCE_TESTS_ADD_SET_PARAM(Builder, updates); + REFERENCE_TESTS_ADD_SET_PARAM(Builder, axis); + REFERENCE_TESTS_ADD_SET_PARAM(Builder, expected); +}; + +class ReferenceScatterUpdate6LayerTest : public testing::TestWithParam, public CommonReferenceTest { +public: + void SetUp() override { + auto params = GetParam(); + function = CreateFunction(params); + inputData = {params.data.data, params.indices.data, params.updates.data, params.axis.data}; + refOutData = {params.expected.data}; + } + + static std::string getTestCaseName(const testing::TestParamInfo& obj) { + const auto& param = obj.param; + std::ostringstream result; + result << "D_shape=" << param.data.shape << "_"; + result << "I_shape=" << param.indices.shape << "_"; + result << "U_shape=" << param.updates.shape << "_"; + result << "A_shape=" << param.axis.shape << "_"; + result << "dType=" << param.data.type << "_"; + result << "iType=" << param.indices.type << "_"; + result << "uType=" << param.updates.type << "_"; + result << "aType=" << param.axis.type << "_"; + result << "oType=" << param.expected.type; + return result.str(); + } + +private: + static std::shared_ptr CreateFunction(const ScatterUpdate3Params& params) { + const auto data_shape = params.data.shape; + const auto indices_shape = params.indices.shape; + const auto updates_shape = params.updates.shape; + const auto axis_shape = params.axis.shape; + const auto numeric_type = params.data.type; + const auto indices_type = params.indices.type; + const auto axis_type = params.axis.type; + + const auto data = std::make_shared(numeric_type, data_shape); + const auto indices = std::make_shared(indices_type, indices_shape); + const auto updates = std::make_shared(numeric_type, updates_shape); + const auto axis = std::make_shared(axis_type, axis_shape); + const auto scatter_update = std::make_shared(data, indices, updates, axis); + return std::make_shared(ngraph::NodeVector {scatter_update}, ngraph::ParameterVector {data, indices, updates, axis}); + } +}; + +TEST_P(ReferenceScatterUpdate6LayerTest, ScatterUpdateWithHardcodedRefs) { + Exec(); +} + +template +std::vector generateScatterUpdate3Params(const element::Type& numeric_type, const element::Type& integer_type) { + using N = typename element_type_traits::value_type; + using I = typename element_type_traits::value_type; + std::vector ScatterUpdateParams { + Builder {} + .data({{3, 2, 2, 3}, numeric_type, std::vector { + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0}}) + .indices({{2, 1}, integer_type, std::vector {0, 1}}) + .updates({{3, 3, 2, 2, 2}, numeric_type, std::vector { + 1, 2, + 3, 4, + 5, 6, + 7, 8, + 9, 10, + 11, 12, + 13, 14, + 15, 16, + 17, 18, + 19, 20, + 21, 22, + 23, 24, + 25, 26, + 27, 28, + 29, 30, + 31, 32, + 33, 34, + 35, 36, + 37, 38, + 39, 40, + 41, 42, + 43, 44, + 45, 46, + 47, 48, + 49, 50, + 51, 52, + 53, 54, + 55, 56, + 57, 58, + 59, 60, + 61, 62, + 63, 64, + 65, 66, + 67, 68, + 69, 70, + 71, 72}}) + .axis({{1}, integer_type, std::vector {2}}) + .expected({{3, 2, 2, 3}, numeric_type, std::vector { + 1, 2, 9, + 3, 4, 11, + 10, 17, 18, + 12, 19, 20, + 25, 26, 33, + 27, 28, 35, + 34, 41, 42, + 36, 43, 44, + 49, 50, 57, + 51, 52, 59, + 58, 65, 66, + 60, 67, 68}}), + Builder {} + .data({{3, 3}, numeric_type, std::vector {0, 0, 0, + 0, 0, 0, + 0, 0, 0}}) + .indices({{2}, integer_type, std::vector {1, 2}}) + .updates({{3, 2}, numeric_type, std::vector {1, 1, + 1, 2, + 2, 2}}) + .axis({{1}, integer_type, std::vector {1}}) + .expected({{3, 3}, numeric_type, std::vector {0, 1, 1, + 0, 1, 2, + 0, 2, 2}}), + Builder {} + .data({{3, 3}, numeric_type, std::vector {0, 0, 0, + 0, 0, 0, + 0, 0, 0}}) + .indices({{2}, integer_type, std::vector {1, 2}}) + .updates({{2, 3}, numeric_type, std::vector {1, 1, 1, + 2, 2, 2}}) + .axis({{1}, integer_type, std::vector {0}}) + .expected({{3, 3}, numeric_type, std::vector {0, 0, 0, + 1, 1, 1, + 2, 2, 2}}), + Builder {} + .data({{3, 4}, numeric_type, std::vector {0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0}}) + .indices({{2}, integer_type, std::vector {0, 2}}) + .updates({{3, 4}, numeric_type, std::vector {1, 2, 3, 7, + 4, 5, 6, 8, + 7, 8, 9, 10}}) + .axis({{1}, integer_type, std::vector {0}}) + .expected({{3, 4}, numeric_type, std::vector {1, 2, 3, 7, + 0, 0, 0, 0, + 4, 5, 6, 8}}), + Builder {} + .data({{3, 3}, numeric_type, std::vector {0, 0, 0, + 0, 0, 0, + 0, 0, 0}}) + .indices({{2}, integer_type, std::vector {0, 2}}) + .updates({{3, 5}, numeric_type, std::vector {1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15}}) + .axis({{1}, integer_type, std::vector {1}}) + .expected({{3, 3}, numeric_type, std::vector {1, 0, 2, + 6, 0, 7, + 11, 0, 12}}), + Builder {} + .data({{3, 3}, numeric_type, std::vector {0, 0, 0, + 0, 0, 0, + 0, 0, 0}}) + .indices({{1, 2}, integer_type, std::vector {1, 2}}) + .updates({{1, 2, 3}, numeric_type, std::vector {1, 2, 3, + 4, 5, 6}}) + .axis({{1}, integer_type, std::vector {0}}) + .expected({{3, 3}, numeric_type, std::vector {0, 0, 0, + 1, 2, 3, + 4, 5, 6}}), + Builder {} + .data({{3, 3}, numeric_type, std::vector {0, 0, 0, + 0, 0, 0, + 0, 0, 0}}) + .indices({{1, 2}, integer_type, std::vector {1, 2}}) + .updates({{3, 1, 2}, numeric_type, std::vector {1, 2, + 3, 4, + 5, 6}}) + .axis({{1}, integer_type, std::vector {1}}) + .expected({{3, 3}, numeric_type, std::vector {0, 1, 2, + 0, 3, 4, + 0, 5, 6}}), + Builder {} + .data({{3, 3}, numeric_type, std::vector {0, 0, 0, + 0, 0, 0, + 0, 0, 0}}) + .indices({{1, 2}, integer_type, std::vector {1, 2}}) + .updates({{4, 4, 4}, numeric_type, std::vector {1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16, + 17, 18, 19, 20, + 21, 22, 23, 24, + 25, 26, 27, 28, + 29, 30, 31, 32, + 33, 34, 35, 36, + 37, 38, 39, 40, + 41, 42, 43, 44, + 45, 46, 47, 48, + 49, 50, 51, 52, + 53, 54, 55, 56, + 57, 58, 59, 60, + 61, 62, 63, 64}}) + .axis({{1}, integer_type, std::vector {1}}) + .expected({{3, 3}, numeric_type, std::vector {0, 1, 2, + 0, 17, 18, + 0, 33, 34}}), + Builder {} + .data({{3, 3}, numeric_type, std::vector {0, 0, 0, + 0, 0, 0, + 0, 0, 0}}) + .indices({{1, 3}, integer_type, std::vector {0, 1, 2}}) + .updates({{4, 4, 4}, numeric_type, std::vector {1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16, + 17, 18, 19, 20, + 21, 22, 23, 24, + 25, 26, 27, 28, + 29, 30, 31, 32, + 33, 34, 35, 36, + 37, 38, 39, 40, + 41, 42, 43, 44, + 45, 46, 47, 48, + 49, 50, 51, 52, + 53, 54, 55, 56, + 57, 58, 59, 60, + 61, 62, 63, 64}}) + .axis({{1}, integer_type, std::vector {1}}) + .expected({{3, 3}, numeric_type, std::vector {1, 2, 3, + 17, 18, 19, + 33, 34, 35}}), + Builder {} + .data({{3, 3}, numeric_type, std::vector {0, 0, 0, + 0, 0, 0, + 0, 0, 0}}) + .indices({{1, 1}, integer_type, std::vector {2}}) + .updates({{2, 2, 2}, numeric_type, std::vector {1, 2, + 3, 4, + 5, 6, + 7, 8}}) + .axis({{1}, integer_type, std::vector {1}}) + .expected({{3, 3}, numeric_type, std::vector {0, 0, 1, + 0, 0, 5, + 0, 0, 0}}), + Builder {} + .data({{3, 4}, numeric_type, std::vector {0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0}}) + .indices({{1, 4}, integer_type, std::vector {0, 1, 2, 3}}) + .updates({{2, 2, 2}, numeric_type, std::vector {1, 2, + 3, 4, + 5, 6, + 7, 8}}) + .axis({{1}, integer_type, std::vector {1}}) + .expected({{3, 4}, numeric_type, std::vector {1, 2, 3, 4, + 5, 6, 7, 8, + 0, 0, 0, 0}}), + Builder {} + .data({{3, 3}, numeric_type, std::vector {0, 0, 0, + 0, 0, 0, + 0, 0, 0}}) + .indices({{1, 3}, integer_type, std::vector {0, 1, 2}}) + .updates({{2, 2, 2}, numeric_type, std::vector {1, 2, + 3, 4, + 5, 6, + 7, 8}}) + .axis({{1}, integer_type, std::vector {0}}) + .expected({{3, 3}, numeric_type, std::vector {1, 2, 0, + 3, 4, 0, + 5, 6, 0}}), + Builder {} + .data({{3, 3}, numeric_type, std::vector {0, 0, 0, + 0, 0, 0, + 0, 0, 0}}) + .indices({{1, 3}, integer_type, std::vector {0, 1, 2}}) + .updates({{2, 2, 1}, numeric_type, std::vector {1, 2, + 3, 4}}) + .axis({{1}, integer_type, std::vector {0}}) + .expected({{3, 3}, numeric_type, std::vector {1, 0, 0, + 2, 0, 0, + 3, 0, 0}}), + Builder {} + .data({{3, 3}, numeric_type, std::vector {0, 0, 0, + 0, 0, 0, + 0, 0, 0}}) + .indices({{1, 3}, integer_type, std::vector {0, 1, 2}}) + .updates({{1, 1, 1}, numeric_type, std::vector {1}}) + .axis({{1}, integer_type, std::vector {0}}) + .expected({{3, 3}, numeric_type, std::vector {1, 0, 0, + 0, 0, 0, + 0, 0, 0}}), + Builder {} + .data({{2, 2}, numeric_type, std::vector {0, 0, + 0, 0}}) + .indices({{2, 1}, integer_type, std::vector {0, 1}}) + .updates({{2, 2, 2}, numeric_type, std::vector {1, 2, + 3, 4, + 5, 6, + 7, 8}}) + .axis({{1}, integer_type, std::vector {0}}) + .expected({{2, 2}, numeric_type, std::vector {1, 2, + 3, 4}}), + Builder {} + .data({{4, 4}, numeric_type, std::vector {0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0}}) + .indices({{4, 1}, integer_type, std::vector {0, 1, 2, 3}}) + .updates({{2, 2, 2}, numeric_type, std::vector {1, 2, + 3, 4, + 5, 6, + 7, 8}}) + .axis({{1}, integer_type, std::vector {0}}) + .expected({{4, 4}, numeric_type, std::vector {1, 2, 0, 0, + 3, 4, 0, 0, + 5, 6, 0, 0, + 7, 8, 0, 0}}), + Builder {} + .data({{2, 3, 4, 2}, numeric_type, std::vector {0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0}}) + .indices({{3, 1}, integer_type, std::vector {0, 1, 2}}) + .updates({{3, 2, 3, 3, 2}, numeric_type, std::vector {1, 2, + 3, 4, + 5, 6, + 7, 8, + 9, 10, + 11, 12, + 13, 14, + 15, 16, + 17, 18, + 19, 20, + 21, 22, + 23, 24, + 25, 26, + 27, 28, + 29, 30, + 31, 32, + 33, 34, + 35, 36, + 37, 38, + 39, 40, + 41, 42, + 43, 44, + 45, 46, + 47, 48, + 49, 50, + 51, 52, + 53, 54, + 55, 56, + 57, 58, + 59, 60, + 61, 62, + 63, 64, + 65, 66, + 67, 68, + 69, 70, + 71, 72, + 73, 74, + 75, 76, + 77, 78, + 79, 80, + 81, 82, + 83, 84, + 85, 86, + 87, 88, + 89, 90, + 91, 92, + 93, 94, + 95, 96, + 97, 98, + 99, 100, + 101, 102, + 103, 104, + 105, 106, + 107, 108}}) + .axis({{1}, integer_type, std::vector {2}}) + .expected({{2, 3, 4, 2}, numeric_type, std::vector { + 1, 2, + 3, 4, + 5, 6, + 0, 0, + 19, 20, + 21, 22, + 23, 24, + 0, 0, + 37, 38, + 39, 40, + 41, 42, + 0, 0, + 55, 56, + 57, 58, + 59, 60, + 0, 0, + 73, 74, + 75, 76, + 77, 78, + 0, 0, + 91, 92, + 93, 94, + 95, 96, + 0, 0}}), + Builder {} + .data({{1, 3, 2, 2}, numeric_type, std::vector {0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0}}) + .indices({{1, 3}, integer_type, std::vector {2, 0, 1}}) + .updates({{1, 3, 2, 2, 2}, numeric_type, std::vector { + 1, 2, + 3, 4, + 5, 6, + 7, 8, + 9, 10, + 11, 12, + 13, 14, + 15, 16, + 17, 18, + 19, 20, + 21, 22, + 23, 24}}) + .axis({{1}, integer_type, std::vector {1}}) + .expected({{1, 3, 2, 2}, numeric_type, std::vector { + 5, 6, + 7, 8, + 9, 10, + 11, 12, + 1, 2, + 3, 4}}), + Builder {} + .data({{2, 2, 2}, numeric_type, std::vector {0, 0, + 0, 0, + 0, 0, + 0, 0}}) + .indices({{1, 2}, integer_type, std::vector {0, 1}}) + .updates({{2, 2, 3, 2}, numeric_type, std::vector {1, 2, + 3, 4, + 5, 6, + 7, 8, + 9, 10, + 11, 12, + 13, 14, + 15, 16, + 17, 18, + 19, 20, + 21, 22, + 23, 24}}) + .axis({{1}, integer_type, std::vector {1}}) + .expected({{2, 2, 2}, numeric_type, std::vector {1, 2, + 3, 4, + 13, 14, + 15, 16}}), + Builder {} + .data({{2, 2, 4}, numeric_type, std::vector {0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0}}) + .indices({{1, 2, 1}, integer_type, std::vector {0, 1}}) + .updates({{2, 2, 3, 2, 1}, numeric_type, std::vector {1, 2, + 3, 4, + 5, 6, + 7, 8, + 9, 10, + 11, 12, + 13, 14, + 15, 16, + 17, 18, + 19, 20, + 21, 22, + 23, 24}}) + .axis({{1}, integer_type, std::vector {1}}) + .expected({{2, 2, 2}, numeric_type, std::vector {1, 13, 0, 0, + 2, 14, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0}}), + Builder {} + .data({{2, 4, 2}, numeric_type, std::vector {0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0}}) + .indices({{1, 2, 1}, integer_type, std::vector {0, 1}}) + .updates({{2, 2, 3, 2, 1}, numeric_type, std::vector {1, 2, + 3, 4, + 5, 6, + 7, 8, + 9, 10, + 11, 12, + 13, 14, + 15, 16, + 17, 18, + 19, 20, + 21, 22, + 23, 24}}) + .axis({{1}, integer_type, std::vector {1}}) + .expected({{2, 4, 2}, numeric_type, std::vector {1, 13, + 2, 14, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0}}), + Builder {} + .data({{2, 2, 2}, numeric_type, std::vector {0, 0, + 0, 0, + 0, 0, + 0, 0}}) + .indices({{2, 1}, integer_type, std::vector {1, 0}}) + .updates({{2, 2, 3, 2}, numeric_type, std::vector {1, 2, + 3, 4, + 5, 6, + 7, 8, + 9, 10, + 11, 12, + 13, 14, + 15, 16, + 17, 18, + 19, 20, + 21, 22, + 23, 24}}) + .axis({{1}, integer_type, std::vector {2}}) + .expected({{2, 2, 2}, numeric_type, std::vector { + 2, 1, + 8, 7, + // + 14, 13, + 20, 19}}), +Builder {} + .data({{2, 2, 4}, numeric_type, std::vector {0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0}}) + .indices({{1, 2, 1}, integer_type, std::vector {0, 1}}) + .updates({{2, 2, 3, 1, 2}, numeric_type, std::vector {1, 2, + 3, 4, + 5, 6, + 7, 8, + 9, 10, + 11, 12, + 13, 14, + 15, 16, + 17, 18, + 19, 20, + 21, 22, + 23, 24}}) + .axis({{1}, integer_type, std::vector {1}}) + .expected({{2, 2, 4}, numeric_type, std::vector {1, 2, 13, 14, + 3, 4, 15, 16, + 0, 0, 0, 0, + 0, 0, 0, 0}}), + + Builder {} + .data({{3, 2, 2, 2}, numeric_type, std::vector {0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0}}) + .indices({{2}, integer_type, std::vector {0, 1}}) + .updates({{2, 2, 2, 2}, numeric_type, std::vector {1, 2, + 3, 4, + 5, 6, + 7, 8, + 9, 10, + 11, 12, + 13, 14, + 15, 16}}) + .axis({{1}, integer_type, std::vector {3}}) + .expected({{3, 2, 2, 2}, numeric_type, std::vector { + 1, 2, + 3, 4, + 5, 6, + 7, 8, + 9, 10, + 11, 12, + 13, 14, + 15, 16, + 0, 0, + 0, 0, + 0, 0, + 0, 0}}), + Builder {} + .data({{5, 2, 2, 2}, numeric_type, std::vector {0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0}}) + .indices({{2}, integer_type, std::vector {0, 1}}) + .updates({{2, 2, 2, 2}, numeric_type, std::vector {1, 2, + 3, 4, + 5, 6, + 7, 8, + 9, 10, + 11, 12, + 13, 14, + 15, 16}}) + .axis({{1}, integer_type, std::vector {2}}) + .expected({{5, 2, 2, 2}, numeric_type, std::vector { + 1, 2, + 3, 4, + 5, 6, + 7, 8, + 9, 10, + 11, 12, + 13, 14, + 15, 16, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0}}), +Builder {} + .data({{5, 2, 2, 2}, numeric_type, std::vector {0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0}}) + .indices({{2, 1}, integer_type, std::vector {0, 1}}) + .updates({{2, 2, 2, 2, 2}, numeric_type, std::vector {1, 2, + 3, 4, + 5, 6, + 7, 8, + 9, 10, + 11, 12, + 13, 14, + 15, 16, + 17, 18, + 19, 20, + 21, 22, + 23, 24, + 25, 26, + 27, 28, + 29, 30, + 31, 32}}) + .axis({{1}, integer_type, std::vector {2}}) + .expected({{5, 2, 2, 2}, numeric_type, std::vector { + 1, 2, + 3, 4, + 9, 10, + 11, 12, + 17, 18, + 19, 20, + 25, 26, + 27, 28, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0}})}; + return ScatterUpdateParams; +} + +template +std::vector generateScatterUpdate3ParamsNegativeAxis(const element::Type& numeric_type, const element::Type& integer_type) { + using N = typename element_type_traits::value_type; + using I = typename element_type_traits::value_type; + std::vector ScatterUpdateParams { + Builder {} + .data({{2, 2, 3}, numeric_type, std::vector {0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0}}) + .indices({{1, 2, 1}, integer_type, std::vector {0, 1}}) + .updates({{2, 2, 3, 1, 2}, numeric_type, std::vector {1, 2, + 3, 4, + 5, 6, + 7, 8, + 9, 10, + 11, 12, + 13, 14, + 15, 16, + 17, 18, + 19, 20, + 21, 22, + 23, 24}}) + .axis({{1}, integer_type, std::vector {-2}}) + .expected({{2, 2, 3}, numeric_type, std::vector {1, 2, 13, + 3, 4, 15, + 14, 0, 0, + 16, 0, 0}}), + Builder {} + .data({{2, 2, 2}, numeric_type, std::vector {0, 0, + 0, 0, + 0, 0, + 0, 0}}) + .indices({{1, 2, 1}, integer_type, std::vector {0, 1}}) + .updates({{2, 2, 3, 1, 2}, numeric_type, std::vector {1, 2, + 3, 4, + 5, 6, + 7, 8, + 9, 10, + 11, 12, + 13, 14, + 15, 16, + 17, 18, + 19, 20, + 21, 22, + 23, 24}}) + .axis({{1}, integer_type, std::vector {-1}}) + .expected({{2, 2, 2}, numeric_type, std::vector {1, 2, + 7, 8, + 13, 14, + 19, 20}}), + Builder {} + .data({{4, 2, 2, 2}, numeric_type, std::vector {0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0}}) + .indices({{2}, integer_type, std::vector {0, 1}}) + .updates({{2, 2, 2, 2}, numeric_type, std::vector {1, 2, + 3, 4, + 5, 6, + 7, 8, + 9, 10, + 11, 12, + 13, 14, + 15, 16}}) + .axis({{1}, integer_type, std::vector {-3}}) + .expected({{4, 2, 2, 2}, numeric_type, std::vector { + 1, 2, + 3, 4, + 5, 6, + 7, 8, + 9, 10, + 11, 12, + 13, 14, + 15, 16, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0, + 0, 0}})}; + return ScatterUpdateParams; +} + +std::vector generateScatterUpdateCombinedParams() { + const std::vector> ScatterUpdateTypeParams { + // f32 + generateScatterUpdate3Params(element::f32, element::i16), + generateScatterUpdate3Params(element::f32, element::i32), + generateScatterUpdate3Params(element::f32, element::i64), + generateScatterUpdate3Params(element::f32, element::u32), + generateScatterUpdate3Params(element::f32, element::u64), + + // f16 + generateScatterUpdate3Params(element::f16, element::i16), + generateScatterUpdate3Params(element::f16, element::i32), + generateScatterUpdate3Params(element::f16, element::i64), + generateScatterUpdate3Params(element::f16, element::u32), + generateScatterUpdate3Params(element::f16, element::u64), + // i8 + generateScatterUpdate3Params(element::i8, element::i16), + generateScatterUpdate3Params(element::i8, element::i32), + generateScatterUpdate3Params(element::i8, element::i64), + generateScatterUpdate3Params(element::i8, element::u32), + generateScatterUpdate3Params(element::i8, element::u64), + // i16 + generateScatterUpdate3Params(element::i16, element::i16), + generateScatterUpdate3Params(element::i16, element::i32), + generateScatterUpdate3Params(element::i16, element::i64), + generateScatterUpdate3Params(element::i16, element::u32), + generateScatterUpdate3Params(element::i16, element::u64), + // i32 + generateScatterUpdate3Params(element::i32, element::i16), + generateScatterUpdate3Params(element::i32, element::i32), + generateScatterUpdate3Params(element::i32, element::i64), + generateScatterUpdate3Params(element::i32, element::u32), + generateScatterUpdate3Params(element::i32, element::u64), + // i64 + generateScatterUpdate3Params(element::i64, element::i16), + generateScatterUpdate3Params(element::i64, element::i32), + generateScatterUpdate3Params(element::i64, element::i64), + generateScatterUpdate3Params(element::i64, element::u32), + generateScatterUpdate3Params(element::i64, element::u64), + // u8 + generateScatterUpdate3Params(element::u8, element::i16), + generateScatterUpdate3Params(element::u8, element::i32), + generateScatterUpdate3Params(element::u8, element::i64), + generateScatterUpdate3Params(element::u8, element::u32), + generateScatterUpdate3Params(element::u8, element::u64), + // u16 + generateScatterUpdate3Params(element::u16, element::i16), + generateScatterUpdate3Params(element::u16, element::i32), + generateScatterUpdate3Params(element::u16, element::i64), + generateScatterUpdate3Params(element::u16, element::u32), + generateScatterUpdate3Params(element::u16, element::u64), + // u32 + generateScatterUpdate3Params(element::u32, element::i16), + generateScatterUpdate3Params(element::u32, element::i32), + generateScatterUpdate3Params(element::u32, element::i64), + generateScatterUpdate3Params(element::u32, element::u32), + generateScatterUpdate3Params(element::u32, element::u64), + // u64 + generateScatterUpdate3Params(element::u64, element::i16), + generateScatterUpdate3Params(element::u64, element::i32), + generateScatterUpdate3Params(element::u64, element::i64), + generateScatterUpdate3Params(element::u64, element::u32), + generateScatterUpdate3Params(element::u64, element::u64), + // bf16 + generateScatterUpdate3Params(element::bf16, element::i16), + generateScatterUpdate3Params(element::bf16, element::i32), + generateScatterUpdate3Params(element::bf16, element::i64), + generateScatterUpdate3Params(element::bf16, element::u32), + generateScatterUpdate3Params(element::bf16, element::u64)}; + std::vector combinedParams; + + for (const auto& params : ScatterUpdateTypeParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} + +std::vector generateScatterUpdateNegativeAxisParams() { + const std::vector> ScatterUpdateTypeParams { + // f32 + generateScatterUpdate3Params(element::f32, element::i16), + generateScatterUpdate3Params(element::f32, element::i32), + generateScatterUpdate3Params(element::f32, element::i64), + // f16 + generateScatterUpdate3Params(element::f16, element::i16), + generateScatterUpdate3Params(element::f16, element::i32), + generateScatterUpdate3Params(element::f16, element::i64), + // i8 + generateScatterUpdate3Params(element::i8, element::i16), + generateScatterUpdate3Params(element::i8, element::i32), + generateScatterUpdate3Params(element::i8, element::i64), + // i16 + generateScatterUpdate3Params(element::i16, element::i16), + generateScatterUpdate3Params(element::i16, element::i32), + generateScatterUpdate3Params(element::i16, element::i64), + // i32 + generateScatterUpdate3Params(element::i32, element::i16), + generateScatterUpdate3Params(element::i32, element::i32), + generateScatterUpdate3Params(element::i32, element::i64), + // i64 + generateScatterUpdate3Params(element::i64, element::i16), + generateScatterUpdate3Params(element::i64, element::i32), + generateScatterUpdate3Params(element::i64, element::i64), + // u8 + generateScatterUpdate3Params(element::u8, element::i16), + generateScatterUpdate3Params(element::u8, element::i32), + generateScatterUpdate3Params(element::u8, element::i64), + // u16 + generateScatterUpdate3Params(element::u16, element::i16), + generateScatterUpdate3Params(element::u16, element::i32), + generateScatterUpdate3Params(element::u16, element::i64), + // u32 + generateScatterUpdate3Params(element::u32, element::i16), + generateScatterUpdate3Params(element::u32, element::i32), + generateScatterUpdate3Params(element::u32, element::i64), + // u64 + generateScatterUpdate3Params(element::u64, element::i16), + generateScatterUpdate3Params(element::u64, element::i32), + generateScatterUpdate3Params(element::u64, element::i64), + // bf16 + generateScatterUpdate3Params(element::bf16, element::i16), + generateScatterUpdate3Params(element::bf16, element::i32), + generateScatterUpdate3Params(element::bf16, element::i64)}; + std::vector combinedParams; + + for (const auto& params : ScatterUpdateTypeParams) { + combinedParams.insert(combinedParams.end(), params.begin(), params.end()); + } + return combinedParams; +} +} // namespace + +INSTANTIATE_TEST_SUITE_P(smoke_ScatterUpdate_With_Hardcoded_Refs, ReferenceScatterUpdate6LayerTest, + ::testing::ValuesIn(generateScatterUpdateCombinedParams()), ReferenceScatterUpdate6LayerTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_ScatterUpdate_Negative_Axis_With_Hardcoded_Refs, ReferenceScatterUpdate6LayerTest, + ::testing::ValuesIn(generateScatterUpdateNegativeAxisParams()), ReferenceScatterUpdate6LayerTest::getTestCaseName); +} // namespace reference_tests diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/scatter_update.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/scatter_update.cpp index 31362e0b2646b2..855adb4112e517 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/scatter_update.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/scatter_update.cpp @@ -25,6 +25,9 @@ const std::vector idxPrecisions = { // map> std::map, std::map, std::vector>> axesShapeInShape { + {{10, 16, 12, 15}, {{{2, 2, 2}, {0, 1, 2, 3}}, {{2, 4}, {0, 1, 2, 3}}, {{8}, {0, 1, 2, 3}}}}, + {{10, 9, 10, 9, 10}, {{{8}, {0, 1, 2, 3, 4}}, {{4, 2}, {0, 1, 2, 3, 4}}}}, + {{10, 9, 10, 9, 10, 12}, {{{8}, {0, 1, 2, 3, 4, 5}}}}, {{10, 16, 12, 15}, {{{2, 4}, {0, 1, 2, 3}}, {{8}, {-1, -2, -3, -4}}}}, {{10, 9, 10, 9, 10}, {{{8}, {-3, -1, 0, 2, 4}}, {{4, 2}, {-2, 2}}}}, }; @@ -43,4 +46,4 @@ const auto ScatterUpdateCase = ::testing::Combine( INSTANTIATE_TEST_SUITE_P(smoke_ScatterUpdate, ScatterUpdateLayerTest, ScatterUpdateCase, ScatterUpdateLayerTest::getTestCaseName); -} // namespace +} // namespace \ No newline at end of file diff --git a/ngraph/core/reference/include/ngraph/runtime/reference/scatter_update.hpp b/ngraph/core/reference/include/ngraph/runtime/reference/scatter_update.hpp index 0b4025d431db9f..6224726d0011d5 100644 --- a/ngraph/core/reference/include/ngraph/runtime/reference/scatter_update.hpp +++ b/ngraph/core/reference/include/ngraph/runtime/reference/scatter_update.hpp @@ -4,13 +4,32 @@ #pragma once +#include + #include "ngraph/check.hpp" #include "ngraph/coordinate_transform.hpp" #include "ngraph/shape.hpp" +#include "ngraph/util.hpp" namespace ngraph { namespace runtime { namespace reference { +static const CoordinateTransformBasic get_target_shape(const Shape& data_shape, + const Coordinate& start_corner, + const Coordinate& end_corner) { + const auto m_n_axes = data_shape.size(); + Shape target_shape; + target_shape.reserve(m_n_axes); + AxisVector axis_order(m_n_axes); + std::iota(axis_order.begin(), axis_order.end(), 0); + const Strides strides(m_n_axes, 1); + for (size_t axis = 0; axis < m_n_axes; axis++) { + target_shape.push_back( + ceil_div(end_corner[axis_order[axis]] - start_corner[axis_order[axis]], strides[axis_order[axis]])); + } + return target_shape; +} + void scatter_update(const char* input_data, const int64_t* indices, const char* updates, @@ -36,43 +55,57 @@ void scatter_update(const char* input_data, // for d_coord in slice data[..., i_idx, ...], // u_coord in slice updates[..., i_coord, ...] // data[index(d_coord)] = updates[index(u_coord)] - - NGRAPH_SUPPRESS_DEPRECATED_START - CoordinateTransform indices_transform{indices_shape}; - CoordinateTransform data_transform{data_shape}; + CoordinateTransformBasic indices_transform{indices_shape}; + const auto indices_in_strides = row_major_strides(indices_shape); size_t indices_ndim = indices_shape.size(); size_t updates_ndim = updates_shape.size(); + size_t data_ndim = data_shape.size(); + + const auto size_after_axis = shape_size(Shape(data_shape.begin() + axis + 1, data_shape.end())); + int num_axis_jumps{0}; + int num_unary_moves{0}; + for (size_t i = axis + 1; i < updates_ndim; ++i) { + const auto updates_size_after_axis = shape_size(Shape(updates_shape.begin() + i, updates_shape.end())); + if (updates_size_after_axis > size_after_axis) + ++num_axis_jumps; + if (updates_shape[i] == 1) + ++num_unary_moves; + } + + if (!num_axis_jumps) + num_axis_jumps = updates_ndim - data_ndim; + + auto updates_axis_dim = axis + num_axis_jumps + num_unary_moves; + + if (updates_axis_dim >= updates_ndim) + updates_axis_dim = updates_ndim - 1; - // Create an outer CoordinateTransform for "update", which would allow to - // iterate only over "indices" dimensions: - // set to "1" all non-indices dimensions - // updates[1, ..., 1, m, n, ..., p, 1, 1,..., 1] Coordinate updates_indices_start_corner(updates_ndim, 0); Coordinate updates_indices_end_corner(updates_ndim, 1); + for (size_t i = 0; i < indices_ndim; ++i) { updates_indices_end_corner[axis + i] = updates_shape[axis + i]; } - CoordinateTransform updates_indices_transform(updates_shape, - updates_indices_start_corner, - updates_indices_end_corner); - // Is needed to simultaneously iterate over updates coordinates while - // iterating over indices. + + const auto updates_indices_transform = + get_target_shape(updates_shape, updates_indices_start_corner, updates_indices_end_corner); auto updates_indices_coord_iter = updates_indices_transform.begin(); + int iteration{0}; for (const Coordinate& indices_cord : indices_transform) { - const size_t indices_idx = indices_transform.index(indices_cord); + const size_t indices_idx = + std::inner_product(indices_cord.begin(), indices_cord.end(), indices_in_strides.begin(), 0); int64_t slice_index = indices[indices_idx]; - // Define the extent of coordinates which will be updated. Coordinate out_start_corner(data_shape.size(), 0); Coordinate out_end_corner(data_shape); out_start_corner[axis] = static_cast(slice_index); out_end_corner[axis] = out_start_corner[axis] + 1; - CoordinateTransform out_transform(data_shape, out_start_corner, out_end_corner); - // Define the CoordinateTransform for updates coordinates. - // All except indices-dimensions. + const auto out_transform = get_target_shape(data_shape, out_start_corner, out_end_corner); + const auto out_transform_in_strides = row_major_strides(data_shape); + if (updates_indices_coord_iter == updates_indices_transform.end()) break; Coordinate updates_update_start_corner = *updates_indices_coord_iter; @@ -80,27 +113,32 @@ void scatter_update(const char* input_data, for (size_t i = 0; i < indices_ndim; ++i) { updates_update_end_corner[axis + i] = updates_update_start_corner[axis + i] + 1; } - // The m, n, .., p symbols stand for values at those axes. - // The m+1 means value at axis m plus 1. - // udpates_shape (start): [ 0, ..., 0, m , n , ... p , 0, ..., 0] - // updates_shape (end): [-1, ..., -1, m+1, n+1, ... p+1, -1, ..., -1] - CoordinateTransform updates_update_transform(updates_shape, - updates_update_start_corner, - updates_update_end_corner); + + const auto updates_update_transform = + get_target_shape(updates_shape, updates_update_start_corner, updates_update_end_corner); + const auto updates_update_in_strides = row_major_strides(updates_shape); auto updates_update_coord_iter = updates_update_transform.begin(); + for (const Coordinate& out_cord : out_transform) { if (updates_update_coord_iter == updates_update_transform.end()) break; - const auto src_idx = updates_update_transform.index(*updates_update_coord_iter) * elem_size; - std::copy(updates + src_idx, - updates + (src_idx + elem_size), - out_buf + out_transform.index(out_cord) * elem_size); + Coordinate update_cord = *updates_update_coord_iter; + Coordinate out_coord = out_cord; + out_coord.at(axis) = slice_index; + update_cord.at(updates_axis_dim) += iteration; + const auto data_idx = + std::inner_product(out_coord.begin(), out_coord.end(), out_transform_in_strides.begin(), 0); + const auto updates_idx = + std::inner_product(update_cord.begin(), update_cord.end(), updates_update_in_strides.begin(), 0) * + elem_size; + + std::copy(updates + updates_idx, updates + (updates_idx + elem_size), out_buf + data_idx * elem_size); updates_update_coord_iter++; } updates_indices_coord_iter++; + iteration++; } - NGRAPH_SUPPRESS_DEPRECATED_END } } // namespace reference } // namespace runtime -} // namespace ngraph +} // namespace ngraph \ No newline at end of file diff --git a/ngraph/core/src/op/scatter_update.cpp b/ngraph/core/src/op/scatter_update.cpp index d9ec7918d027f5..80b8a2cb29c9df 100644 --- a/ngraph/core/src/op/scatter_update.cpp +++ b/ngraph/core/src/op/scatter_update.cpp @@ -109,4 +109,4 @@ bool op::v3::ScatterUpdate::has_evaluate() const { break; } return false; -} +} \ No newline at end of file