[GNA] Fixed handling of unaligned crop layer (#11316)
This commit is contained in:
@@ -1053,38 +1053,11 @@ void GNAGraphCompiler::CropPrimitive(InferenceEngine::CNNLayerPtr layer) {
|
||||
IE_ASSERT(!layer->insData.empty());
|
||||
auto inputs = layer->insData.begin()->lock();
|
||||
|
||||
IE_ASSERT(!cropLayer->axis.empty());
|
||||
IE_ASSERT(cropLayer->axis.size() == cropLayer->dim.size());
|
||||
IE_ASSERT(cropLayer->axis.size() == cropLayer->offset.size());
|
||||
|
||||
std::vector<int> axis, dim, offset;
|
||||
for (int n = 0; n < cropLayer->axis.size(); n++) {
|
||||
uint32_t input_dim = GetDataDimSize(inputs, inputs->getDims().size() - cropLayer->axis[n]);
|
||||
// Exclude crop layer components that do nothing
|
||||
if (cropLayer->offset[n] == 0 && cropLayer->dim[n] == input_dim) {
|
||||
continue;
|
||||
}
|
||||
axis.push_back(cropLayer->axis[n]);
|
||||
dim.push_back(cropLayer->dim[n]);
|
||||
offset.push_back(cropLayer->offset[n]);
|
||||
}
|
||||
|
||||
if (axis.size() != 1) {
|
||||
THROW_GNA_EXCEPTION <<
|
||||
"Crop layer does not support the number of (non-trivial) cropped dimensions more than 1, provided: "
|
||||
<< axis.size() << ".";
|
||||
}
|
||||
|
||||
size_t cropOffset = offset.front() * cropLayer->precision.size();
|
||||
size_t cropOutputSize = dim.front() * cropLayer->precision.size();
|
||||
const uint32_t noOfInputsDivisor = gnaFlags->input_low_precision ?
|
||||
GNALimitations::noOfInputsLowPrecDivisor : GNALimitations::noOfInputsDivisor;
|
||||
|
||||
// fix for crop on tensor dim > 2D
|
||||
for (int n = axis[0]+1; n < cropLayer->dim.size(); n++) {
|
||||
cropOffset *= cropLayer->dim[n];
|
||||
cropOutputSize *= cropLayer->dim[n];
|
||||
}
|
||||
size_t cropOffset, cropOutputSize;
|
||||
std::vector<int32_t> axis;
|
||||
std::tie(cropOffset, cropOutputSize, axis) = GetCropParams(cropLayer);
|
||||
size_t cropOffsetBytes = cropOffset * cropLayer->precision.size();
|
||||
size_t cropOutputSizeBytes = cropOutputSize * cropLayer->precision.size();
|
||||
|
||||
if (!LayerInfo(cropLayer).isCropAffined()) {
|
||||
// leave crop as it is
|
||||
@@ -1099,13 +1072,13 @@ void GNAGraphCompiler::CropPrimitive(InferenceEngine::CNNLayerPtr layer) {
|
||||
}
|
||||
|
||||
// calculate index idx for connectInput last parameter
|
||||
connectInput(layer, &cropLayerInfo->second.gna_ptr, cropOutputSize + cropOffset, cropOffset, 0);
|
||||
connectInput(layer, &cropLayerInfo->second.gna_ptr, cropOutputSizeBytes + cropOffsetBytes, cropOffsetBytes, 0);
|
||||
|
||||
// cases for certain output layers
|
||||
for (auto&& outLayer : getInputTo(layer->outData.front())) {
|
||||
auto& nextLayer = outLayer.second;
|
||||
if (LayerInfo(nextLayer).isConcat()) {
|
||||
connectOutput(layer, &cropLayerInfo->second.gna_ptr, cropOutputSize);
|
||||
connectOutput(layer, &cropLayerInfo->second.gna_ptr, cropOutputSizeBytes);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -1119,10 +1092,12 @@ void GNAGraphCompiler::CropPrimitive(InferenceEngine::CNNLayerPtr layer) {
|
||||
}
|
||||
|
||||
// TODO: add unit tests for 4d crops blobs
|
||||
uint32_t num_rows_in = GetDataDimSize(inputs, inputs->getDims().size() - axis.front());
|
||||
uint32_t num_rows_in = InferenceEngine::details::product(begin(inputs->getDims()), end(inputs->getDims()));
|
||||
uint32_t num_columns_in = 1;
|
||||
|
||||
uint32_t num_rows_out = GetDataDimSize(outputs, inputs->getDims().size() - axis.front());
|
||||
uint32_t num_rows_out = InferenceEngine::details::product(begin(outputs->getDims()), end(outputs->getDims()));
|
||||
const uint32_t noOfInputsDivisor = gnaFlags->input_low_precision ?
|
||||
GNALimitations::noOfInputsLowPrecDivisor : GNALimitations::noOfInputsDivisor;
|
||||
uint32_t num_padding = ALIGN(num_rows_in, noOfInputsDivisor) - num_rows_in;
|
||||
|
||||
void* ptr_inputs = nullptr;
|
||||
@@ -1158,7 +1133,7 @@ void GNAGraphCompiler::CropPrimitive(InferenceEngine::CNNLayerPtr layer) {
|
||||
connectInput(layer, ptr_inputs, num_data_bytes_in, 0, 0);
|
||||
connectOutput(layer, ptr_outputs, num_data_bytes_out);
|
||||
|
||||
FillWeightOfAligningFilter(layer, ptr_weights, offset.front(), (quantized == nullptr) ? false : true);
|
||||
FillWeightOfAligningFilter(layer, ptr_weights, cropOffset, (quantized == nullptr) ? false : true);
|
||||
|
||||
(quantized == nullptr) ?
|
||||
gnamem->readonly().push_value(layer, ptr_biases, 0.0f, num_rows_out, 64) :
|
||||
@@ -1589,8 +1564,8 @@ void GNAGraphCompiler::FillWeightOfAligningFilter(InferenceEngine::CNNLayerPtr l
|
||||
auto outputs = *layer->outData.begin();
|
||||
auto inputs = layer->insData.begin()->lock();
|
||||
|
||||
uint32_t num_rows_in = InferenceEngine::details::product(++begin(inputs->getDims()), end(inputs->getDims()));
|
||||
uint32_t num_rows_out = InferenceEngine::details::product(++begin(outputs->getDims()), end(outputs->getDims()));
|
||||
uint32_t num_rows_in = InferenceEngine::details::product(begin(inputs->getDims()), end(inputs->getDims()));
|
||||
uint32_t num_rows_out = InferenceEngine::details::product(begin(outputs->getDims()), end(outputs->getDims()));
|
||||
|
||||
if (!ptrWeights) {
|
||||
THROW_GNA_EXCEPTION << "Weights memory is not allocated!!!";
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <legacy/ie_layers.h>
|
||||
#include "gna_graph_tools.hpp"
|
||||
|
||||
namespace GNAPluginNS {
|
||||
class GNACropLayer {
|
||||
@@ -16,9 +17,51 @@ public:
|
||||
{}
|
||||
|
||||
InferenceEngine::CNNLayerPtr getCrop() { return cropLayer; }
|
||||
|
||||
/**
|
||||
* pointer to gna croped memory beginning
|
||||
*/
|
||||
void *gna_ptr = nullptr;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief returns parameters extracted from Crop layer: elements offset, elements output size and axes
|
||||
* @param cropLayer pointer to a Crop layer
|
||||
*/
|
||||
inline std::tuple<size_t, size_t, std::vector<int32_t>> GetCropParams(InferenceEngine::CropLayer* cropLayer) {
|
||||
IE_ASSERT(!cropLayer->axis.empty());
|
||||
IE_ASSERT(cropLayer->axis.size() == cropLayer->dim.size());
|
||||
IE_ASSERT(cropLayer->axis.size() == cropLayer->offset.size());
|
||||
|
||||
std::vector<int> axis, dim, offset;
|
||||
auto inputs = cropLayer->insData.begin()->lock();
|
||||
for (int n = 0; n < cropLayer->axis.size(); n++) {
|
||||
uint32_t input_dim = GetDataDimSize(inputs, inputs->getDims().size() - cropLayer->axis[n]);
|
||||
// Exclude crop layer components that do nothing
|
||||
if (cropLayer->offset[n] == 0 && cropLayer->dim[n] == input_dim) {
|
||||
continue;
|
||||
}
|
||||
axis.push_back(cropLayer->axis[n]);
|
||||
dim.push_back(cropLayer->dim[n]);
|
||||
offset.push_back(cropLayer->offset[n]);
|
||||
}
|
||||
|
||||
if (axis.size() != 1) {
|
||||
THROW_GNA_EXCEPTION <<
|
||||
"Crop layer does not support the number of (non-trivial) cropped dimensions more than 1, provided: "
|
||||
<< axis.size() << ".";
|
||||
}
|
||||
|
||||
size_t cropOffset = offset.front();
|
||||
size_t cropOutputSize = dim.front();
|
||||
|
||||
// fix for crop on tensor dim > 2D
|
||||
for (int n = axis[0]+1; n < cropLayer->dim.size(); n++) {
|
||||
cropOffset *= cropLayer->dim[n];
|
||||
cropOutputSize *= cropLayer->dim[n];
|
||||
}
|
||||
|
||||
return std::make_tuple(cropOffset, cropOutputSize, axis);
|
||||
}
|
||||
|
||||
} // namespace GNAPluginNS
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <legacy/ngraph_ops/power.hpp>
|
||||
#include <ngraph/opsets/opset8.hpp>
|
||||
#include "ops/pwl.hpp"
|
||||
#include "layers/gna_crop_layer.hpp"
|
||||
|
||||
namespace GNAPluginNS {
|
||||
|
||||
@@ -363,8 +364,10 @@ class LayerInfo {
|
||||
// currently crop layer only supports 2 bytes in int16 and int8 mode.
|
||||
// In fp32 mode this is not necessary but is useful for testing
|
||||
auto bytesPerCropElement = 2;
|
||||
size_t cropOffset = cropLayer->offset.back() * bytesPerCropElement;
|
||||
return (ALIGN64(cropOffset) != cropOffset);
|
||||
size_t offset;
|
||||
std::tie(offset, std::ignore, std::ignore) = GetCropParams(cropLayer);
|
||||
size_t bytesOffset = offset * bytesPerCropElement;
|
||||
return (ALIGN64(bytesOffset) != bytesOffset);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
// Copyright (C) 2022 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "common_test_utils/test_constants.hpp"
|
||||
#include "subgraph_tests/stridedslice_concat.hpp"
|
||||
|
||||
using namespace SubgraphTestsDefinitions;
|
||||
|
||||
namespace {
|
||||
const std::vector<InferenceEngine::Precision> netPrecisions = {
|
||||
InferenceEngine::Precision::FP32,
|
||||
InferenceEngine::Precision::FP16
|
||||
};
|
||||
|
||||
const std::vector<std::map<std::string, std::string>> configs = {
|
||||
{
|
||||
{"GNA_DEVICE_MODE", "GNA_SW_EXACT"},
|
||||
}
|
||||
};
|
||||
|
||||
const std::vector<StridedSliceParams> sliceParams = {
|
||||
{{8, 16}, {1, 16}, {2, 16}, {1, 1}, {0, 1}, {0, 1}},
|
||||
{{1, 16}, {1, 1}, {1, 2}, {1, 1}, {1, 0}, {1, 0}},
|
||||
{{1, 8, 16}, {1, 1, 16}, {1, 2, 16}, {1, 1, 1}, {1, 0, 1}, {1, 0, 1}},
|
||||
{{8, 25}, {3, 25}, {4, 25}, {1, 1}, {0, 1}, {0, 1}}
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(smoke_SliceConcatTest, SliceConcatTest,
|
||||
::testing::Combine(
|
||||
::testing::ValuesIn(netPrecisions),
|
||||
::testing::Values(CommonTestUtils::DEVICE_GNA),
|
||||
::testing::ValuesIn(configs),
|
||||
::testing::ValuesIn(sliceParams)),
|
||||
SliceConcatTest::getTestCaseName);
|
||||
} // namespace
|
||||
@@ -0,0 +1,15 @@
|
||||
// Copyright (C) 2022 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "shared_test_classes/subgraph/stridedslice_concat.hpp"
|
||||
|
||||
namespace SubgraphTestsDefinitions {
|
||||
|
||||
TEST_P(SliceConcatTest, CompareWithRefImpl) {
|
||||
Run();
|
||||
};
|
||||
|
||||
} // namespace SubgraphTestsDefinitions
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
// Copyright (C) 2022 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include "shared_test_classes/base/layer_test_utils.hpp"
|
||||
#include "ngraph_functions/builders.hpp"
|
||||
#include "ngraph_functions/utils/ngraph_helpers.hpp"
|
||||
|
||||
namespace SubgraphTestsDefinitions {
|
||||
|
||||
typedef std::tuple<
|
||||
std::vector<int64_t>, // Input shape
|
||||
std::vector<int64_t>, // Begin
|
||||
std::vector<int64_t>, // End
|
||||
std::vector<int64_t>, // Strides
|
||||
std::vector<int64_t>, // Begin mask
|
||||
std::vector<int64_t> // End mask
|
||||
> StridedSliceParams;
|
||||
|
||||
typedef std::tuple<
|
||||
InferenceEngine::Precision, // Network Precision
|
||||
std::string, // Target Device
|
||||
std::map<std::string, std::string>, // Configuration
|
||||
StridedSliceParams // StridedSlice parameters
|
||||
> SliceConcatParams;
|
||||
|
||||
class SliceConcatTest : public testing::WithParamInterface<SliceConcatParams>,
|
||||
virtual public LayerTestsUtils::LayerTestsCommon {
|
||||
public:
|
||||
static std::string getTestCaseName(const testing::TestParamInfo<SliceConcatParams>& obj);
|
||||
|
||||
protected:
|
||||
void SetUp() override;
|
||||
};
|
||||
|
||||
} // namespace SubgraphTestsDefinitions
|
||||
@@ -0,0 +1,66 @@
|
||||
// Copyright (C) 2022 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "shared_test_classes/subgraph/stridedslice_concat.hpp"
|
||||
#include "ngraph_functions/builders.hpp"
|
||||
|
||||
namespace SubgraphTestsDefinitions {
|
||||
|
||||
std::string SliceConcatTest::getTestCaseName(const testing::TestParamInfo<SliceConcatParams>& obj) {
|
||||
InferenceEngine::Precision netPrecision;
|
||||
std::string targetDevice;
|
||||
std::map<std::string, std::string> configuration;
|
||||
StridedSliceParams sliceParams;
|
||||
std::tie(netPrecision, targetDevice, configuration, sliceParams) = obj.param;
|
||||
std::vector<int64_t> inputShape, begin, end, strides, beginMask, endMask;
|
||||
std::tie(inputShape, begin, end, strides, beginMask, endMask) = sliceParams;
|
||||
|
||||
std::ostringstream result;
|
||||
result << "netPRC=" << netPrecision.name() << "_";
|
||||
result << "targetDevice=" << targetDevice;
|
||||
for (auto const& configItem : configuration) {
|
||||
result << "_configItem=" << configItem.first << "_" << configItem.second;
|
||||
}
|
||||
result << "IS=" << CommonTestUtils::vec2str(inputShape) << "_";
|
||||
result << "B=" << CommonTestUtils::vec2str(begin) << "_";
|
||||
result << "E=" << CommonTestUtils::vec2str(end) << "_";
|
||||
result << "S=" << CommonTestUtils::vec2str(strides) << "_";
|
||||
result << "BM=" << CommonTestUtils::vec2str(beginMask) << "_";
|
||||
result << "EM=" << CommonTestUtils::vec2str(endMask) << "_";
|
||||
return result.str();
|
||||
}
|
||||
|
||||
void SliceConcatTest::SetUp() {
|
||||
InferenceEngine::Precision netPrecision;
|
||||
std::map<std::string, std::string> tempConfig;
|
||||
StridedSliceParams sliceParams;
|
||||
std::tie(netPrecision, targetDevice, tempConfig, sliceParams) = this->GetParam();
|
||||
configuration.insert(tempConfig.begin(), tempConfig.end());
|
||||
std::vector<int64_t> inputShape, begin, end, strides, beginMask, endMask;
|
||||
std::tie(inputShape, begin, end, strides, beginMask, endMask) = sliceParams;
|
||||
|
||||
auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision);
|
||||
size_t input_size = std::accumulate(std::begin(inputShape), std::end(inputShape), 1, std::multiplies<size_t>());
|
||||
auto params = ngraph::builder::makeParams(ngPrc, {{1, input_size}});
|
||||
|
||||
ngraph::Output<ngraph::Node> input = params[0];
|
||||
if (inputShape[0] != 1 || inputShape.size() != 2) {
|
||||
input = std::make_shared<ngraph::opset8::Reshape>(params[0],
|
||||
ngraph::builder::makeConstant(ngraph::element::i64, ngraph::Shape{inputShape.size()}, inputShape), false);
|
||||
}
|
||||
|
||||
auto ss = ngraph::builder::makeStridedSlice(input, begin, end, strides, ngPrc, beginMask, endMask,
|
||||
std::vector<int64_t>(inputShape.size(), 0),
|
||||
std::vector<int64_t>(inputShape.size(), 0),
|
||||
std::vector<int64_t>(inputShape.size(), 0));
|
||||
|
||||
ngraph::Shape const_shape(inputShape.size(), 1);
|
||||
const_shape.back() = 32;
|
||||
auto const_input = ngraph::builder::makeConstant(ngPrc, const_shape, std::vector<float>{}, true);
|
||||
auto concat = ngraph::builder::makeConcat({const_input, ss}, inputShape.size() - 1);
|
||||
|
||||
function = std::make_shared<ngraph::Function>(concat, params, "StridedSliceConcatTest");
|
||||
}
|
||||
|
||||
} // namespace SubgraphTestsDefinitions
|
||||
@@ -0,0 +1,60 @@
|
||||
// Copyright (C) 2022 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
// to suppress deprecated definition errors
|
||||
#define IMPLEMENT_INFERENCE_ENGINE_PLUGIN
|
||||
#include <legacy/ie_layers.h>
|
||||
#include <layers/gna_crop_layer.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
typedef std::tuple<
|
||||
std::vector<size_t>, // Input shape
|
||||
std::vector<int>, // Output shape
|
||||
std::vector<int>, // Axes
|
||||
std::vector<int>, // Offset
|
||||
size_t, // Offset in flatten data
|
||||
size_t, // Output size in flatten data
|
||||
std::vector<int> // Axes which arre not skipped
|
||||
> CropParams;
|
||||
|
||||
const std::vector<CropParams> crop_params_vector = {
|
||||
{{8, 16}, {1, 16}, {0, 1}, {1, 0}, 16, 16, {0}},
|
||||
{{5, 24}, {1, 24}, {0, 1}, {2, 0}, 48, 24, {0}},
|
||||
{{8, 16}, {2, 16}, {0, 1}, {1, 0}, 16, 32, {0}},
|
||||
{{1, 16}, {1, 8}, {0, 1}, {0, 5}, 5, 8, {1}},
|
||||
{{1, 8, 16}, {1, 1, 16}, {0, 1, 2}, {0, 1, 0}, 16, 16, {1}},
|
||||
{{1, 1, 8, 16}, {1, 1, 1, 16}, {0, 1, 2, 3}, {0, 0, 1, 0}, 16, 16, {2}}
|
||||
};
|
||||
|
||||
TEST(GetCropParamsTest, testGetCropParams) {
|
||||
InferenceEngine::LayerParams attrs = {"Crop", "Crop", InferenceEngine::Precision::FP32};
|
||||
for (const auto& crop_params : crop_params_vector) {
|
||||
std::vector<size_t> in_shape;
|
||||
std::vector<int> orig_out_shape, orig_axes, orig_offset;
|
||||
size_t result_offset, result_out_size;
|
||||
std::vector<int> result_axes;
|
||||
std::tie(in_shape, orig_out_shape, orig_axes, orig_offset, result_offset, result_out_size, result_axes) = crop_params;
|
||||
|
||||
auto crop_layer = std::make_shared<InferenceEngine::CropLayer>(attrs);
|
||||
auto layout = in_shape.size() == 2 ? InferenceEngine::NC : (in_shape.size() == 3 ? InferenceEngine::CHW : InferenceEngine::NCHW);
|
||||
auto data = std::make_shared<InferenceEngine::Data>("Crop_input",
|
||||
InferenceEngine::TensorDesc(InferenceEngine::Precision::FP32, in_shape, layout));
|
||||
crop_layer->insData.push_back(data);
|
||||
crop_layer->dim = orig_out_shape;
|
||||
crop_layer->axis = orig_axes;
|
||||
crop_layer->offset = orig_offset;
|
||||
size_t offset, out_size;
|
||||
std::vector<int32_t> axis;
|
||||
std::tie(offset, out_size, axis) = GNAPluginNS::GetCropParams(crop_layer.get());
|
||||
ASSERT_EQ(offset, result_offset);
|
||||
ASSERT_EQ(out_size, result_out_size);
|
||||
ASSERT_EQ(axis, result_axes);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
Reference in New Issue
Block a user