From 28de7899938c812b83347e07f08cd3ce43b6ecc7 Mon Sep 17 00:00:00 2001 From: Maxim Kurin Date: Sat, 31 Oct 2020 02:02:23 +0300 Subject: [PATCH] [IE][VPU]: GatherND layer & tests (#2710) * GatherND layer & test * Update vpu firmware 1452 --- inference-engine/cmake/vpu_dependencies.cmake | 2 +- .../include/vpu/frontend/frontend.hpp | 1 + .../graph_transformer/include/vpu/model/stage.hpp | 1 + .../include/vpu/stage_builder.hpp | 9 ++ .../graph_transformer/src/frontend/frontend.cpp | 1 + .../vpu/graph_transformer/src/stages/gather_nd.cpp | 121 +++++++++++++++++++++ .../single_layer_tests/gather_nd.cpp | 6 +- .../single_layer_tests/gather_nd.cpp | 53 +++++++++ .../include/single_layer_tests/gather_nd.hpp | 6 +- .../shared/src/single_layer_tests/gather_nd.cpp | 12 +- .../include/ngraph_functions/builders.hpp | 1 + 11 files changed, 206 insertions(+), 7 deletions(-) create mode 100644 inference-engine/src/vpu/graph_transformer/src/stages/gather_nd.cpp create mode 100644 inference-engine/tests/functional/plugin/myriad/shared_tests_instances/single_layer_tests/gather_nd.cpp diff --git a/inference-engine/cmake/vpu_dependencies.cmake b/inference-engine/cmake/vpu_dependencies.cmake index fa67cfa..92ef842 100644 --- a/inference-engine/cmake/vpu_dependencies.cmake +++ b/inference-engine/cmake/vpu_dependencies.cmake @@ -19,7 +19,7 @@ set(VPU_SUPPORTED_FIRMWARES usb-ma2450 usb-ma2x8x pcie-ma248x) # Default packages # -set(FIRMWARE_PACKAGE_VERSION 1445) +set(FIRMWARE_PACKAGE_VERSION 1452) set(VPU_CLC_MA2X8X_VERSION "movi-cltools-20.09.1") # diff --git a/inference-engine/src/vpu/graph_transformer/include/vpu/frontend/frontend.hpp b/inference-engine/src/vpu/graph_transformer/include/vpu/frontend/frontend.hpp index 1bfdd94..2440941 100644 --- a/inference-engine/src/vpu/graph_transformer/include/vpu/frontend/frontend.hpp +++ b/inference-engine/src/vpu/graph_transformer/include/vpu/frontend/frontend.hpp @@ -156,6 +156,7 @@ public: void parseSwish(const Model& model, const ie::CNNLayerPtr& layer, const DataVector& inputs, const DataVector& outputs) const; void parseActivation(const Model& model, const ie::CNNLayerPtr& layer, const DataVector& inputs, const DataVector& outputs) const; void parseLogicalNot(const Model& model, const ie::CNNLayerPtr& layer, const DataVector& inputs, const DataVector& outputs) const; + void parseGatherND(const Model& model, const ie::CNNLayerPtr& layer, const DataVector& inputs, const DataVector& outputs) const; void parseHSwish(const Model& model, const ie::CNNLayerPtr& layer, const DataVector& inputs, const DataVector& outputs) const; // diff --git a/inference-engine/src/vpu/graph_transformer/include/vpu/model/stage.hpp b/inference-engine/src/vpu/graph_transformer/include/vpu/model/stage.hpp index f8119f3..7f624d9 100644 --- a/inference-engine/src/vpu/graph_transformer/include/vpu/model/stage.hpp +++ b/inference-engine/src/vpu/graph_transformer/include/vpu/model/stage.hpp @@ -171,6 +171,7 @@ VPU_DECLARE_ENUM(StageType, StridedSlice = 133, SoftPlus = 134, Swish = 135, + GatherND = 136, HSwish = 137, ) diff --git a/inference-engine/src/vpu/graph_transformer/include/vpu/stage_builder.hpp b/inference-engine/src/vpu/graph_transformer/include/vpu/stage_builder.hpp index cb3e57f..b463f4a 100644 --- a/inference-engine/src/vpu/graph_transformer/include/vpu/stage_builder.hpp +++ b/inference-engine/src/vpu/graph_transformer/include/vpu/stage_builder.hpp @@ -312,6 +312,15 @@ public: const Data& input0, const Data& input1, const Data& output); + + Stage addGatherNDStage( + const Model& model, + const std::string& name, + const ie::CNNLayerPtr& layer, + const Data& input, + const Data& indices, + const Data& output, + int32_t batch_dims); }; } // namespace vpu diff --git a/inference-engine/src/vpu/graph_transformer/src/frontend/frontend.cpp b/inference-engine/src/vpu/graph_transformer/src/frontend/frontend.cpp index d5e4482..e885a7b 100644 --- a/inference-engine/src/vpu/graph_transformer/src/frontend/frontend.cpp +++ b/inference-engine/src/vpu/graph_transformer/src/frontend/frontend.cpp @@ -129,6 +129,7 @@ FrontEnd::FrontEnd(StageBuilder::Ptr stageBuilder, const ie::ICore* core) {"SoftPlus", LAYER_PARSER(parseSoftPlus)}, {"Swish", LAYER_PARSER(parseSwish)}, {"Activation", LAYER_PARSER(parseActivation)}, + {"GatherND", LAYER_PARSER(parseGatherND)}, {"HSwish", LAYER_PARSER(parseHSwish)}, }} { VPU_THROW_UNLESS(_core != nullptr, "Argument core is null"); diff --git a/inference-engine/src/vpu/graph_transformer/src/stages/gather_nd.cpp b/inference-engine/src/vpu/graph_transformer/src/stages/gather_nd.cpp new file mode 100644 index 0000000..e97856c --- /dev/null +++ b/inference-engine/src/vpu/graph_transformer/src/stages/gather_nd.cpp @@ -0,0 +1,121 @@ +// Copyright (C) 2020 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include +#include + +namespace vpu { + +namespace { + +class GatherNDStage final : public StageNode { +public: + using StageNode::StageNode; + +protected: + StagePtr cloneImpl() const override { + return std::make_shared(*this); + } + + void propagateDataOrderImpl(StageDataInfo &orderInfo) override { + const auto input1 = inputEdge(0)->input(); + const auto input2 = inputEdge(1)->input(); + const auto output = outputEdge(0)->output(); + + orderInfo.setInput(inputEdge(0), + DimsOrder::fromNumDims(input1->desc().numDims())); + orderInfo.setInput(inputEdge(1), + DimsOrder::fromNumDims(input2->desc().numDims())); + orderInfo.setOutput(outputEdge(0), + DimsOrder::fromNumDims(output->desc().numDims())); + } + + void getDataStridesRequirementsImpl( + StageDataInfo &stridesInfo) override { + for (const auto &inEdge : inputEdges()) { + stridesInfo.setInput(inEdge, StridesRequirement::compact()); + } + stridesInfo.setOutput(outputEdge(0), StridesRequirement::compact()); + } + + void finalizeDataLayoutImpl() override {} + + void + getBatchSupportInfoImpl(StageDataInfo &batchInfo) override {} + + StageSHAVEsRequirements getSHAVEsRequirementsImpl() const override { + return StageSHAVEsRequirements::NotNeeded; + } + + void initialCheckImpl() const override { + VPU_THROW_UNLESS(numInputs() == 2, + "{} stage with name {} must have only 1 output, actually " + "provided {} inputs", + type(), name(), numInputs()); + VPU_THROW_UNLESS(numOutputs() == 1, + "{} stage with name {} must have only 1 output, actually " + "provided {} outputs", + type(), name(), numInputs()); + VPU_THROW_UNLESS(inputs()[0]->desc().type() == outputs()[0]->desc().type(), + "First input and output must have the same DataType, " + "actual input type is {} and output type is {}", + inputs()[0]->desc().type(), outputs()[0]->desc().type()); + assertInputsOutputsTypes( + this, {{DataType::U8, DataType::FP16, DataType::S32}, {DataType::S32}}, + {{DataType::U8, DataType::FP16, DataType::S32}}); + } + + void serializeParamsImpl(BlobSerializer &serializer) const override { + const auto batchDims = attrs().get("batch_dims"); + serializer.append(batchDims); + } + + void serializeDataImpl(BlobSerializer &serializer) const override { + auto input0 = inputEdge(0)->input(); + auto input1 = inputEdge(1)->input(); + auto output = outputEdge(0)->output(); + + input0->serializeBuffer(serializer); + output->serializeBuffer(serializer); + input1->serializeBuffer(serializer); + } +}; + +}// namespace + +Stage StageBuilder::addGatherNDStage(const Model &model, + const std::string &name, + const ie::CNNLayerPtr &layer, + const Data &input, const Data &indices, + const Data &output, int32_t batchDims) { + auto stage = model->addNewStage( + layer->name, StageType::GatherND, layer, {input, indices}, {output}); + + stage->attrs().set("batch_dims", batchDims); + + return stage; +} + +void FrontEnd::parseGatherND(const Model &model, const ie::CNNLayerPtr &layer, + const DataVector &inputs, + const DataVector &outputs) const { + VPU_THROW_UNLESS(layer, "CNNLayer pointer is null."); + VPU_THROW_UNLESS(inputs.size() == 2, + "{} layer with name {} must have only 1 output, actually " + "provided {} outputs", + layer->type, layer->name, inputs.size()); + VPU_THROW_UNLESS(outputs.size() == 1, + "{} layer with name {} must have only 1 output, actually " + "provided {} outputs", + layer->type, layer->name, outputs.size()); + + const auto batchDims = layer->GetParamAsInt("batch_dims", 0); + + _stageBuilder->addGatherNDStage(model, layer->name, layer, inputs[0], + inputs[1], outputs[0], batchDims); +} + +}// namespace vpu diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/gather_nd.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/gather_nd.cpp index d2ff976..5904fe7 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/gather_nd.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/gather_nd.cpp @@ -36,7 +36,8 @@ INSTANTIATE_TEST_CASE_P(smoke_Set1, GatherNDLayerTest, gatherNDArgsSubset1, ::testing::ValuesIn(dPrecisions), ::testing::ValuesIn(iPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_CPU)), + ::testing::Values(CommonTestUtils::DEVICE_CPU), + ::testing::Values({})), GatherNDLayerTest::getTestCaseName); const auto gatherNDArgsSubset2 = ::testing::Combine( @@ -51,6 +52,7 @@ INSTANTIATE_TEST_CASE_P(smoke_Set2, GatherNDLayerTest, gatherNDArgsSubset2, ::testing::ValuesIn(dPrecisions), ::testing::ValuesIn(iPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_CPU)), + ::testing::Values(CommonTestUtils::DEVICE_CPU), + ::testing::Values({})), GatherNDLayerTest::getTestCaseName); } // namespace diff --git a/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/single_layer_tests/gather_nd.cpp b/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/single_layer_tests/gather_nd.cpp new file mode 100644 index 0000000..3a8ea30 --- /dev/null +++ b/inference-engine/tests/functional/plugin/myriad/shared_tests_instances/single_layer_tests/gather_nd.cpp @@ -0,0 +1,53 @@ +// Copyright (C) 2020 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include "single_layer_tests/gather_nd.hpp" +#include + +using namespace LayerTestsDefinitions; + +namespace { + +const std::vector netPrecisions = { + InferenceEngine::Precision::U8, + InferenceEngine::Precision::FP16, + InferenceEngine::Precision::FP32, +}; + +const std::vector indicesPrecisions = { + InferenceEngine::Precision::I32, +}; + +const std::vector layerParams = { + // ngraph examples + // N = 1000: Not enough memory. replaced with 500 + // Probably always calculating with FP32 precision + GatherNDParamsSubset{{500, 256, 10, 15}, {25, 125, 3}, 0}, + GatherNDParamsSubset{{30, 2, 100, 35}, {30, 2, 3, 1}, 2}, + // some random tests + GatherNDParamsSubset{{3, 3}, {2, 2}, 0}, + GatherNDParamsSubset{{5, 3}, {2, 1}, 0}, + GatherNDParamsSubset{{5, 3, 4}, {2, 2}, 0}, + GatherNDParamsSubset{{6, 3, 4}, {2, 1, 2}, 0}, + GatherNDParamsSubset{{5, 2, 6, 8}, {1}, 0}, + GatherNDParamsSubset{{6, 6, 9, 7}, {2}, 0}, + GatherNDParamsSubset{{2, 4, 9, 4}, {3}, 0}, + GatherNDParamsSubset{{5, 2, 3, 7}, {4}, 0}, + GatherNDParamsSubset{{2, 2, 2}, {2, 1}, 1}, + GatherNDParamsSubset{{2, 2, 2, 2}, {2, 1}, 1}, + GatherNDParamsSubset{{2, 2, 2, 2}, {2, 2, 1}, 2}, +}; + +INSTANTIATE_TEST_CASE_P( + smoke_GatherND, + GatherNDLayerTest, + testing::Combine( + testing::ValuesIn(layerParams), + testing::ValuesIn(netPrecisions), + testing::ValuesIn(indicesPrecisions), + testing::Values(CommonTestUtils::DEVICE_MYRIAD), + testing::Values({{InferenceEngine::MYRIAD_DETECT_NETWORK_BATCH, CONFIG_VALUE(NO)}})), + GatherNDLayerTest::getTestCaseName); + +} // namespace diff --git a/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/gather_nd.hpp b/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/gather_nd.hpp index 5989b36..8111361 100644 --- a/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/gather_nd.hpp +++ b/inference-engine/tests/functional/plugin/shared/include/single_layer_tests/gather_nd.hpp @@ -10,6 +10,7 @@ #include "functional_test_utils/layer_test_utils.hpp" +using Config = std::map; typedef std::tuple< std::vector, // Data shapes @@ -21,13 +22,14 @@ typedef std::tuple< GatherNDParamsSubset, InferenceEngine::Precision, // Data precision InferenceEngine::Precision, // Indices precision - LayerTestsUtils::TargetDevice // Device name + LayerTestsUtils::TargetDevice, // Device name + Config // Plugin config > GatherNDParams; namespace LayerTestsDefinitions { class GatherNDLayerTest : public testing::WithParamInterface, - public LayerTestsUtils::LayerTestsCommon { + public LayerTestsUtils::LayerTestsCommon { public: static std::string getTestCaseName(const testing::TestParamInfo &obj); diff --git a/inference-engine/tests/functional/plugin/shared/src/single_layer_tests/gather_nd.cpp b/inference-engine/tests/functional/plugin/shared/src/single_layer_tests/gather_nd.cpp index 0440d6e..be43cc9 100644 --- a/inference-engine/tests/functional/plugin/shared/src/single_layer_tests/gather_nd.cpp +++ b/inference-engine/tests/functional/plugin/shared/src/single_layer_tests/gather_nd.cpp @@ -17,8 +17,9 @@ std::string GatherNDLayerTest::getTestCaseName(const testing::TestParamInfoGetParam(); + std::tie(gatherArgsSubset, dPrecision, iPrecision, targetDevice, configuration) = this->GetParam(); std::tie(dataShape, indicesShape, batchDims) = gatherArgsSubset; auto ngDPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(dPrecision); 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 29625c7..284aca1 100644 --- a/inference-engine/tests/ngraph_functions/include/ngraph_functions/builders.hpp +++ b/inference-engine/tests/ngraph_functions/include/ngraph_functions/builders.hpp @@ -439,5 +439,6 @@ std::shared_ptr makeNormalizeL2(const ngraph::Output& data, const std::vector& axes, float eps, ngraph::op::EpsMode epsMode); + } // namespace builder } // namespace ngraph -- 2.7.4