diff --git a/inference-engine/src/gna_plugin/gna_graph_compiler.cpp b/inference-engine/src/gna_plugin/gna_graph_compiler.cpp index 256489be376..d3b522d89e4 100644 --- a/inference-engine/src/gna_plugin/gna_graph_compiler.cpp +++ b/inference-engine/src/gna_plugin/gna_graph_compiler.cpp @@ -797,22 +797,16 @@ void GNAGraphCompiler::ConcatPrimitive(InferenceEngine::CNNLayerPtr layer) { // 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 - bytesAllocated = concatLayerInfo.reserved_size; - } connectInput(layer, &concatLayerInfo.gna_ptr, - concatLayerInfo.reserved_size, -static_cast(inputLayer.offset), idx); + concatLayerInfo.reserved_size, inputLayer.offset, idx, false); // TODO: currently connectInput api accept only total size, for concat we need extension for allocated, and actual sizes bytesAllocated = inputLayer.tensorSize; concatLayerInfo.input_allocated = true; } else if (layerInfo.isMemory()) { - connectInput(layer, &concatLayerInfo.gna_ptr, concatLayerInfo.reserved_size, -static_cast(inputLayer.offset), idx); + connectInput(layer, &concatLayerInfo.gna_ptr, concatLayerInfo.reserved_size, inputLayer.offset, idx, false); concatLayerInfo.input_allocated = true; } @@ -2021,7 +2015,7 @@ void GNAGraphCompiler::connectOutput(InferenceEngine::CNNLayerPtr layer, void *p } } -GNAPluginNS::ConnectionDetails GNAGraphCompiler::connectInput(CNNLayerPtr layer, void *ptr, size_t num_data_bytes_in, int32_t offset, int idx) { +GNAPluginNS::ConnectionDetails GNAGraphCompiler::connectInput(CNNLayerPtr layer, void *ptr, size_t num_data_bytes_in, int32_t offset, int idx, bool connectTo) { // selecting particular input layers // auto prevLayer = CNNNetPrevLayer(layer, idx); auto prevLayer = CNNNetPrevLayerSkipCertain(layer, idx, [](CNNLayerPtr l) { @@ -2041,7 +2035,7 @@ GNAPluginNS::ConnectionDetails GNAGraphCompiler::connectInput(CNNLayerPtr layer, } // real allocation pointer will be kept in ptr not in ptr_inputs_global - if (offset < 0) { + if (!connectTo) { gnamem->push_value(ptr, static_cast(0), num_data_bytes_in, @@ -2062,20 +2056,20 @@ GNAPluginNS::ConnectionDetails GNAGraphCompiler::connectInput(CNNLayerPtr layer, << ", and size_requested=" << num_data_bytes_in; } - if (offset >= 0) { - gnamem->bind_ptr(ptr, &inputDesc->getPtrInputsGlobal(prevLayer->name).front(), offset); + if (connectTo) { + gnamem->bind_ptr(ptr, &inputDesc->getPtrInputsGlobal(prevLayer->name).front(), offset, ALIGN(num_data_bytes_in, 64)); } else { - gnamem->bind_ptr(&inputDesc->getPtrInputsGlobal(prevLayer->name).front(), ptr, -offset); + gnamem->bind_ptr(&inputDesc->getPtrInputsGlobal(prevLayer->name).front(), ptr, offset, ALIGN(num_data_bytes_in, 64)); } return prevLayer; } // const input if (LayerInfo(prevLayer).isConst()) { - if (offset >= 0) { + if (connectTo) { gnamem->bind_ptr(ptr, const_connections[prevLayer->name], offset); } else { - gnamem->bind_ptr(const_connections[prevLayer->name], ptr, -offset); + gnamem->bind_ptr(const_connections[prevLayer->name], ptr, offset); } return prevLayer; @@ -2146,17 +2140,17 @@ GNAPluginNS::ConnectionDetails GNAGraphCompiler::connectInput(CNNLayerPtr layer, if (memoryLayer.reserved_size == 0) { auto memorySize = InferenceEngine::details::product(memoryLayer.getDims()) * memoryLayer.elementSizeBytes(); - // negative offset used for indicate that memory layer should be bound to given buffer - if (offset >= 0) { + // connectTo used for indicate that memory layer should be bound to given buffer + if (connectTo) { memorySize = std::max(memorySize, num_data_bytes_in); gnamem->reserve_ptr(&memoryLayer.gna_ptr, ALIGN64(memorySize), 64); gnamem->bind_ptr(ptr, &memoryLayer.gna_ptr, offset); } else { - if (num_data_bytes_in > memorySize - offset) { + if (num_data_bytes_in < memorySize + offset) { THROW_GNA_LAYER_EXCEPTION(layer) <<" invalid allocation request of " - << num_data_bytes_in << " is more then state tensor size of: " << memorySize; + << num_data_bytes_in << " is more then state tensor size of: " << memorySize + offset; } - gnamem->bind_ptr(&memoryLayer.gna_ptr, ptr, -offset); + gnamem->bind_ptr(&memoryLayer.gna_ptr, ptr, offset); } memoryLayer.reserved_size = ALIGN64(memorySize); diff --git a/inference-engine/src/gna_plugin/gna_graph_compiler.hpp b/inference-engine/src/gna_plugin/gna_graph_compiler.hpp index 9f8e65e531c..65e4c010616 100644 --- a/inference-engine/src/gna_plugin/gna_graph_compiler.hpp +++ b/inference-engine/src/gna_plugin/gna_graph_compiler.hpp @@ -84,13 +84,16 @@ public: * @param num_data_bytes_in - size * @param offset - num bytes to advance in buffer * @param idx - index of input port that we are connecting + * @param connectTo - connectTo is true is alternative to positive or equal to zero offset + * in case when we would like to use zero offset and connect from pointer set this to negative * @return layer used as input */ GNAPluginNS::ConnectionDetails connectInput(InferenceEngine::CNNLayerPtr layer, void *pVoid, size_t num_data_bytes_in, int32_t offset = 0, - int idx = 0); + int idx = 0, + bool connectTo = true); /** * Fill in the Affine layer weights diff --git a/inference-engine/tests/functional/plugin/gna/shared_tests_instances/subgraph_tests/first_connect_input_concat.cpp b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/subgraph_tests/first_connect_input_concat.cpp new file mode 100644 index 00000000000..d9fa0ebeb7a --- /dev/null +++ b/inference-engine/tests/functional/plugin/gna/shared_tests_instances/subgraph_tests/first_connect_input_concat.cpp @@ -0,0 +1,38 @@ +// Copyright (C) 2020 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#include "subgraph_tests/first_connect_input_concat.hpp" +#include "common_test_utils/test_constants.hpp" + +using namespace LayerTestsDefinitions; + +namespace { + +std::vector>> inShapes = { + {{1, 1288}}, + {{1, 56}}, + {{1, 6456}} +}; + +const std::vector netPrecisions = { + InferenceEngine::Precision::FP32, + InferenceEngine::Precision::FP16, +}; + +std::map additional_config = { + {"GNA_DEVICE_MODE", "GNA_SW_EXACT"}, + {"GNA_COMPACT_MODE", "NO"}, +}; + +INSTANTIATE_TEST_CASE_P(smoke_concat_first_input, ConcatFirstInputTest, + ::testing::Combine( + ::testing::ValuesIn(inShapes), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(CommonTestUtils::DEVICE_GNA), + ::testing::Values(additional_config)), + ConcatFirstInputTest::getTestCaseName); + +} //namespace diff --git a/inference-engine/tests/functional/plugin/shared/include/subgraph_tests/first_connect_input_concat.hpp b/inference-engine/tests/functional/plugin/shared/include/subgraph_tests/first_connect_input_concat.hpp new file mode 100644 index 00000000000..aeb735697fa --- /dev/null +++ b/inference-engine/tests/functional/plugin/shared/include/subgraph_tests/first_connect_input_concat.hpp @@ -0,0 +1,33 @@ +// Copyright (C) 2020 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#pragma once + +#include +#include +#include +#include + +#include +#include + +typedef std::tuple< + std::vector>, // Input shapes + InferenceEngine::Precision, // Network Precision + std::string, // Target Device + std::map // Config +> concatFirstInputParams; + +namespace LayerTestsDefinitions { + +class ConcatFirstInputTest : public testing::WithParamInterface, + virtual public LayerTestsUtils::LayerTestsCommon { +public: + static std::string getTestCaseName(testing::TestParamInfo obj); + +protected: + void SetUp() override; +}; + +} // namespace LayerTestsDefinitions diff --git a/inference-engine/tests/functional/plugin/shared/src/subgraph_tests/first_connect_input_concat.cpp b/inference-engine/tests/functional/plugin/shared/src/subgraph_tests/first_connect_input_concat.cpp new file mode 100644 index 00000000000..01e8fbc91d6 --- /dev/null +++ b/inference-engine/tests/functional/plugin/shared/src/subgraph_tests/first_connect_input_concat.cpp @@ -0,0 +1,58 @@ +// Copyright (C) 2020 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include +#include + +#include + +#include "common_test_utils/common_utils.hpp" +#include "functional_test_utils/plugin_cache.hpp" +#include "functional_test_utils/layer_test_utils.hpp" +#include "functional_test_utils/blob_utils.hpp" + +#include "ngraph_functions/pass/convert_prc.hpp" + +#include "subgraph_tests/first_connect_input_concat.hpp" + + +namespace LayerTestsDefinitions { + +std::string ConcatFirstInputTest::getTestCaseName(testing::TestParamInfo obj) { + std::vector> inputShapes; + InferenceEngine::Precision netPrecision; + std::string targetDevice; + std::map additional_config; + std::tie(inputShapes, netPrecision, targetDevice, additional_config) = obj.param; + + std::ostringstream result; + result << "IS=" << CommonTestUtils::vec2str(inputShapes) << "_"; + result << "netPRC=" << netPrecision.name() << "_"; + result << "targetDevice=" << targetDevice; + + return result.str(); +} + +void ConcatFirstInputTest::SetUp() { + std::vector> inputShapes; + InferenceEngine::Precision netPrecision; + std::map additional_config; + std::tie(inputShapes, netPrecision, targetDevice, configuration) = this->GetParam(); + auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); + auto params = ngraph::builder::makeParams(ngPrc, inputShapes); + auto const_second_param = ngraph::builder::makeConstant(ngPrc, {1, 8}, std::vector{-1.0f}); + auto concat = std::make_shared(ngraph::OutputVector{params[0], const_second_param}, 1); + auto relu = std::make_shared(concat); + + ngraph::ResultVector results{std::make_shared(relu)}; + + function = std::make_shared(results, params, "ConcatMultiInput"); +} + +TEST_P(ConcatFirstInputTest, CompareWithRefImpl) { + Run(); +}; +} // namespace LayerTestsDefinitions