From 7048f756dc0ccd0e4142d22b70af4b1d200036f1 Mon Sep 17 00:00:00 2001 From: Michael Yi Date: Mon, 2 Nov 2020 13:06:23 -0800 Subject: [PATCH] Variadic Split (#91) * variadic split w/o -1 * -1 implemented * Fix -1 support in variadic split and test it * Style consistency * Cleanup * Fix exception message --- .../src/plaidml_plugin/ops/variadic_split.cpp | 72 +++++++++++++++++++ .../single_layer_tests/variadic_split.cpp | 4 +- .../single_layer_tests/variadic_split.cpp | 36 ++++++++++ .../single_layer_tests/variadic_split.hpp | 2 +- .../src/single_layer_tests/variadic_split.cpp | 5 +- .../include/ngraph_functions/builders.hpp | 2 +- .../ngraph_functions/src/variadic_split.cpp | 4 +- 7 files changed, 117 insertions(+), 8 deletions(-) create mode 100644 inference-engine/src/plaidml_plugin/ops/variadic_split.cpp create mode 100644 inference-engine/tests/functional/plugin/plaidml/shared_tests_instances/single_layer_tests/variadic_split.cpp 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 204909e2557b87..e665b2ab9b5d3f 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(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/plugin/shared/include/single_layer_tests/variadic_split.hpp b/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/variadic_split.hpp index 26dc0d6f0d0e55..834c9a662eb2e0 100644 --- a/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/variadic_split.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/variadic_split.hpp @@ -15,7 +15,7 @@ namespace LayerTestsDefinitions { typedef std::tuple< - std::vector, // Num splits + std::vector, // Num splits size_t, // Axis InferenceEngine::Precision, // Net precision std::vector, // Input shapes diff --git a/inference-engine/tests/functional/plugin/shared/src/single_layer_tests/variadic_split.cpp b/inference-engine/tests/functional/plugin/shared/src/single_layer_tests/variadic_split.cpp index ba3c932a2424e5..ead2470c2190cd 100644 --- a/inference-engine/tests/functional/plugin/shared/src/single_layer_tests/variadic_split.cpp +++ b/inference-engine/tests/functional/plugin/shared/src/single_layer_tests/variadic_split.cpp @@ -23,7 +23,7 @@ namespace LayerTestsDefinitions { std::string VariadicSplitLayerTest::getTestCaseName(testing::TestParamInfo obj) { size_t axis; - std::vector numSplits; + std::vector numSplits; InferenceEngine::Precision netPrecision; InferenceEngine::SizeVector inputShapes; std::string targetDevice; @@ -41,7 +41,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, inputShape, targetDevice) = this->GetParam(); auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); diff --git a/inference-engine/tests/ngraph_functions/include/ngraph_functions/builders.hpp b/inference-engine/tests/ngraph_functions/include/ngraph_functions/builders.hpp index 22cf1da0077d11..b5443c74d48938 100644 --- a/inference-engine/tests/ngraph_functions/include/ngraph_functions/builders.hpp +++ b/inference-engine/tests/ngraph_functions/include/ngraph_functions/builders.hpp @@ -185,7 +185,7 @@ std::shared_ptr makeSplit(const ngraph::Output &in, size_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_functions/src/variadic_split.cpp b/inference-engine/tests/ngraph_functions/src/variadic_split.cpp index efdecb21c5374a..4bba791214aeeb 100644 --- a/inference-engine/tests/ngraph_functions/src/variadic_split.cpp +++ b/inference-engine/tests/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;