diff --git a/inference-engine/src/plaidml_plugin/ops/variadic_split.cpp b/inference-engine/src/plaidml_plugin/ops/variadic_split.cpp new file mode 100644 index 00000000000000..d18d8e1888daeb --- /dev/null +++ b/inference-engine/src/plaidml_plugin/ops/variadic_split.cpp @@ -0,0 +1,72 @@ +// Copyright (C) 2020 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "plaidml_ops.hpp" +#include "plaidml_util.hpp" + +#include "ngraph/opsets/opset.hpp" +#include "ngraph/opsets/opset1.hpp" + +#include "plaidml/op/op.h" + +using namespace plaidml; // NOLINT[build/namespaces] +using namespace InferenceEngine; // NOLINT[build/namespaces] + +namespace { + +template +std::vector cast_constant_operand(size_t operand_idx, ngraph::Node* layer) { + auto* ngraph_const = ngraph::as_type(layer->get_input_node_ptr(operand_idx)); + if (ngraph_const) { + return ngraph_const->cast_vector(); + } else { + THROW_IE_EXCEPTION << "Dynamic split lengths not currently supported by PlaidML plugin; all of split_lengths " + "must be Constants"; + } +} + +} // namespace + +namespace PlaidMLPlugin { + +static OpRegistration reg("variadicsplit", [](const Context& ctx) { + IE_ASSERT(ctx.operands.size() == 3); + auto I = ctx.operands.at(0); + auto axes = get_axis_vector_from_constant_operand(1, ctx.layer); + IE_ASSERT(axes.size() == 1); + auto axis = axes[0]; + auto split_lengths = cast_constant_operand(2, ctx.layer); + + auto ndims = I.rank(); + std::vector I_dims(ndims); + std::vector I_idxs(ndims); + std::vector Os; + I.bind_dims(I_dims); + auto O_dims = I_dims; + + size_t split_size = 0; + for (auto split : split_lengths) { + if (split != -1) { + split_size += split; + } + } + auto placeholder = I_dims[axis] - split_size; + + edsl::TensorDim offset(0); + for (auto split : split_lengths) { + auto O_idxs = I_idxs; + O_idxs[axis] = I_idxs[axis] - offset; + if (split == -1) { + O_dims[axis] = placeholder; + offset = offset + placeholder; + } else { + O_dims[axis] = edsl::TensorDim(split); + offset = offset + split; + } + Os.push_back(edsl::Contraction().outShape(O_dims).outAccess(O_idxs).assign(I(I_idxs))); + } + return edsl::make_tuple(Os); +}); + +} // namespace PlaidMLPlugin diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/variadic_split.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/variadic_split.cpp index cc3e7390cb2701..4107fb1497b3f2 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/variadic_split.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/variadic_split.cpp @@ -17,12 +17,12 @@ namespace { }; // Sum of elements numSplits = inputShapes[Axis] - const std::vector> numSplits = { + const std::vector> numSplits = { {1, 16, 5, 8}, {2, 19, 5, 4}, {7, 13, 2, 8}, {5, 8, 12, 5}, - {4, 11, 6, 9} + {4, 11, -1, 9} }; INSTANTIATE_TEST_CASE_P(smoke_NumSplitsCheck, VariadicSplitLayerTest, diff --git a/inference-engine/tests/functional/plugin/plaidml/shared_tests_instances/single_layer_tests/variadic_split.cpp b/inference-engine/tests/functional/plugin/plaidml/shared_tests_instances/single_layer_tests/variadic_split.cpp new file mode 100644 index 00000000000000..e9d37415c2ce3d --- /dev/null +++ b/inference-engine/tests/functional/plugin/plaidml/shared_tests_instances/single_layer_tests/variadic_split.cpp @@ -0,0 +1,36 @@ +// Copyright (C) 2019 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "single_layer_tests/variadic_split.hpp" +#include "common_test_utils/test_constants.hpp" + +using namespace LayerTestsDefinitions; + +namespace { + + const std::vector netPrecisions = { + InferenceEngine::Precision::FP32, + // InferenceEngine::Precision::FP16 + }; + + // Sum of elements numSplits = inputShapes[Axis] + const std::vector> numSplits = { + {1, 16, 5, 8}, + {2, 19, 5, 4}, + {7, 13, 2, 8}, + {5, 8, 12, 5}, + {4, 11, -1, 9} + }; + + INSTANTIATE_TEST_CASE_P(NumSplitsCheck, VariadicSplitLayerTest, + ::testing::Combine( + ::testing::ValuesIn(numSplits), + ::testing::Values(0, 1, 2, 3), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(std::vector({30, 30, 30, 30})), + ::testing::Values(CommonTestUtils::DEVICE_PLAIDML)), + VariadicSplitLayerTest::getTestCaseName); +} // namespace diff --git a/inference-engine/tests/functional/shared_test_classes/src/single_layer/variadic_split.cpp b/inference-engine/tests/functional/shared_test_classes/src/single_layer/variadic_split.cpp index 9922080182bd9e..d1d2df543fe55e 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/single_layer/variadic_split.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/single_layer/variadic_split.cpp @@ -8,7 +8,7 @@ namespace LayerTestsDefinitions { std::string VariadicSplitLayerTest::getTestCaseName(testing::TestParamInfo obj) { size_t axis; - std::vector numSplits; + std::vector numSplits; InferenceEngine::Precision netPrecision; InferenceEngine::Precision inPrc, outPrc; InferenceEngine::Layout inLayout, outLayout; @@ -32,7 +32,8 @@ namespace LayerTestsDefinitions { void VariadicSplitLayerTest::SetUp() { SetRefMode(LayerTestsUtils::RefMode::CONSTANT_FOLDING); size_t axis; - std::vector inputShape, numSplits; + std::vector inputShape; + std::vector numSplits; InferenceEngine::Precision netPrecision; std::tie(numSplits, axis, netPrecision, inPrc, outPrc, inLayout, outLayout, inputShape, targetDevice) = this->GetParam(); auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); diff --git a/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/builders.hpp b/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/builders.hpp index 2b0b614b89f049..8c2f7e9a604a03 100644 --- a/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/builders.hpp +++ b/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/builders.hpp @@ -191,7 +191,7 @@ std::shared_ptr makeSplit(const ngraph::Output &in, int64_t axis); std::shared_ptr makeVariadicSplit(const ngraph::Output &in, - const std::vector numSplits, + const std::vector numSplits, size_t axis); std::shared_ptr makeActivation(const ngraph::Output &in, diff --git a/inference-engine/tests/ngraph_helpers/ngraph_functions/src/variadic_split.cpp b/inference-engine/tests/ngraph_helpers/ngraph_functions/src/variadic_split.cpp index efdecb21c5374a..4bba791214aeeb 100644 --- a/inference-engine/tests/ngraph_helpers/ngraph_functions/src/variadic_split.cpp +++ b/inference-engine/tests/ngraph_helpers/ngraph_functions/src/variadic_split.cpp @@ -10,11 +10,11 @@ namespace ngraph { namespace builder { std::shared_ptr makeVariadicSplit(const ngraph::Output &in, - const std::vector numSplits, + const std::vector numSplits, size_t axis) { auto splitAxisOp = std::make_shared(element::u64, ngraph::Shape{}, std::vector{axis}); - auto numSplit = std::make_shared(element::u64, ngraph::Shape{numSplits.size()}, + auto numSplit = std::make_shared(element::i64, ngraph::Shape{numSplits.size()}, numSplits); auto VariadicSplitNode = std::make_shared(in, splitAxisOp, numSplit); return VariadicSplitNode;