[GNA] Fix offset and size computation for Crop (#13400)

Fix GetCropParams
    Add test to reproduce crop isue from ticket
    Use convolution in the test
    Cleanup get dim getters using backoffset
This commit is contained in:
Krzysztof Bruniecki
2022-10-28 08:46:19 +02:00
committed by GitHub
parent cc1dd0bf1a
commit fdd047edb9
12 changed files with 314 additions and 126 deletions

View File

@@ -10,6 +10,7 @@
#include "backend/gna_types.h"
#include "quantization.hpp"
#include "weights_converter.hpp"
#include "gna_graph_tools.hpp"
namespace GNAPluginNS {
@@ -192,7 +193,7 @@ static size_t GetBiasSizeForLayer(InferenceEngine::WeightableLayer& wl) {
return wl._biases->size();
} else if (LayerInfo(wl).isConvolution()) {
// calculating biases len using outdata dims: biases number should be equal to output channels number
size_t size = InferenceEngine::GetDataDimSize(wl.outData.front(), InferenceEngine::DataDimName::C);
size_t size = InferenceEngine::GetDataDimByName(wl.outData.front(), InferenceEngine::DataDimName::C);
return size;
} else {
// calculating biases size using outData dimensions

View File

@@ -1264,7 +1264,7 @@ class ScaleFactorPerLayer<InferenceEngine::WeightableLayer*> {
double weights_reducer = 1.0;
auto conv = dynamic_cast<InferenceEngine::ConvolutionLayer *>(wl);
if (conv && !LayerInfo(conv).isConvolutionFilter()) {
const auto inDepth = GetDataDimSize(conv->insData.front().lock(), InferenceEngine::DataDimName::C);
const auto inDepth = InferenceEngine::GetDataDimByName(conv->insData.front().lock(), InferenceEngine::DataDimName::C);
weights_reducer = GNAConvolutionLayer::getWeightsReducer(*conv);
weights_reducer *= MAX_VAL_2B_FEAT * scaleRange * inDepth / std::numeric_limits<int32_t>::max();
weights_reducer = std::max(1.0, weights_reducer);

View File

@@ -312,15 +312,15 @@ void GNAGraphCompiler::ConvolutionPrimitive(InferenceEngine::CNNLayerPtr layer)
const auto outputs = layer->outData.front();
assertConvolutionLayoutProper(inputs);
const auto in_batch = GetDataDimSize(inputs, InferenceEngine::DataDimName::N);
const auto in_channels = GetDataDimSize(inputs, InferenceEngine::DataDimName::C);
auto in_height = GetDataDimSize(inputs, InferenceEngine::DataDimName::H);
auto in_width = GetDataDimSize(inputs, InferenceEngine::DataDimName::W);
const auto in_batch = InferenceEngine::GetDataDimByName(inputs, InferenceEngine::DataDimName::N);
const auto in_channels = InferenceEngine::GetDataDimByName(inputs, InferenceEngine::DataDimName::C);
auto in_height = InferenceEngine::GetDataDimByName(inputs, InferenceEngine::DataDimName::H);
auto in_width = InferenceEngine::GetDataDimByName(inputs, InferenceEngine::DataDimName::W);
const auto out_batch = GetDataDimSize(outputs, InferenceEngine::DataDimName::N);
const auto out_channels = GetDataDimSize(outputs, InferenceEngine::DataDimName::C);
auto out_height = GetDataDimSize(outputs, InferenceEngine::DataDimName::H);
auto out_width = GetDataDimSize(outputs, InferenceEngine::DataDimName::W);
const auto out_batch = InferenceEngine::GetDataDimByName(outputs, InferenceEngine::DataDimName::N);
const auto out_channels = InferenceEngine::GetDataDimByName(outputs, InferenceEngine::DataDimName::C);
auto out_height = InferenceEngine::GetDataDimByName(outputs, InferenceEngine::DataDimName::H);
auto out_width = InferenceEngine::GetDataDimByName(outputs, InferenceEngine::DataDimName::W);
if (in_height > 1 && in_width == 1) {
std::swap(in_height, in_width);
@@ -906,13 +906,13 @@ void GNAGraphCompiler::PoolingPrimitive(InferenceEngine::CNNLayerPtr layer) {
auto inputs = layer->insData.begin()->lock();
auto outputs = *layer->outData.begin();
uint32_t w_dim_in = GetDataDimSize(inputs, InferenceEngine::DataDimName::W);
uint32_t h_dim_in = GetDataDimSize(inputs, InferenceEngine::DataDimName::H);
const uint32_t c_dim_in = GetDataDimSize(inputs, InferenceEngine::DataDimName::C);
uint32_t w_dim_in = InferenceEngine::GetDataDimByName(inputs, InferenceEngine::DataDimName::W);
uint32_t h_dim_in = InferenceEngine::GetDataDimByName(inputs, InferenceEngine::DataDimName::H);
const uint32_t c_dim_in = InferenceEngine::GetDataDimByName(inputs, InferenceEngine::DataDimName::C);
uint32_t w_dim_out = GetDataDimSize(outputs, InferenceEngine::DataDimName::W);
uint32_t h_dim_out = GetDataDimSize(outputs, InferenceEngine::DataDimName::H);
const uint32_t c_dim_out = GetDataDimSize(outputs, InferenceEngine::DataDimName::C);
uint32_t w_dim_out = InferenceEngine::GetDataDimByName(outputs, InferenceEngine::DataDimName::W);
uint32_t h_dim_out = InferenceEngine::GetDataDimByName(outputs, InferenceEngine::DataDimName::H);
const uint32_t c_dim_out = InferenceEngine::GetDataDimByName(outputs, InferenceEngine::DataDimName::C);
if (w_dim_in == 1) { // swap dimensions if needed to support swapped 1D case
swap(h_dim_in, w_dim_in);
@@ -1142,11 +1142,9 @@ void GNAGraphCompiler::CropPrimitive(InferenceEngine::CNNLayerPtr layer) {
IE_ASSERT(!layer->insData.empty());
auto inputs = layer->insData.begin()->lock();
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();
const auto crop_params = GetCropParams(cropLayer);
size_t cropOffsetBytes = crop_params.start_offset * cropLayer->precision.size();
size_t cropOutputSizeBytes = crop_params.crop_size * cropLayer->precision.size();
if (!LayerInfo(cropLayer).isCropAffined()) {
// leave crop as it is
@@ -1175,11 +1173,6 @@ void GNAGraphCompiler::CropPrimitive(InferenceEngine::CNNLayerPtr layer) {
IE_ASSERT(!layer->outData.empty());
auto outputs = *layer->outData.begin();
// only 1D crops supported
if (axis.size() != 1) {
THROW_GNA_EXCEPTION << "only 1D crop layer supported: " << cropLayer->name;
}
// TODO: add unit tests for 4d crops blobs
uint32_t num_rows_in = InferenceEngine::details::product(begin(inputs->getDims()), end(inputs->getDims()));
uint32_t num_columns_in = 1;
@@ -1222,7 +1215,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, cropOffset, (quantized == nullptr) ? false : true);
FillWeightOfAligningFilter(layer, ptr_weights, crop_params.start_offset, (quantized == nullptr) ? false : true);
(quantized == nullptr) ?
gnamem->getQueue(REGION_RO)->push_value(layer, ptr_biases, 0.0f, num_rows_out, 64) :
@@ -1297,16 +1290,16 @@ void GNAGraphCompiler::EltwisePrimitive(InferenceEngine::CNNLayerPtr layer) {
auto outputs = *layer->outData.begin();
auto in_4b_batch = GetDataDimSize(inputs4Bytes, InferenceEngine::DataDimName::N);
auto in_4b_channels = GetDataDimSize(inputs4Bytes, InferenceEngine::DataDimName::C);
auto in_4b_height = GetDataDimSize(inputs4Bytes, InferenceEngine::DataDimName::H);
auto in_4b_width = GetDataDimSize(inputs4Bytes, InferenceEngine::DataDimName::W);
auto in_4b_batch = InferenceEngine::GetDataDimByName(inputs4Bytes, InferenceEngine::DataDimName::N);
auto in_4b_channels = InferenceEngine::GetDataDimByName(inputs4Bytes, InferenceEngine::DataDimName::C);
auto in_4b_height = InferenceEngine::GetDataDimByName(inputs4Bytes, InferenceEngine::DataDimName::H);
auto in_4b_width = InferenceEngine::GetDataDimByName(inputs4Bytes, InferenceEngine::DataDimName::W);
auto in_4b_total_size = in_4b_batch * in_4b_channels * in_4b_height * in_4b_width;
auto in_2b_batch = GetDataDimSize(inputs2Bytes, InferenceEngine::DataDimName::N);
auto in_2b_channels = GetDataDimSize(inputs2Bytes, InferenceEngine::DataDimName::C);
auto in_2b_height = GetDataDimSize(inputs2Bytes, InferenceEngine::DataDimName::H);
auto in_2b_width = GetDataDimSize(inputs2Bytes, InferenceEngine::DataDimName::W);
auto in_2b_batch = InferenceEngine::GetDataDimByName(inputs2Bytes, InferenceEngine::DataDimName::N);
auto in_2b_channels = InferenceEngine::GetDataDimByName(inputs2Bytes, InferenceEngine::DataDimName::C);
auto in_2b_height = InferenceEngine::GetDataDimByName(inputs2Bytes, InferenceEngine::DataDimName::H);
auto in_2b_width = InferenceEngine::GetDataDimByName(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 != in_4b_batch) {
@@ -1428,9 +1421,11 @@ void GNAGraphCompiler::GemmPrimitive(InferenceEngine::CNNLayerPtr layer) {
auto batch_size = (in_dims.size() == 1) ? 1 : in_dims.front();
uint32_t num_rows_in = InferenceEngine::details::product(in_dims) / batch_size;
uint32_t num_columns_in = batch_size;
uint32_t num_rows_out = GetDataDimSize(outputs, 1);
const auto out_dims = outputs->getDims();
const auto out_dims_size = ngraph::shape_size(out_dims);
const auto bytes_per_output = outputs->getPrecision().size();
uint32_t num_rows_out = InferenceEngine::GetDimFromBack(out_dims, 1);
uint32_t num_padding = ALIGN(num_rows_in, noOfInputsDivisor) - num_rows_in;
uint32_t num_padding_out = 0;
// Gemm gets two inputs
void* ptr_input_1 = nullptr; // the first input
@@ -1443,9 +1438,9 @@ void GNAGraphCompiler::GemmPrimitive(InferenceEngine::CNNLayerPtr layer) {
dnn->InitAffineComponent(currentComponent,
num_rows_in + num_padding,
num_columns_in,
num_rows_out + num_padding_out,
num_rows_out,
inputPrecision.size(),
outputs->getPrecision().size(),
bytes_per_output,
quantized == nullptr ? input_2->getPrecision().size() : 2,
quantized == nullptr ? input_2->getPrecision().size() : 4,
GetScaleFactor(layer, QuantizedDataType::weights),
@@ -1456,8 +1451,7 @@ void GNAGraphCompiler::GemmPrimitive(InferenceEngine::CNNLayerPtr layer) {
ptr_biases,
false);
size_t num_data_bytes_out = InferenceEngine::details::product(begin(outputs->getDims()), end(outputs->getDims()))
* outputs->getPrecision().size();
const auto num_data_bytes_out = out_dims_size * bytes_per_output;
size_t num_data_bytes_in_1 = InferenceEngine::details::product(begin(input_1->getDims()), end(input_1->getDims()))
* input_1->getPrecision().size();
@@ -1483,6 +1477,7 @@ void GNAGraphCompiler::AffinePrimitive(InferenceEngine::CNNLayerPtr layer, bool
IE_ASSERT(!layer->outData.empty());
auto inputs = layer->insData.begin()->lock();
auto outputs = *layer->outData.begin();
const auto out_dims = outputs->getDims();
Precision inputPrecision;
uint32_t noOfInputsDivisor = GNALimitations::noOfInputsDivisor;
@@ -1501,7 +1496,7 @@ void GNAGraphCompiler::AffinePrimitive(InferenceEngine::CNNLayerPtr layer, bool
auto batch_size = (in_dims.size() == 1) ? 1 : in_dims.front();
uint32_t num_rows_in = InferenceEngine::details::product(in_dims) / batch_size;
uint32_t num_columns_in = batch_size;
uint32_t num_rows_out = isDiag ? num_rows_in : GetDataDimSize(outputs, 1);
uint32_t num_rows_out = isDiag ? num_rows_in : InferenceEngine::GetDimFromBack(out_dims, 1);
uint32_t num_padding = ALIGN(num_rows_in, noOfInputsDivisor) - num_rows_in;
uint32_t num_padding_out = isDiag ? num_padding : 0;
@@ -1697,8 +1692,8 @@ void GNAGraphCompiler::ConcatAlignFilterPrimitive(InferenceEngine::CNNLayerPtr l
const uint32_t noOfInputsDivisor = gnaFlags->input_low_precision ?
GNALimitations::noOfInputsLowPrecDivisor : GNALimitations::noOfInputsDivisor;
uint32_t num_columns_in = GetDataDimSize(inputs, 2);
uint32_t num_rows_out = GetDataDimSize(outputs, 1);
uint32_t num_columns_in = GetDimFromBack(inputs->getDims(), 2);
uint32_t num_rows_out = GetDimFromBack(outputs->getDims(), 1);
uint32_t num_rows_in = filterLayer->_weights->size() / num_rows_out;
uint32_t num_padding = ALIGN(num_rows_in, noOfInputsDivisor) - num_rows_in;
@@ -1929,10 +1924,10 @@ void GNAGraphCompiler::PWLPrimitive(InferenceEngine::CNNLayerPtr layer) {
auto orientation = kDnnInterleavedOrientation;
uint32_t w_dim_in = GetDataDimSize(inputs, DataDimName::W);
uint32_t h_dim_in = GetDataDimSize(inputs, DataDimName::H);
uint32_t c_dim_in = GetDataDimSize(inputs, DataDimName::C);
uint32_t n_dim_in = GetDataDimSize(inputs, DataDimName::N);
uint32_t w_dim_in = GetDataDimByName(inputs, DataDimName::W);
uint32_t h_dim_in = GetDataDimByName(inputs, DataDimName::H);
uint32_t c_dim_in = GetDataDimByName(inputs, DataDimName::C);
uint32_t n_dim_in = GetDataDimByName(inputs, DataDimName::N);
num_columns = n_dim_in;
num_rows = w_dim_in * h_dim_in * c_dim_in;

View File

@@ -128,8 +128,10 @@ inline std::pair<InferenceEngine::CNNLayerPtr, InferenceEngine::CNNLayerPtr> Fin
// Check if reshape is expected for this pattern:
// the next layer has the both, height and width dimensions > 1
IE_ASSERT(in_dims_size == 3 || in_dims_size == 4);
size_t height = in_dims_size == 3 ? 1 : GetDataDimSize(next->insData[0].lock(), InferenceEngine::DataDimName::H);
size_t width = GetDataDimSize(next->insData[0].lock(), InferenceEngine::DataDimName::W);
size_t height = in_dims_size == 3 ? 1
: InferenceEngine::GetDataDimByName(next->insData[0].lock(),
InferenceEngine::DataDimName::H);
size_t width = InferenceEngine::GetDataDimByName(next->insData[0].lock(), InferenceEngine::DataDimName::W);
if (out_dims_size < 3 || height != 1 || width != 1) {
return std::make_pair(nullptr, nullptr);
}
@@ -178,11 +180,12 @@ inline std::pair<InferenceEngine::CNNLayerPtr, InferenceEngine::CNNLayerPtr> Fin
// Check if reshape is expected for this pattern:
// the previous layer has number of channels > 1 and one of height/width dimensions is also > 1
in_dims_size = parent->insData[0].lock()->getDims().size();
out_dims_size = parent->outData[0]->getDims().size();
const auto out_dims = parent->outData[0]->getDims();
out_dims_size = out_dims.size();
IE_ASSERT(out_dims_size == 3 || out_dims_size == 4);
size_t channels = GetDataDimSize(parent->outData[0], static_cast<uint32_t>(out_dims_size - 1));
size_t height = out_dims_size == 3 ? 1 : GetDataDimSize(parent->outData[0], InferenceEngine::DataDimName::H);
size_t width = GetDataDimSize(parent->outData[0], static_cast<uint32_t>(InferenceEngine::DataDimName::W));
size_t channels = InferenceEngine::GetDimFromFront(out_dims, 1);
size_t height = out_dims_size == 3 ? 1 : InferenceEngine::GetDataDimByName(parent->outData[0], InferenceEngine::DataDimName::H);
size_t width = InferenceEngine::GetDimFromBack(out_dims, 3);
if (in_dims_size < 3 || channels != 1 && (height != 1 || width != 1)) {
return std::make_pair(nullptr, nullptr);
}
@@ -259,9 +262,9 @@ inline std::vector<TranspositionInfo> FindTranspositionInfoFromPrevLayers(Infere
std::function<std::vector<TranspositionInfo>(InferenceEngine::CNNLayerPtr)> findTranspositionInfoRecursive =
[&findTranspositionInfoRecursive](InferenceEngine::CNNLayerPtr layer) -> std::vector<TranspositionInfo> {
auto getTransposeInfoFromData = [](InferenceEngine::DataPtr data, bool transpose = true) {
auto rows = InferenceEngine::GetDataDimSize(data, InferenceEngine::DataDimName::C);
auto columns = InferenceEngine::GetDataDimSize(data, InferenceEngine::DataDimName::H) *
InferenceEngine::GetDataDimSize(data, InferenceEngine::DataDimName::W);
auto rows = InferenceEngine::GetDataDimByName(data, InferenceEngine::DataDimName::C);
auto columns = InferenceEngine::GetDataDimByName(data, InferenceEngine::DataDimName::H) *
InferenceEngine::GetDataDimByName(data, InferenceEngine::DataDimName::W);
return std::vector<TranspositionInfo>{{transpose, rows, columns}};
};
if (LayerInfo(layer).isConvolution() || LayerInfo(layer).isPooling()) {
@@ -355,9 +358,9 @@ inline std::vector<TranspositionInfo> FindTranspositionInfoFromNextLayers(Infere
std::function<std::vector<TranspositionInfo>(InferenceEngine::CNNLayerPtr)> findTranspositionInfoRecursive =
[&findTranspositionInfoRecursive](InferenceEngine::CNNLayerPtr layer) -> std::vector<TranspositionInfo> {
if (LayerInfo(layer).isConvolution()) {
auto rows = InferenceEngine::GetDataDimSize(layer->input(), InferenceEngine::DataDimName::C);
auto columns = InferenceEngine::GetDataDimSize(layer->input(), InferenceEngine::DataDimName::H) *
InferenceEngine::GetDataDimSize(layer->input(), InferenceEngine::DataDimName::W);
auto rows = InferenceEngine::GetDataDimByName(layer->input(), InferenceEngine::DataDimName::C);
auto columns = InferenceEngine::GetDataDimByName(layer->input(), InferenceEngine::DataDimName::H) *
InferenceEngine::GetDataDimByName(layer->input(), InferenceEngine::DataDimName::W);
return {{true, rows, columns}};
}

View File

@@ -776,14 +776,25 @@ inline void CNNNetworkReconnectLayer(CNNLayerPtr old_prev_layer, CNNLayerPtr new
}
}
inline uint32_t GetDimFromFront(const InferenceEngine::SizeVector& dims, uint32_t dim) {
if (dim >= dims.size()) {
return 1;
}
return static_cast<uint32_t>(dims[dim]);
}
/**
* @brief returns a size of a specified data dimension depending on its back offset
* @param data a pointer to the data
* @brief returns a specified dimension depending on its back offset
* @param dims vector of dimensions
* @param backOffset back dimension offset
*/
inline uint32_t GetDataDimSize(InferenceEngine::DataPtr data, uint32_t backOffset) {
auto dims = data->getDims();
return (dims.size() > backOffset - 1) ? static_cast<uint32_t>(dims[dims.size() - backOffset]) : uint32_t(1);
inline uint32_t GetDimFromBack(const InferenceEngine::SizeVector& dims, const uint32_t backOffset) {
if (backOffset > dims.size()) {
return 1;
}
const auto indexFromFront = dims.size() - backOffset;
return GetDimFromFront(dims, indexFromFront);
}
enum class DataDimName {
@@ -795,7 +806,7 @@ enum class DataDimName {
* @param data a pointer to the data
* @param dimName dimension name
*/
inline uint32_t GetDataDimSize(InferenceEngine::DataPtr data, DataDimName dimName) {
inline uint32_t GetDataDimByName(InferenceEngine::DataPtr data, DataDimName dimName) {
uint32_t dimIxInNCHW = static_cast<uint32_t>(dimName);
IE_ASSERT(dimIxInNCHW <= 3);
@@ -819,7 +830,8 @@ inline uint32_t GetDataDimSize(InferenceEngine::DataPtr data, DataDimName dimNam
default:
THROW_GNA_EXCEPTION << data->getName() << " Unexpected layout " << data->getLayout();
}
return GetDataDimSize(data, backOffsets[dimIxInNCHW]);
auto dims = data->getDims();
return GetDimFromBack(dims, backOffsets[dimIxInNCHW]);
}
} // namespace InferenceEngine

View File

@@ -40,9 +40,11 @@ double getWeightsReducer(InferenceEngine::ConvolutionLayer& conv) {
// for kernelSize in {7, 8} -> 1.2
const std::vector< KRT > reducers{ {49, 3.0}, {36, 2.6}, {21, 2.3}, {14, 1.7}, {9, 1.3}, {7, 1.2} };
auto reducer = 1.0;
const auto inDepth = GetDataDimSize(conv.insData.front().lock(), InferenceEngine::DataDimName::C);
const auto inHeight = GetDataDimSize(conv.insData.front().lock(), InferenceEngine::DataDimName::H);
const auto inWidth = GetDataDimSize(conv.insData.front().lock(), InferenceEngine::DataDimName::W);
const auto inDepth = InferenceEngine::GetDataDimByName(conv.insData.front().lock(), InferenceEngine::DataDimName::C);
const auto inHeight =
InferenceEngine::GetDataDimByName(conv.insData.front().lock(), InferenceEngine::DataDimName::H);
const auto inWidth =
InferenceEngine::GetDataDimByName(conv.insData.front().lock(), InferenceEngine::DataDimName::W);
if (isConv2D(inHeight, inWidth, inDepth, conv._kernel_y, conv._kernel_x) &&
!isMappableFrom2DTo1D(inHeight, inWidth, inDepth, conv._kernel_y, conv._kernel_x, conv._stride_y, conv._stride_x)) {
const auto kernelSize = conv._kernel_x * conv._kernel_y;

View File

@@ -0,0 +1,58 @@
// Copyright (C) 2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "gna_crop_layer.hpp"
#include "../gna_plugin_log.hpp"
#include <vector>
namespace GNAPluginNS {
SimpleCrop get_crop_params(const std::vector<int32_t>& axis_in,
const std::vector<int32_t>& offset_in,
const std::vector<int32_t>& dim_in,
const std::vector<size_t>& input_dims) {
const auto total_size_to_crop = ov::shape_size(input_dims);
SimpleCrop ret{0, total_size_to_crop};
auto crop_axis_detected = false;
auto cropped_dim_size = total_size_to_crop;
for (int n = 0; n < axis_in.size(); n++) {
const auto axis = axis_in[n];
if (axis < 0 || axis >= input_dims.size()) {
gnawarn() << "Crop axis outside of input shape size detected.\n";
continue;
}
const auto input_dim = input_dims[axis];
// Skip axis that is untouched
if (offset_in[n] == 0 && dim_in[n] == input_dim) {
continue;
}
if (crop_axis_detected) {
THROW_GNA_EXCEPTION
<< "Crop layer does not support the number of (non-trivial) cropped dimensions more than 1.";
}
crop_axis_detected = true;
ret.crop_size = dim_in[n];
ret.start_offset = offset_in[n];
cropped_dim_size = input_dim;
}
if (crop_axis_detected) {
ret.start_offset *= (total_size_to_crop / cropped_dim_size);
ret.crop_size *= (total_size_to_crop / cropped_dim_size);
}
return ret;
}
SimpleCrop GetCropParams(InferenceEngine::CropLayer* cropLayer) {
auto input_dims = cropLayer->insData.begin()->lock()->getDims();
const auto out_val = get_crop_params(cropLayer->axis, cropLayer->offset, cropLayer->dim, input_dims);
return out_val;
}
} // namespace GNAPluginNS

View File

@@ -5,7 +5,8 @@
#pragma once
#include <legacy/ie_layers.h>
#include "gna_graph_tools.hpp"
#include <cstdint>
#include <vector>
namespace GNAPluginNS {
class GNACropLayer {
@@ -24,44 +25,20 @@ public:
void *gna_ptr = nullptr;
};
struct SimpleCrop {
size_t start_offset;
size_t crop_size;
};
/**
* @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());
SimpleCrop get_crop_params(const std::vector<int32_t>& axis_in,
const std::vector<int32_t>& offset_in,
const std::vector<int32_t>& dim_in,
const std::vector<size_t>& input_dims);
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);
}
SimpleCrop GetCropParams(InferenceEngine::CropLayer* cropLayer);
} // namespace GNAPluginNS

View File

@@ -344,9 +344,8 @@ class LayerInfo {
bool isCropAffined() const noexcept {
auto cropLayer = dynamic_cast<InferenceEngine::CropLayer *> (layer);
if (cropLayer != nullptr && !cropLayer->offset.empty()) {
size_t offset;
std::tie(offset, std::ignore, std::ignore) = GetCropParams(cropLayer);
return GNAPluginNS::GNALimitations::isCropAffinedOffset(offset);
const auto crop_params = GetCropParams(cropLayer);
return GNAPluginNS::GNALimitations::isCropAffinedOffset(crop_params.start_offset);
}
return false;
}

View File

@@ -2414,8 +2414,9 @@ void TransposeWeightsFromNCHWToNHWCPass::run() {
// Transpose all constant inputs
for (auto && input : constInputs) {
auto rows = GetDataDimSize(input->outData[0], DataDimName::C);
auto columns = GetDataDimSize(input->outData[0], DataDimName::H) * GetDataDimSize(input->outData[0], DataDimName::W);
auto rows = GetDataDimByName(input->outData[0], DataDimName::C);
auto columns = GetDataDimByName(input->outData[0], DataDimName::H) *
GetDataDimByName(input->outData[0], DataDimName::W);
auto blob = convertToRWBlob(input->blobs["custom"]);
input->blobs["custom"] = blob;

View File

@@ -0,0 +1,145 @@
// Copyright (C) 2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <vector>
#include <memory>
#include <tuple>
#include <vector>
#include <string>
#include <ie_core.hpp>
#include "common_test_utils/common_utils.hpp"
#include "functional_test_utils/plugin_cache.hpp"
#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"
#include "ngraph_functions/pass/convert_prc.hpp"
typedef std::tuple<
InferenceEngine::Precision, // Network Precision
std::string, // Target Device
std::map<std::string, std::string>, // Configuration
std::vector<size_t> // input shape
> cccmParams;
namespace LayerTestsDefinitions {
class CropAfterConvolutionTest : public testing::WithParamInterface<cccmParams>,
public LayerTestsUtils::LayerTestsCommon {
public:
static std::string getTestCaseName(testing::TestParamInfo<cccmParams> obj) {
InferenceEngine::Precision netPrecision;
std::string targetDevice;
std::map<std::string, std::string> configuration;
std::vector<size_t> cropInputShape;
std::tie(netPrecision, targetDevice, configuration, cropInputShape) = obj.param;
std::ostringstream result;
result << "netPRC=" << netPrecision.name() << "_";
result << "targetDevice=" << targetDevice << "_";
for (auto const& configItem : configuration) {
result << "_configItem=" << configItem.first << "_" << configItem.second;
}
result << "_CIS=" << CommonTestUtils::vec2str(cropInputShape);
return result.str();
}
protected:
void SetUp() override {
InferenceEngine::Precision netPrecision;
std::vector<size_t> inputShape;
std::tie(netPrecision, targetDevice, configuration, inputShape) = this->GetParam();
auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision);
auto reshape_pattern_size = ngraph::Shape{inputShape.size()};
auto reshape_pattern = ngraph::builder::makeConstant(ov::element::i64, reshape_pattern_size, inputShape);
auto params = ngraph::builder::makeParams(ngPrc, {inputShape});
auto input_reshape = std::make_shared<ngraph::opset9::Reshape>(params[0], reshape_pattern, false);
const std::vector<size_t> filterSize{1, 1};
const std::vector<size_t> strides{1, 1};
const std::vector<ptrdiff_t> padsBegin{0, 0};
const std::vector<ptrdiff_t> padsEnd{0, 0};
const std::vector<size_t> dilations{1, 1};
const auto pad_type = ngraph::op::PadType::EXPLICIT;
const size_t numOutChannels = 8;
constexpr auto c_index_in_nchw = 1;
constexpr auto h_index_in_nchw = 2;
const auto weights_size = ngraph::shape_size(filterSize) * numOutChannels * inputShape[c_index_in_nchw];
auto weights_values = CommonTestUtils::generate_float_numbers(weights_size, -0.2f, 0.2f);
const auto weights2_size = ngraph::shape_size(filterSize) * numOutChannels * numOutChannels;
auto weights2_values = CommonTestUtils::generate_float_numbers(weights2_size, -0.2f, 0.2f);
auto convolution_node = ngraph::builder::makeConvolution(input_reshape,
ngPrc,
filterSize,
strides,
padsBegin,
padsEnd,
dilations,
pad_type,
numOutChannels,
false,
weights_values);
const std::vector<int64_t> crop_begin{4};
const std::vector<int64_t> crop_end{20};
const std::vector<int64_t> crop_stride{1};
const std::vector<int64_t> axes{h_index_in_nchw};
auto split_node =
ngraph::builder::makeSlice(convolution_node, crop_begin, crop_end, crop_stride, axes, ngPrc);
auto convolution_node2 = ngraph::builder::makeConvolution(split_node,
ngPrc,
filterSize,
strides,
padsBegin,
padsEnd,
dilations,
pad_type,
numOutChannels,
false,
weights2_values);
ngraph::ResultVector results{std::make_shared<ngraph::opset9::Result>(convolution_node2)};
function = std::make_shared<ngraph::Function>(results, params, "CropAfterConvolutionTest");
}
};
TEST_P(CropAfterConvolutionTest, CompareWithRefImpl) {
Run();
};
const std::vector<InferenceEngine::Precision> netPrecisions = {
InferenceEngine::Precision::FP16,
InferenceEngine::Precision::FP32,
};
const std::vector<std::map<std::string, std::string>> configs = {
{
{"GNA_DEVICE_MODE", "GNA_SW_EXACT"}
},
{
{"GNA_DEVICE_MODE", "GNA_SW_FP32"}
}
};
const std::vector<std::vector<size_t>> input_shapes {
{1, 8, 32, 16},
{1, 16, 32, 16},
{1, 8, 128, 32},
{1, 16, 32, 32},
};
INSTANTIATE_TEST_SUITE_P(smoke_crop_after_conv, CropAfterConvolutionTest,
::testing::Combine(
::testing::ValuesIn(netPrecisions),
::testing::Values(CommonTestUtils::DEVICE_GNA),
::testing::ValuesIn(configs),
::testing::ValuesIn(input_shapes)),
CropAfterConvolutionTest::getTestCaseName);
} // namespace LayerTestsDefinitions

View File

@@ -18,17 +18,16 @@ typedef std::tuple<
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
size_t // Output size in flatten data
> 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}}
{{8, 16}, {1, 16}, {0, 1}, {1, 0}, 16, 16},
{{5, 24}, {1, 24}, {0, 1}, {2, 0}, 48, 24},
{{8, 16}, {2, 16}, {0, 1}, {1, 0}, 16, 32},
{{1, 16}, {1, 8}, {0, 1}, {0, 5}, 5, 8 },
{{1, 8, 16}, {1, 1, 16}, {0, 1, 2}, {0, 1, 0}, 16, 16},
{{1, 1, 8, 16}, {1, 1, 1, 16}, {0, 1, 2, 3}, {0, 0, 1, 0}, 16, 16}
};
TEST(GetCropParamsTest, testGetCropParams) {
@@ -37,8 +36,7 @@ TEST(GetCropParamsTest, testGetCropParams) {
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;
std::tie(in_shape, orig_out_shape, orig_axes, orig_offset, result_offset, result_out_size) = 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);
@@ -48,12 +46,9 @@ TEST(GetCropParamsTest, testGetCropParams) {
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);
const auto results = GNAPluginNS::GetCropParams(crop_layer.get());
ASSERT_EQ(results.start_offset, result_offset);
ASSERT_EQ(results.crop_size, result_out_size);
}
}