[GNA] Support for cascade concat with non functional layers between concats (#598)
authorAndrey Dmitriev <andrey.dmitriev@intel.com>
Thu, 30 Jul 2020 13:45:18 +0000 (16:45 +0300)
committerGitHub <noreply@github.com>
Thu, 30 Jul 2020 13:45:18 +0000 (16:45 +0300)
[GNA] Support for cascade concat with non functional layers between concats

inference-engine/src/gna_plugin/gna_graph_compiler.cpp
inference-engine/tests/functional/plugin/gna/shared_tests_instances/subgraph_tests/cascade_concat.cpp [new file with mode: 0644]
inference-engine/tests/functional/plugin/shared/include/subgraph_tests/cascade_concat.hpp [new file with mode: 0644]
inference-engine/tests/functional/plugin/shared/src/subgraph_tests/cascade_concat.cpp [new file with mode: 0644]

index a49d940..c4dee7f 100644 (file)
@@ -602,9 +602,22 @@ void GNAGraphCompiler::ConcatPrimitive(InferenceEngine::CNNLayerPtr layer) {
 
     auto& concatLayerInfo = concat_connection.find(concatLayer->name)->second;
     for (auto &&outLayer : getInputTo(concatLayer->outData.front())) {
-        if ( LayerInfo(outLayer.second).isConcat() ) {
-            connectOutput(layer, &concatLayerInfo.gna_ptr, concatLayerInfo.reserved_size);
+        auto concatCandidate = outLayer.second;
+        if (LayerInfo(concatCandidate).isNonFunctional()) {
+            // searching for next concat
+            auto isNonFunctional = [](CNNLayerPtr l) {
+                return LayerInfo(l).isNonFunctional();
+            };
+            if (!CNNNetHasNextLayerSkipCertain(concatCandidate, 0, 0, isNonFunctional)) {
+                continue;
+            }
+            concatCandidate = CNNNetGetNextLayerSkipCertain(concatCandidate, 0, 0, isNonFunctional).first;
+        }
+        if (!LayerInfo(concatCandidate).isConcat()) {
+            continue;
         }
+        gnalog() << "Cascaded concat connection found from: " << layer->name << ", to: " << concatCandidate->name << std::endl;
+        connectOutput(layer, &concatLayerInfo.gna_ptr, concatLayerInfo.reserved_size);
     }
 
     size_t idx = 0;
@@ -625,21 +638,22 @@ void GNAGraphCompiler::ConcatPrimitive(InferenceEngine::CNNLayerPtr layer) {
         auto layerInfo = LayerInfo(concatParent);
         // auto layerInfo = LayerInfo(getCreatorLayer(concatLayerInput->insData[it].lock()).lock());
         if (layerInfo.isInput()) {
+            auto & bytesAllocated = inputDesc->bytes_allocated_for_input[((InferenceEngine::CNNLayerPtr)layerInfo)->name];
             if (concatLayerInfo.input_allocated) {
                 // for concat input allocated only once, so lets mark this specific input layer also as allocated
                 // we will bind it to offset further in connectInput
                 // size need to be equal to full layer in order to pass checks
-                inputDesc->bytes_allocated_for_input[((InferenceEngine::CNNLayerPtr)layerInfo)->name] = concatLayerInfo.reserved_size;
+                bytesAllocated = concatLayerInfo.reserved_size;
             }
 
             connectInput(layer, &concatLayerInfo.gna_ptr,
                          concatLayerInfo.reserved_size, -static_cast<int32_t>(inputLayer.offset), idx);
 
             // TODO: currently connectInput api accept only total size, for concat we need extension for allocated, and actual sizes
-            inputDesc->bytes_allocated_for_input[((InferenceEngine::CNNLayerPtr) layerInfo)->name] = inputLayer.tensorSize;
+            bytesAllocated = inputLayer.tensorSize;
 
             concatLayerInfo.input_allocated = true;
-        } else  if (layerInfo.isMemory()) {
+        } else if (layerInfo.isMemory()) {
             connectInput(layer, &concatLayerInfo.gna_ptr, concatLayerInfo.reserved_size, -static_cast<int>(inputLayer.offset), idx);
 
             concatLayerInfo.input_allocated = true;
diff --git a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/subgraph_tests/cascade_concat.cpp b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/subgraph_tests/cascade_concat.cpp
new file mode 100644 (file)
index 0000000..16d2755
--- /dev/null
@@ -0,0 +1,65 @@
+// Copyright (C) 2020 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+#include <vector>
+#include <ie_precision.hpp>
+#include <subgraph_tests/cascade_concat.hpp>
+#include "common_test_utils/test_constants.hpp"
+
+using namespace LayerTestsDefinitions;
+
+namespace {
+    std::vector<std::vector<std::vector<size_t>>> shape1{
+            {{1, 64}},
+            {{1, 128}},
+            {{1, 32}},
+            {{1, 16}},
+            {{1, 8}}
+    };
+
+    std::vector<std::vector<std::vector<size_t>>> shape2{
+            {{1, 72}},
+            {{1, 128}},
+            {{1, 32}},
+            {{1, 16}},
+            {{1, 8}}
+    };
+
+    std::vector<std::vector<std::vector<size_t>>> shape3{
+            {{1, 80}},
+            {{1, 128}},
+            {{1, 32}},
+            {{1, 16}},
+            {{1, 8}}
+    };
+
+    std::vector<InferenceEngine::Precision> netPrecisions = {InferenceEngine::Precision::FP32,
+    };
+
+    std::map<std::string, std::string> additional_config = {
+            {"GNA_SCALE_FACTOR_0", "1"},
+            {"GNA_SCALE_FACTOR_1", "1"},
+            {"GNA_SCALE_FACTOR_2", "1"}
+    };
+
+    INSTANTIATE_TEST_CASE_P(cascade_concat, CascadeConcat,
+                            ::testing::Combine(
+                                    ::testing::ValuesIn(shape1),
+                                    ::testing::ValuesIn(shape2),
+                                    ::testing::ValuesIn(shape3),
+                                    ::testing::ValuesIn(netPrecisions),
+                                    ::testing::Values(false),
+                                    ::testing::Values(CommonTestUtils::DEVICE_GNA),
+                                    ::testing::Values(additional_config)),
+                            CascadeConcat::getTestCaseName);
+
+    INSTANTIATE_TEST_CASE_P(cascade_concat_multioutput, CascadeConcat,
+                            ::testing::Combine(
+                                    ::testing::ValuesIn(shape1),
+                                    ::testing::ValuesIn(shape2),
+                                    ::testing::ValuesIn(shape3),
+                                    ::testing::ValuesIn(netPrecisions),
+                                    ::testing::Values(true),
+                                    ::testing::Values(CommonTestUtils::DEVICE_GNA),
+                                    ::testing::Values(additional_config)),
+                            CascadeConcat::getTestCaseName);
+}  // namespace
diff --git a/inference-engine/tests/functional/plugin/shared/include/subgraph_tests/cascade_concat.hpp b/inference-engine/tests/functional/plugin/shared/include/subgraph_tests/cascade_concat.hpp
new file mode 100644 (file)
index 0000000..03cd47d
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright (C) 2020 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+#pragma once
+
+#include <tuple>
+#include <string>
+#include <vector>
+#include "functional_test_utils/layer_test_utils.hpp"
+#include "ngraph_functions/builders.hpp"
+
+namespace LayerTestsDefinitions {
+
+typedef std::tuple<
+        std::vector<std::vector<size_t>>, //input shapes 1
+        std::vector<std::vector<size_t>>, //input shapes 2
+        std::vector<std::vector<size_t>>, //input shapes 3
+        InferenceEngine::Precision,       //Network precision
+        bool,                             //Multioutput -> True, Single out ->false
+        std::string,                      //Device name
+        std::map<std::string, std::string>//config
+        > CascadeConcatTuple;
+
+class CascadeConcat
+        : public testing::WithParamInterface<CascadeConcatTuple>,
+          public LayerTestsUtils::LayerTestsCommon {
+public:
+    static std::string getTestCaseName(const testing::TestParamInfo<CascadeConcatTuple> &obj);
+protected:
+    void SetUp() override;
+};
+} // namespace LayerTestsDefinitions
diff --git a/inference-engine/tests/functional/plugin/shared/src/subgraph_tests/cascade_concat.cpp b/inference-engine/tests/functional/plugin/shared/src/subgraph_tests/cascade_concat.cpp
new file mode 100644 (file)
index 0000000..5e2d54b
--- /dev/null
@@ -0,0 +1,66 @@
+// Copyright (C) 2020 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+//
+#include <debug.h>
+#include "common_test_utils/common_utils.hpp"
+#include "functional_test_utils/precision_utils.hpp"
+#include "functional_test_utils/skip_tests_config.hpp"
+#include "subgraph_tests/cascade_concat.hpp"
+
+namespace LayerTestsDefinitions {
+
+std::string CascadeConcat::getTestCaseName(const testing::TestParamInfo<CascadeConcatTuple> &obj) {
+    std::vector<std::vector<size_t>> input1, input2, input3;
+    InferenceEngine::Precision netPrecision;
+    std::string targetName;
+    bool multioutput;
+    std::map<std::string, std::string> additional_config;
+    std::tie(input1, input2, input3, netPrecision, multioutput, targetName, additional_config) = obj.param;
+    std::ostringstream results;
+
+    results << "IS=" << CommonTestUtils::vec2str(input1[0]) << "_";
+    results << CommonTestUtils::vec2str(input2[0]) << "_";
+    results << CommonTestUtils::vec2str(input3[0]) << "_";
+    results << "netPRC=" << netPrecision.name() << "_";
+    results << "Multioutput=" << multioutput << "_";
+    results << "targetDevice=" << targetName << "_";
+    return results.str();
+}
+
+void CascadeConcat::SetUp() {
+    std::vector<std::vector<size_t>> input1, input2, input3;
+    InferenceEngine::Precision netPrecision;
+    std::map<std::string, std::string> additional_config;
+    bool multioutput;
+    std::tie(input1, input2, input3, netPrecision, multioutput, targetDevice, additional_config) = this->GetParam();
+    configuration.insert(additional_config.begin(), additional_config.end());
+    auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision);
+    auto input = ngraph::builder::makeParams(ngPrc, {input1[0], input2[0], input2[0]});
+    auto relu1 = std::make_shared<ngraph::opset1::Relu>(input[0]);
+    auto relu2 = std::make_shared<ngraph::opset1::Relu>(input[1]);
+    auto relu3 = std::make_shared<ngraph::opset1::Relu>(input[2]);
+    auto concat = std::make_shared<ngraph::opset1::Concat>(ngraph::OutputVector{relu1->output(0),
+                                                                                      relu2->output(0)},
+                                                                                1);
+    auto reshape = ngraph::builder::makeSqueezeUnsqueeze(concat, ngPrc, {0}, ngraph::helpers::SqueezeOpType::UNSQUEEZE);
+    auto reshape2 = ngraph::builder::makeSqueezeUnsqueeze(reshape, ngPrc, {0}, ngraph::helpers::SqueezeOpType::SQUEEZE);
+    auto concat2 = std::make_shared<ngraph::opset1::Concat>(ngraph::OutputVector{reshape2->output(0),
+                                                                                       relu3->output(0)},
+                                                                                 1);
+    ngraph::ResultVector results;
+    if (multioutput) {
+        auto const_mult = ngraph::builder::makeConstant(ngPrc, ngraph::Shape{1, input1[0][1]+input2[0][1]},
+                                                  std::vector<float>{1.01f});
+        auto mult = std::make_shared<ngraph::op::v0::Multiply>(concat, const_mult);
+        results = ngraph::ResultVector{std::make_shared<ngraph::opset1::Result>(concat2),
+                                       std::make_shared<ngraph::opset1::Result>(mult)};
+    } else {
+        results = ngraph::ResultVector{std::make_shared<ngraph::opset1::Result>(concat2)};
+    }
+    function = std::make_shared<ngraph::Function>(results, input, "concat_reshape_reshape_concat_mul");
+}
+
+TEST_P(CascadeConcat, CompareWithRefs) {
+    Run();
+}
+} // namespace LayerTestsDefinitions