* [GNA] Fix pooling output backward compatibility * Apply review
This commit is contained in:
committed by
GitHub
parent
bcc1404c58
commit
feb7814a96
@@ -259,6 +259,38 @@ bool GNAPluginNS::backend::AMIntelDNN::isOperationCnnLegacySpecific(const Gna2Op
|
||||
static_cast<Gna2Shape*>(op.Parameters[PoolStrideParamIdx])->NumberOfDimensions == 1 &&
|
||||
static_cast<Gna2Shape*>(op.Parameters[PoolStrideParamIdx])->Dimensions[0] > static_cast<Gna2Shape*>(op.Parameters[PoolWinParamIdx])->Dimensions[0];
|
||||
}
|
||||
|
||||
void GNAPluginNS::backend::AMIntelDNN::updateNumberOfOutputsIfPoolingEnabled(Gna2Model& gnaModel, bool useLegacyFormula) {
|
||||
IE_ASSERT(gnaModel.Operations != nullptr || gnaModel.NumberOfOperations == 0);
|
||||
for (uint32_t i = 0; i < gnaModel.NumberOfOperations; i++) {
|
||||
auto& gnaOp = gnaModel.Operations[i];
|
||||
IE_ASSERT(gnaOp.Operands != nullptr);
|
||||
IE_ASSERT(gnaOp.Operands[InOpIdx] != nullptr);
|
||||
auto& inputShape = gnaOp.Operands[InOpIdx]->Shape;
|
||||
IE_ASSERT(gnaOp.Parameters != nullptr || gnaOp.NumberOfParameters == 0);
|
||||
if (gnaOp.Type == Gna2OperationTypeConvolution && inputShape.NumberOfDimensions == 2 &&
|
||||
gnaOp.NumberOfParameters >= PoolStrideParamIdx &&
|
||||
gnaOp.Parameters[PoolWinParamIdx]!= nullptr &&
|
||||
gnaOp.Parameters[PoolStrideParamIdx] != nullptr) {
|
||||
IE_ASSERT(gnaOp.Operands[OutOpIdx] != nullptr);
|
||||
IE_ASSERT(gnaOp.Operands[FilterOpIdx] != nullptr);
|
||||
IE_ASSERT(gnaOp.Parameters[ConvStrideParamIdx] != nullptr);
|
||||
|
||||
const auto& fltStrideShape = *reinterpret_cast<Gna2Shape*>(gnaOp.Parameters[ConvStrideParamIdx]);
|
||||
const auto fltStride = fltStrideShape.Dimensions[0];
|
||||
const auto inVecCnt = inputShape.Dimensions[1];
|
||||
const auto nFltSize = gnaOp.Operands[FilterOpIdx]->Shape.Dimensions[1];
|
||||
const auto outFromConv = GNAPluginNS::GNAConvolutionLayer::outputFromConv(inVecCnt, nFltSize, fltStride);
|
||||
const auto& poolWindow = *static_cast<Gna2Shape*>(gnaOp.Parameters[PoolWinParamIdx]);
|
||||
const auto& poolStride = *static_cast<Gna2Shape*>(gnaOp.Parameters[PoolStrideParamIdx]);
|
||||
const auto numberOfOutputs = GNAPluginNS::GNAConvolutionLayer::outputFromPooling(
|
||||
outFromConv, poolWindow.Dimensions[0], poolStride.Dimensions[0],
|
||||
useLegacyFormula || isOperationCnnLegacySpecific(gnaOp));
|
||||
auto& outputTensor = *gnaOp.Operands[OutOpIdx];
|
||||
const_cast<uint32_t&>(outputTensor.Shape.Dimensions[1]) = numberOfOutputs;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void GNAPluginNS::backend::AMIntelDNN::InitMaxpoolComponentPrivate(intel_dnn_component_t &comp,
|
||||
@@ -1679,28 +1711,10 @@ void GNAPluginNS::backend::AMIntelDNN::InitGNAStruct(intel_nnet_type_t *ptr_nnet
|
||||
HelperGna2OperationSetParameter(gnaOperation, gnaUserAllocator, gnaUserFree, PoolWinParamIdx, poolWindow);
|
||||
HelperGna2OperationSetParameter(gnaOperation, gnaUserAllocator, gnaUserFree, PoolStrideParamIdx, poolStride);
|
||||
|
||||
auto& outputTensor = const_cast<Gna2Tensor&>(*gnaOperation->Operands[OutOpIdx]);
|
||||
const auto fltStrideShape = reinterpret_cast<Gna2Shape*>(gnaOperation->Parameters[ConvStrideParamIdx]);
|
||||
// adjust Gna2OperationTypeConvolution fused layer output dimensions to reflect convolution zeroPadding and pooling
|
||||
if (gnaOperation->Operands[InOpIdx]->Shape.NumberOfDimensions == 2) { // kDnnConvolutional1dOp
|
||||
const auto inVecCnt = gnaOperation->Operands[InOpIdx]->Shape.Dimensions[1];
|
||||
|
||||
const auto nFltSize = gnaOperation->Operands[FilterOpIdx]->Shape.Dimensions[1];
|
||||
// Always move 1 "row"
|
||||
const auto fltStride = fltStrideShape->Dimensions[0];
|
||||
const auto outFromConv = outputFromConv(inVecCnt, nFltSize, fltStride);
|
||||
// FLAT input matrix, pooled outputs per filter
|
||||
|
||||
auto effectiveCompileTarget = gnaCompileTarget;
|
||||
if (isOperationCnnLegacySpecific(*gnaOperation)) {
|
||||
effectiveCompileTarget = InferenceEngine::GNAConfigParams::GNA_TARGET_2_0;
|
||||
}
|
||||
if (effectiveCompileTarget == InferenceEngine::GNAConfigParams::GNA_TARGET_3_0) {
|
||||
outputTensor.Shape.Dimensions[1] = outputFromPooling(outFromConv, poolWindow->Dimensions[0], poolStride->Dimensions[0]);
|
||||
} else {
|
||||
outputTensor.Shape.Dimensions[1] = outputFromPoolingLegacy(outFromConv, poolStride->Dimensions[0]);
|
||||
}
|
||||
} else { // kDnnConvolutional2dOp
|
||||
if (gnaOperation->Operands[InOpIdx]->Shape.NumberOfDimensions != 2) { // kDnnConvolutional2dOp
|
||||
auto& outputTensor = const_cast<Gna2Tensor&>(*gnaOperation->Operands[OutOpIdx]);
|
||||
const auto fltStrideShape = reinterpret_cast<Gna2Shape*>(gnaOperation->Parameters[ConvStrideParamIdx]);
|
||||
// Override GNA operation output pointer with the one from pooling component
|
||||
outputTensor.Data = comp.ptr_outputs;
|
||||
|
||||
|
||||
@@ -158,6 +158,9 @@ public:
|
||||
// Checks whether operation is Convolution and its parameters makes it specific to GNA1/GNA2 targets
|
||||
// It does not guarantee that operation fully compatible to GNA1/GNA2, but for sure is not comaptible with GNA3 target
|
||||
static bool isOperationCnnLegacySpecific(const Gna2Operation& operation);
|
||||
// Recomputes number of outputs from CNN1D operations using legacy or new formula
|
||||
// If isOperationCnnLegacySpecific() is true the number of outputs will also be recomputed for legacy compatibility
|
||||
static void updateNumberOfOutputsIfPoolingEnabled(Gna2Model& gnaModel, bool useLegacyFormula);
|
||||
#endif
|
||||
|
||||
template<class A, class B>
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "backend/am_intel_dnn.hpp"
|
||||
#include "gna/gna_config.hpp"
|
||||
#include "gna_plugin_log.hpp"
|
||||
#include "layers/gna_convolution_layer.hpp"
|
||||
|
||||
//#define MODEL_DUMP
|
||||
|
||||
@@ -143,10 +144,14 @@ void GNADeviceHelper::enforceLegacyCnnsWhenNeeded(Gna2Model& gnaModel) {
|
||||
uint32_t GNADeviceHelper::createModel(Gna2Model& gnaModel) const {
|
||||
std::unique_lock<std::mutex> lockGnaCalls{ acrossPluginsSync };
|
||||
uint32_t modelId;
|
||||
if (enforceLegacyCnnNeeded()) {
|
||||
const auto legacyExecTarget = enforceLegacyCnnNeeded();
|
||||
if (legacyExecTarget) {
|
||||
enforceLegacyCnns(gnaModel);
|
||||
}
|
||||
enforceLegacyCnnsWhenNeeded(gnaModel);
|
||||
|
||||
GNAPluginNS::backend::AMIntelDNN::updateNumberOfOutputsIfPoolingEnabled(gnaModel, legacyExecTarget);
|
||||
|
||||
#if GNA_LIB_VER == 2 && defined MODEL_DUMP
|
||||
std::string path =
|
||||
#ifdef _WIN32
|
||||
|
||||
@@ -56,7 +56,10 @@ uint32_t outputFromConv(const uint32_t in, const uint32_t flt, const uint32_t st
|
||||
return (in - flt) / stride + 1;
|
||||
}
|
||||
|
||||
uint32_t outputFromPooling(const uint32_t in, const uint32_t window, const uint32_t stride) {
|
||||
uint32_t outputFromPooling(const uint32_t in, const uint32_t window, const uint32_t stride, const bool legacy) {
|
||||
if (legacy) {
|
||||
return outputFromPoolingLegacy(in, stride);
|
||||
}
|
||||
// ceil[(in - window)/stride] + 1, GNA Spec 1.24
|
||||
if (window > in || window == 0 || stride == 0) {
|
||||
THROW_GNA_EXCEPTION << "Invalid (input, window, stride) = (" << in << "," << window << "," << stride << ")";
|
||||
|
||||
@@ -20,7 +20,7 @@ double getWeightsReducer(InferenceEngine::ConvolutionLayer& conv);
|
||||
|
||||
uint32_t outputFromConv(const uint32_t in, const uint32_t flt, const uint32_t stride);
|
||||
|
||||
uint32_t outputFromPooling(const uint32_t in, const uint32_t window, const uint32_t stride);
|
||||
uint32_t outputFromPooling(const uint32_t in, const uint32_t window, const uint32_t stride, bool legacy = false);
|
||||
|
||||
uint32_t outputFromPoolingLegacy(const uint32_t in, const uint32_t stride);
|
||||
|
||||
|
||||
@@ -219,6 +219,15 @@ const std::vector<std::map<std::string, std::string>> configs = {
|
||||
}
|
||||
};
|
||||
|
||||
const std::vector<std::map<std::string, std::string>> configsExec30Compile20 = {
|
||||
{
|
||||
{"GNA_DEVICE_MODE", "GNA_SW_EXACT"},
|
||||
{"GNA_SCALE_FACTOR_0", "1"},
|
||||
{"GNA_EXEC_TARGET", "GNA_TARGET_3_0"},
|
||||
{"GNA_COMPILE_TARGET", "GNA_TARGET_2_0"}
|
||||
}
|
||||
};
|
||||
|
||||
const std::vector<op::PadType> padTypes = {
|
||||
op::PadType::VALID,
|
||||
op::PadType::EXPLICIT,
|
||||
@@ -237,6 +246,11 @@ const std::vector<modelType> models = {
|
||||
modelType::TranspConvBcastAddMaxPoolActTransp
|
||||
};
|
||||
|
||||
const std::vector<modelType> modelsWithPool = {
|
||||
modelType::TranspConvBcastAddMaxPoolTransp,
|
||||
modelType::TranspConvBcastAddMaxPoolActTransp
|
||||
};
|
||||
|
||||
const std::vector<std::vector<size_t>> input2DNHWC = {{1, 4, 4, 32}};
|
||||
const std::vector<std::vector<size_t >> kernels2D = {{1, 2}, {2, 1}, {2, 2}};
|
||||
const std::vector<std::vector<size_t >> strides2D = {{1, 1}};
|
||||
@@ -277,6 +291,20 @@ INSTANTIATE_TEST_SUITE_P(smoke_Decompose2DConv, Decompose2DConvTest,
|
||||
::testing::ValuesIn(models)),
|
||||
Decompose2DConvTest::getTestCaseName);
|
||||
|
||||
// These tests flow compile the model for GNA 2.0
|
||||
// and load by GNA Library for GNA 3.0 execution target
|
||||
// They assure that the W/A for pooling output differences btw GNA 2.0 / 3.0 is properly working
|
||||
INSTANTIATE_TEST_CASE_P(smoke_Decompose2DConv_Exec30Compile20, Decompose2DConvTest,
|
||||
::testing::Combine(
|
||||
conv2DParams,
|
||||
miscParams,
|
||||
::testing::ValuesIn(netPrecisions),
|
||||
::testing::Values(CommonTestUtils::DEVICE_GNA),
|
||||
::testing::ValuesIn(configsExec30Compile20),
|
||||
::testing::ValuesIn(input2DNHWC),
|
||||
::testing::ValuesIn(modelsWithPool)),
|
||||
Decompose2DConvTest::getTestCaseName);
|
||||
|
||||
|
||||
/* ============= Strides & Dilations Combination ============= */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user