[GNA] Prohibit 2D data reshaping for diagonal layer if it's the first functional layer in network (#5097)

This commit is contained in:
Elizaveta Lobanova 2021-04-12 11:23:29 +03:00 committed by GitHub
parent e864972f83
commit 69be1f1c02
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 345 additions and 16 deletions

View File

@ -1204,16 +1204,17 @@ void GNAGraphCompiler::EltwisePrimitive(InferenceEngine::CNNLayerPtr layer) {
auto in_2b_width = GetDataDimSize(inputs2Bytes, InferenceEngine::DataDimName::W);
auto in_2b_total_size = in_2b_batch * in_2b_channels * in_2b_height * in_2b_width;
if (((in_2b_batch > 1) || (in_4b_batch > 1)) && in_2b_batch != in_4b_batch) {
THROW_GNA_LAYER_EXCEPTION(layer) << " Inputs with different batch sizes that not equals 1 is not supported";
if (in_2b_batch != in_4b_batch) {
THROW_GNA_LAYER_EXCEPTION(layer) << " Inputs with different batch sizes are not supported";
}
if (in_4b_total_size != in_2b_total_size) {
THROW_GNA_LAYER_EXCEPTION(layer) << " Inputs size mismatch " << in_4b_total_size << " != " << in_2b_total_size;
}
uint32_t num_rows_in = in_4b_channels * in_4b_height * in_4b_width;
uint32_t num_columns_in = in_4b_batch;
// If batch size > 1 the data is reshaped to one with batch size = 1
uint32_t num_rows_in = in_4b_total_size;
uint32_t num_columns_in = 1;
uint32_t num_rows_out = num_rows_in;
uint32_t num_padding = ALIGN(num_rows_in, noOfInputsDivisor) - num_rows_in;

View File

@ -5,6 +5,7 @@
#pragma once
#include <legacy/graph_tools.hpp>
#include "gna_graph_tools.hpp"
#include "gna_plugin_log.hpp"
#include "layers/gna_layer_info.hpp"
@ -54,6 +55,14 @@ inline bool HasTo2DReshapeData(InferenceEngine::CNNLayerPtr layer) {
if (layer->name.rfind("SyntheticScaleShift", 0) == std::string::npos)
return false;
// Don't reshape the first dnn layer since it breaks groups recognition
auto prevLayer = InferenceEngine::CNNNetPrevLayerSkipCertain(layer, 0, [](InferenceEngine::CNNLayerPtr ptr) {
return LayerInfo(ptr).isNonValuesChangable();
});
IE_ASSERT(prevLayer != nullptr);
if (LayerInfo(prevLayer).isInput())
return false;
// Don't reshape diagonallayers with bias connection
return !GNAPluginNS::LayerInfo(getCreatorLayer(layer->insData.front().lock()).lock()).has32BOutput();
}

View File

@ -913,7 +913,7 @@ void GNAModelSerial::ImportTranspositionInfo(std::istream &is,
void GNAModelSerial::ExportTranspositionInfo(std::ostream &os,
const TranspositionInfoMap &transpositionInfoMap) const {
for (const auto &transpositionInfo : transpositionInfoMap) {
auto nameSize = strlen(transpositionInfo.first.c_str()) + 1;
auto nameSize = strlen(transpositionInfo.first.c_str());
writeBits(static_cast<uint32_t>(nameSize), os);
writeNBytes(transpositionInfo.first.c_str(), nameSize, os);
auto fragmentsNum = transpositionInfo.second.size();

View File

@ -270,6 +270,9 @@ class LayerInfo {
}
return true;
}
bool isNonValuesChangable() const {
return isNonFunctional() || isSplit() || isSlice() || isConcat();
}
bool isPooling() const noexcept {
return isOfType("pooling");
}

View File

@ -81,9 +81,13 @@ static void insertDiagonalLayerBetween(InferenceEngine::CNNLayerPtr prevLayer,
auto diagLayer = std::make_shared<ScaleShiftLayer>(LayerParams({diagName, "ScaleShift", Precision::FP32}));
IE_ASSERT(diagLayer != nullptr);
// TODO: diagonal size
size_t weightsSize = LayerInfo(prevLayer).has32BOutput() ? weightsSize = nextLayer->outData[0]->getDims().back() :
Get2DReshapedData(nextLayer->outData[0], 8)->getDims()[1];
auto inputLayer = InferenceEngine::CNNNetPrevLayerSkipCertain(nextLayer, 0, [](InferenceEngine::CNNLayerPtr ptr) {
return LayerInfo(ptr).isNonValuesChangable();
});
IE_ASSERT(inputLayer != nullptr);
size_t weightsSize = (LayerInfo(prevLayer).has32BOutput() || LayerInfo(inputLayer).isInput()) ?
weightsSize = nextLayer->outData[0]->getDims().back() :
Get2DReshapedData(nextLayer->outData[0], 8)->getDims()[1];
std::vector<float> weightsValues(weightsSize, fillValue);
IE_ASSERT(diagLayer != nullptr);
diagLayer->_weights = make_shared_blob<float>(

View File

@ -79,10 +79,12 @@ void FP::ApplyDiagonalTransform(intel_dnn_component_t *component) {
C[i * ldc + j] = bias[i];
}
}
for (uint32_t j = 0; j < n; j++) {
float *Bcol = B + j * component->num_rows_in;
float *Ccol = C + j * component->num_rows_out;
cblas_ssbmv1(CblasRowMajor, CblasLower, m, 0, 1.0, A, 1, Bcol, 1, 1.0, Ccol, 1);
std::vector<float> Arow(n);
for (uint32_t i = 0; i < m; i++) {
float *Brow = B + i * n;
float *Crow = C + i * ldc;
std::fill(std::begin(Arow), std::end(Arow), A[i]);
cblas_ssbmv1(CblasRowMajor, CblasLower, n, 0, 1.0, Arow.data(), 1, Brow, 1, 1.0, Crow, 1);
}
}

View File

@ -0,0 +1,178 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <vector>
#include <memory>
#include <tuple>
#include <vector>
#include <string>
#include <fstream>
#include <ie_core.hpp>
#include <ie_layouts.h>
#include "shared_test_classes/base/layer_test_utils.hpp"
#include "functional_test_utils/blob_utils.hpp"
#include "ngraph_functions/utils/ngraph_helpers.hpp"
#include "ngraph_functions/builders.hpp"
typedef std::tuple<
std::vector<size_t>, // Input shape
InferenceEngine::Precision, // Network Precision
std::string, // Target Device
std::map<std::string, std::string>, // Export Configuration
std::map<std::string, std::string> // Import Configuration
> exportImportNetworkParams;
namespace LayerTestsDefinitions {
class ImportActConvActTest : public testing::WithParamInterface<exportImportNetworkParams>,
public LayerTestsUtils::LayerTestsCommon {
public:
static std::string getTestCaseName(testing::TestParamInfo<exportImportNetworkParams> obj) {
std::vector<size_t> inputShape;
InferenceEngine::Precision netPrecision;
std::string targetDevice;
std::map<std::string, std::string> exportConfiguration;
std::map<std::string, std::string> importConfiguration;
std::tie(inputShape, netPrecision, targetDevice, exportConfiguration, importConfiguration) = obj.param;
std::ostringstream result;
result << "netPRC=" << netPrecision.name() << "_";
result << "targetDevice=" << targetDevice << "_";
for (auto const &configItem : exportConfiguration) {
result << "_exportConfigItem=" << configItem.first << "_" << configItem.second;
}
for (auto const &configItem : importConfiguration) {
result << "_importConfigItem=" << configItem.first << "_" << configItem.second;
}
result << CommonTestUtils::vec2str(inputShape);
return result.str();
}
void Run() override {
SKIP_IF_CURRENT_TEST_IS_DISABLED()
configuration.insert(exportConfiguration.begin(), exportConfiguration.end());
LoadNetwork();
GenerateInputs();
Infer();
executableNetwork.Export("exported_model.blob");
for (auto const &configItem : importConfiguration) {
configuration[configItem.first] = configItem.second;
}
std::fstream inputStream("exported_model.blob", std::ios_base::in | std::ios_base::binary);
if (inputStream.fail()) {
FAIL() << "Cannot open file to import model: exported_model.blob";
}
auto importedNetwork = core->ImportNetwork(inputStream, targetDevice, configuration);
// Generate inputs
std::vector<InferenceEngine::Blob::Ptr> inputs;
auto inputsInfo = importedNetwork.GetInputsInfo();
auto functionParams = function->get_parameters();
for (int i = 0; i < functionParams.size(); ++i) {
const auto& param = functionParams[i];
const auto infoIt = inputsInfo.find(param->get_friendly_name());
GTEST_ASSERT_NE(infoIt, inputsInfo.cend());
const auto& info = infoIt->second;
auto blob = GenerateInput(*info);
inputs.push_back(blob);
}
// Infer imported network
InferenceEngine::InferRequest importInfer = importedNetwork.CreateInferRequest();
inputsInfo = importedNetwork.GetInputsInfo();
functionParams = function->get_parameters();
for (int i = 0; i < functionParams.size(); ++i) {
const auto& param = functionParams[i];
const auto infoIt = inputsInfo.find(param->get_friendly_name());
GTEST_ASSERT_NE(infoIt, inputsInfo.cend());
const auto& info = infoIt->second;
auto blob = inputs[i];
importInfer.SetBlob(info->name(), blob);
}
importInfer.Infer();
// Validate
auto expectedOutputs = CalculateRefs();
auto actualOutputs = std::vector<InferenceEngine::Blob::Ptr>{};
for (const auto &output : importedNetwork.GetOutputsInfo()) {
const auto &name = output.first;
actualOutputs.push_back(importInfer.GetBlob(name));
}
IE_ASSERT(actualOutputs.size() == expectedOutputs.size())
<< "nGraph interpreter has " << expectedOutputs.size() << " outputs, while IE " << actualOutputs.size();
Compare(expectedOutputs, actualOutputs);
}
protected:
void SetUp() override {
std::vector<size_t> inputShape;
InferenceEngine::Precision netPrecision;
std::tie(inputShape, netPrecision, targetDevice, exportConfiguration, importConfiguration) = this->GetParam();
auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision);
auto params = ngraph::builder::makeParams(ngPrc, {inputShape});
auto relu1 = std::make_shared<ngraph::opset1::Relu>(params[0]);
size_t num_out_channels = 8;
size_t kernel_size = 8;
std::vector<float> filter_weights = CommonTestUtils::generate_float_numbers(num_out_channels * inputShape[1] * kernel_size,
-0.2f, 0.2f);
auto conv = ngraph::builder::makeConvolution(relu1, ngPrc, { 1, kernel_size }, { 1, 1 }, { 0, 0 }, { 0, 0 }, { 1, 1 },
ngraph::op::PadType::VALID, num_out_channels, true, filter_weights);
auto relu2 = std::make_shared<ngraph::opset1::Relu>(conv);
ngraph::ResultVector results{std::make_shared<ngraph::opset1::Result>(relu2)};
function = std::make_shared<ngraph::Function>(results, params, "ExportImportNetwork");
}
private:
std::map<std::string, std::string> exportConfiguration;
std::map<std::string, std::string> importConfiguration;
};
TEST_P(ImportActConvActTest, CompareWithRefImpl) {
Run();
};
const std::vector<std::vector<size_t>> inputShape = {
{1, 1, 1, 240},
{1, 1, 1, 160},
{1, 2, 1, 80}
};
const std::vector<InferenceEngine::Precision> netPrecisions = {
InferenceEngine::Precision::FP32,
InferenceEngine::Precision::FP16
};
const std::vector<std::map<std::string, std::string>> exportConfigs = {
{
{"GNA_DEVICE_MODE", "GNA_SW_EXACT"}
}
};
const std::vector<std::map<std::string, std::string>> importConfigs = {
{
{"GNA_DEVICE_MODE", "GNA_SW_EXACT"}
}
};
INSTANTIATE_TEST_CASE_P(smoke_ImportActConvAct, ImportActConvActTest,
::testing::Combine(
::testing::ValuesIn(inputShape),
::testing::ValuesIn(netPrecisions),
::testing::Values(CommonTestUtils::DEVICE_GNA),
::testing::ValuesIn(exportConfigs),
::testing::ValuesIn(importConfigs)),
ImportActConvActTest::getTestCaseName);
} // namespace LayerTestsDefinitions

View File

@ -39,11 +39,7 @@ std::map<std::vector<size_t>, std::vector<std::vector<size_t>>> basic = {
{{1, 50}, {{}}},
{{1, 128}, {{}}},
{{1, 10 * 1024}, {{}}},
{{64, 1}, {{}}},
{{8, 128}, {{}}},
{{16, 128}, {{}}},
{{18, 128}, {{}}},
{{32, 512}, {{}}},
{{1, 4, 2, 256}, {{}}},
{{4, 4, 4, 4}, {{}}},
{{1, 16, 1, 128}, {{}}},

View File

@ -0,0 +1,41 @@
// Copyright (C) 2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <vector>
#include "subgraph_tests/eltwise_reshape_activation.hpp"
#include "common_test_utils/test_constants.hpp"
using namespace SubgraphTestsDefinitions;
namespace {
const std::vector<std::vector<std::vector<size_t>>> shapes = {
{{1, 64}, {64, 1}},
{{8, 256}, {16, 128}},
{{6, 384}, {18, 128}},
{{8, 2048}, {32, 512}}
};
const std::vector<InferenceEngine::Precision> netPrecisions = {
InferenceEngine::Precision::FP32,
InferenceEngine::Precision::FP16
};
std::vector<std::map<std::string, std::string>> additional_config = {
{
{"GNA_DEVICE_MODE", "GNA_SW_FP32"}
},
{
{"GNA_DEVICE_MODE", "GNA_SW_EXACT"}
}
};
INSTANTIATE_TEST_CASE_P(smoke_EltwiseReshapeActivationTest, EltwiseReshapeActivation,
::testing::Combine(
::testing::ValuesIn(shapes),
::testing::ValuesIn(netPrecisions),
::testing::Values(CommonTestUtils::DEVICE_GNA),
::testing::ValuesIn(additional_config)),
EltwiseReshapeActivation::getTestCaseName);
} // namespace

View File

@ -0,0 +1,15 @@
// Copyright (C) 2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include "shared_test_classes/subgraph/eltwise_reshape_activation.hpp"
namespace SubgraphTestsDefinitions {
TEST_P(EltwiseReshapeActivation, CompareWithRefs) {
Run();
}
} // namespace SubgraphTestsDefinitions

View File

@ -0,0 +1,29 @@
// Copyright (C) 2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <string>
#include "shared_test_classes/base/layer_test_utils.hpp"
namespace SubgraphTestsDefinitions {
using EltwiseReshapeActivationParams = typename std::tuple<
std::vector<std::vector<size_t>>, // input shape and shape after reshape
InferenceEngine::Precision, // precision
std::string, // device name
std::map<std::string, std::string> // configuration
>;
class EltwiseReshapeActivation : public testing::WithParamInterface<EltwiseReshapeActivationParams>,
public LayerTestsUtils::LayerTestsCommon {
public:
static std::string getTestCaseName(testing::TestParamInfo<ParamType> obj);
protected:
void SetUp() override;
};
} // namespace SubgraphTestsDefinitions

View File

@ -0,0 +1,51 @@
// Copyright (C) 2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#include "ngraph_functions/builders.hpp"
#include "shared_test_classes/subgraph/eltwise_reshape_activation.hpp"
namespace SubgraphTestsDefinitions {
using namespace CommonTestUtils;
using namespace InferenceEngine;
std::string EltwiseReshapeActivation::getTestCaseName(testing::TestParamInfo<ParamType> obj) {
InferenceEngine::Precision netPrecision;
std::vector<std::vector<size_t>> shapes;
std::string targetDevice;
std::map<std::string, std::string> configuration;
std::tie(shapes, netPrecision, targetDevice, configuration) = obj.param;
std::ostringstream result;
result << "IS=" << CommonTestUtils::vec2str(shapes[0]) << "_";
result << "AS=" << CommonTestUtils::vec2str(shapes[1]) << "_";
result << "PRC=" << netPrecision.name() << "_";
result << "dev=" << targetDevice;
for (auto const& configItem : configuration) {
result << "_configItem=" << configItem.first << "_" << configItem.second;
}
return result.str();
}
void EltwiseReshapeActivation::SetUp() {
InferenceEngine::Precision netPrecision;
std::vector<std::vector<size_t>> shapes;
std::map<std::string, std::string> config;
std::tie(shapes, netPrecision, targetDevice, config) = this->GetParam();
configuration.insert(config.begin(), config.end());
auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision);
auto input = ngraph::builder::makeParams(ngPrc, { shapes[0], shapes[0] });
auto eltw = ngraph::builder::makeEltwise(input[0], input[1], ngraph::helpers::EltwiseTypes::ADD);
auto reshape_pattern1 = std::make_shared<ngraph::op::Constant>(ngraph::element::i64, ngraph::Shape{shapes[1].size()}, shapes[1]);
auto reshape1 = std::make_shared<ngraph::op::v1::Reshape>(eltw, reshape_pattern1, false);
auto relu = ngraph::builder::makeActivation(reshape1, ngPrc, ngraph::helpers::ActivationTypes::Relu);
auto reshape_pattern2 = std::make_shared<ngraph::op::Constant>(ngraph::element::i64, ngraph::Shape{shapes[0].size()}, shapes[0]);
auto reshape2 = std::make_shared<ngraph::op::v1::Reshape>(relu, reshape_pattern2, false);
function = std::make_shared<ngraph::Function>(reshape2, input, "EltwiseReshapeActivation");
}
} // namespace SubgraphTestsDefinitions