[LPT] BLOCKED layout ignoring (#1873)

* [LPT] BLOCKED layout ignoring

* [LPT] Permute transformation tests

* [LPT] Tests rework
This commit is contained in:
Edward Shogulin 2020-08-25 10:43:33 +03:00 committed by GitHub
parent a2f0eef6aa
commit ee96595d1d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 364 additions and 99 deletions

View File

@ -122,6 +122,8 @@ public:
const std::unordered_set<std::string>& exceptionLayerTypes = {},
const int portIndex = -1);
static bool isLayoutSupported(const CNNLayer& layer);
static size_t getInputChannelsCount(const CNNLayer& layer);
static size_t getParamOutput(const CNNLayer& layer);

View File

@ -83,6 +83,10 @@ const std::vector<Precision>& LayerTransformation::getPrecisionsOnWeights() cons
}
bool LayerTransformation::canBeTransformed(const TransformationContext& context, const CNNLayer& layer) const {
if (!CNNNetworkHelper::isLayoutSupported(layer)) {
return false;
}
if (!isQuantized(layer)) {
return false;
}

View File

@ -872,7 +872,41 @@ std::vector<CNNLayerPtr> CNNNetworkHelper::getParentsRecursivelyExceptTypes(
return parents;
}
bool CNNNetworkHelper::isLayoutSupported(const CNNLayer& layer) {
auto isSupported = [](const Data& data) -> bool {
switch (data.getLayout()) {
case Layout::NC:
case Layout::NCHW:
case Layout::NCDHW: {
return true;
}
case Layout::CHW: {
if (data.getDims().size() != 3lu) {
return false;
}
return true;
}
default: {
return false;
}
}
return true;
};
for (const auto& data : layer.outData) {
if (!isSupported(*data)) {
return false;
}
}
return true;
}
size_t CNNNetworkHelper::getInputChannelsCount(const CNNLayer& layer) {
if (!isLayoutSupported(layer)) {
THROW_IE_LPT_EXCEPTION(layer) << "Not supported layout";
}
if (layer.insData.size() == 0) {
THROW_IE_EXCEPTION << "There are no input layers";
}
@ -882,25 +916,8 @@ size_t CNNNetworkHelper::getInputChannelsCount(const CNNLayer& layer) {
THROW_IE_EXCEPTION << "insert data is absent";
}
switch (insertData->getLayout()) {
case Layout::NC:
case Layout::NCHW:
case Layout::NCDHW: {
return insertData->getDims()[1];
}
case Layout::CHW: {
if (insertData->getDims().size() != 3lu) {
THROW_IE_EXCEPTION << "Unexpected dimensions size " << insertData->getDims().size() << " for layer "
<< layer.name;
}
// Actually MO assumes NCH layout for 3D blobs, so we get channels count from dimension 1
return insertData->getDims()[1];
}
default: {
THROW_IE_EXCEPTION << "Not supported layout " << insertData->getLayout();
}
}
// For CHW: actually MO assumes NCH layout for 3D blobs, so we get channels count from dimension 1
return insertData->getDims()[1];
}
size_t CNNNetworkHelper::getParamOutput(const CNNLayer& layer) {

View File

@ -11,31 +11,106 @@ using namespace LayerTestsDefinitions;
namespace {
const std::vector<InferenceEngine::Precision> netPrecisions = {
InferenceEngine::Precision::FP32,
InferenceEngine::Precision::FP16
InferenceEngine::Precision::FP32
};
const std::vector<InferenceEngine::details::LayerTransformation::Params> trasformationParamValues = {
LayerTestsUtils::LayerTransformationParamsFactory::createParams().setUpdatePrecisions(true),
LayerTestsUtils::LayerTransformationParamsFactory::createParams().setUpdatePrecisions(false),
LayerTestsUtils::LayerTransformationParamsFactory::createParamsU8I8()
const std::vector<PermuteTransformationTestValues> testValues = {
// 6D: per-tensor: channels are permuted
{
LayerTestsUtils::LayerTransformationParamsFactory::createParamsU8I8(),
{ 1, 64, 38, 38 },
{ 1, 64, 19, 2, 19, 2 },
{ 0, 3, 5, 1, 2, 4 },
{
{ 0.f },
{ 25.5f},
{ 0.f },
{ 25.5f }
},
{
InferenceEngine::Precision::FP32,
false,
false
}
},
// 6D: per-tensor: channels are not permuted
{
LayerTestsUtils::LayerTransformationParamsFactory::createParamsU8I8(),
{ 1, 64, 38, 38 },
{ 1, 64, 19, 2, 19, 2 },
{ 0, 1, 5, 3, 2, 4 },
{
{ 0.f },
{ 25.5f},
{ 0.f },
{ 25.5f }
},
{
InferenceEngine::Precision::FP32,
false,
false
}
},
// 4D: per-tensor: channels are permuted
{
LayerTestsUtils::LayerTransformationParamsFactory::createParamsU8I8(),
{ 1, 3, 16, 16 },
{},
{ 0, 2, 1, 3 },
{
{ 0.f },
{ 25.5f},
{ 0.f },
{ 25.5f }
},
{
InferenceEngine::Precision::U8,
true,
false
}
},
// 4D: per-channel: channels are permuted
{
LayerTestsUtils::LayerTransformationParamsFactory::createParamsU8I8(),
{ 1, 3, 16, 16 },
{},
{ 0, 2, 1, 3 },
{
{ 0.f, 0.f, 0.f },
{ 25.5f, 25.5f / 2.f, 25.5f / 4.f },
{ 0.f, 0.f, 0.f },
{ 25.5f, 25.5f / 2.f, 25.5f / 4.f }
},
{
InferenceEngine::Precision::FP32,
false,
false
}
},
// 4D: per-channel: channels are not permuted
{
LayerTestsUtils::LayerTransformationParamsFactory::createParamsU8I8(),
{ 1, 3, 16, 16 },
{},
{ 0, 1, 3, 2 },
{
{ 0.f, 0.f, 0.f },
{ 25.5f, 25.5f / 2.f, 25.5f / 4.f },
{ 0.f, 0.f, 0.f },
{ 25.5f, 25.5f / 2.f, 25.5f / 4.f }
},
{
InferenceEngine::Precision::U8,
true,
false
}
}
};
const std::vector<bool> perTensorValues = { true, false };
const std::vector<bool> transposeChannelDimValues = { true, false };
INSTANTIATE_TEST_CASE_P(LPT, PermuteTransformation,
::testing::Combine(
::testing::ValuesIn(netPrecisions),
::testing::Values(InferenceEngine::SizeVector({ 1, 3, 16, 16 })),
::testing::Values(CommonTestUtils::DEVICE_CPU),
::testing::ValuesIn(trasformationParamValues),
::testing::ValuesIn(perTensorValues),
::testing::ValuesIn(transposeChannelDimValues)),
::testing::ValuesIn(testValues)),
PermuteTransformation::getTestCaseName);
} // namespace

View File

@ -11,28 +11,106 @@ using namespace LayerTestsDefinitions;
namespace {
const std::vector<InferenceEngine::Precision> netPrecisions = {
InferenceEngine::Precision::FP32
InferenceEngine::Precision::FP32
};
const std::vector<InferenceEngine::details::LayerTransformation::Params> trasformationParamValues = {
LayerTestsUtils::LayerTransformationParamsFactory::createParams()
const std::vector<PermuteTransformationTestValues> testValues = {
// 6D: per-tensor: channels are permuted
{
LayerTestsUtils::LayerTransformationParamsFactory::createParamsU8I8(),
{ 1, 64, 38, 38 },
{ 1, 64, 19, 2, 19, 2 },
{ 0, 3, 5, 1, 2, 4 },
{
{ 0.f },
{ 25.5f},
{ 0.f },
{ 25.5f }
},
{
InferenceEngine::Precision::FP32,
false,
false
}
},
// 6D: per-tensor: channels are not permuted
{
LayerTestsUtils::LayerTransformationParamsFactory::createParamsU8I8(),
{ 1, 64, 38, 38 },
{ 1, 64, 19, 2, 19, 2 },
{ 0, 1, 5, 3, 2, 4 },
{
{ 0.f },
{ 25.5f},
{ 0.f },
{ 25.5f }
},
{
InferenceEngine::Precision::FP32,
false,
false
}
},
// 4D: per-tensor: channels are permuted
{
LayerTestsUtils::LayerTransformationParamsFactory::createParamsU8I8(),
{ 1, 3, 16, 16 },
{},
{ 0, 2, 1, 3 },
{
{ 0.f },
{ 25.5f},
{ 0.f },
{ 25.5f }
},
{
InferenceEngine::Precision::U8,
true,
false
}
},
// 4D: per-channel: channels are permuted
{
LayerTestsUtils::LayerTransformationParamsFactory::createParamsU8I8(),
{ 1, 3, 16, 16 },
{},
{ 0, 2, 1, 3 },
{
{ 0.f, 0.f, 0.f },
{ 25.5f, 25.5f / 2.f, 25.5f / 4.f },
{ 0.f, 0.f, 0.f },
{ 25.5f, 25.5f / 2.f, 25.5f / 4.f }
},
{
InferenceEngine::Precision::FP32,
false,
false
}
},
// 4D: per-channel: channels are not permuted
{
LayerTestsUtils::LayerTransformationParamsFactory::createParamsU8I8(),
{ 1, 3, 16, 16 },
{},
{ 0, 1, 3, 2 },
{
{ 0.f, 0.f, 0.f },
{ 25.5f, 25.5f / 2.f, 25.5f / 4.f },
{ 0.f, 0.f, 0.f },
{ 25.5f, 25.5f / 2.f, 25.5f / 4.f }
},
{
InferenceEngine::Precision::U8,
true,
false
}
}
};
const std::vector<bool> perTensorValues = { true, false };
const std::vector<bool> transposeChannelDimValues = { true, false };
INSTANTIATE_TEST_CASE_P(LPT, PermuteTransformation,
::testing::Combine(
::testing::ValuesIn(netPrecisions),
::testing::Values(InferenceEngine::SizeVector({ 1, 3, 16, 16 })),
::testing::Values(CommonTestUtils::DEVICE_GPU),
::testing::ValuesIn(trasformationParamValues),
::testing::ValuesIn(perTensorValues),
::testing::ValuesIn(transposeChannelDimValues)),
::testing::ValuesIn(testValues)),
PermuteTransformation::getTestCaseName);
} // namespace

View File

@ -11,13 +11,35 @@
namespace LayerTestsDefinitions {
class PermuteTransformationTestValues {
public:
class Actual {
public:
std::vector<float> fqInputLowIntervals;
std::vector<float> fqInputHighIntervals;
std::vector<float> fqOutputLowIntervals;
std::vector<float> fqOutputHighIntervals;
};
class Expected {
public:
InferenceEngine::Precision permutePrecision;
bool scales;
bool shifts;
};
InferenceEngine::details::LayerTransformation::Params params;
InferenceEngine::SizeVector inputShape;
std::vector<size_t> reshapeValue;
std::vector<size_t> permuteValue;
Actual actual;
Expected expected;
};
typedef std::tuple<
InferenceEngine::Precision,
InferenceEngine::SizeVector,
std::string,
InferenceEngine::details::LayerTransformation::Params,
bool,
bool> PermuteTransformationParams;
PermuteTransformationTestValues> PermuteTransformationParams;
class PermuteTransformation :
public testing::WithParamInterface<PermuteTransformationParams>,

View File

@ -17,70 +17,116 @@
#include "functional_test_utils/blob_utils.hpp"
#include "ngraph_functions/pass/convert_prc.hpp"
#include "ngraph_functions/builders.hpp"
#include "low_precision_transformations/network_helper.hpp"
namespace LayerTestsDefinitions {
inline std::ostream &operator << (std::ostream &os, const std::vector<size_t>& values) {
os << "{";
for (size_t i = 0; i < values.size(); ++i) {
if (i > 0) {
os << values[i];
} else {
os << ", " << values[i];
}
}
os << "}";
return os;
}
std::string PermuteTransformation::getTestCaseName(testing::TestParamInfo<PermuteTransformationParams> obj) {
InferenceEngine::Precision netPrecision;
InferenceEngine::SizeVector inputShapes;
std::string targetDevice;
InferenceEngine::details::LayerTransformation::Params params;
bool perTensor;
bool transposeChannelDim;
std::tie(netPrecision, inputShapes, targetDevice, params, perTensor, transposeChannelDim) = obj.param;
PermuteTransformationTestValues testValues;
std::tie(netPrecision, targetDevice, testValues) = obj.param;
std::ostringstream result;
result << netPrecision.name() << "_" << targetDevice << "_" << toString(params) <<
(perTensor ? "_perTensor" : "_perChannel") <<
(transposeChannelDim ? "_transposeChannelDim" : "_notTransposeChannelDim");
result << netPrecision.name() << "_" << targetDevice << "_" << toString(testValues.params) <<
testValues.inputShape.size() << "D_" <<
testValues.reshapeValue << "_" <<
testValues.permuteValue << "_" <<
testValues.actual.fqOutputLowIntervals.size() << "_" <<
testValues.actual.fqOutputHighIntervals.size() << "_" <<
testValues.expected.permutePrecision << "_" <<
testValues.expected.scales << "_" <<
testValues.expected.shifts;
return result.str();
}
void PermuteTransformation::SetUp() {
InferenceEngine::SizeVector inputShape;
InferenceEngine::Precision netPrecision;
InferenceEngine::details::LayerTransformation::Params params;
bool perTensor;
bool transposeChannelDim;
std::tie(netPrecision, inputShape, targetDevice, params, perTensor, transposeChannelDim) = this->GetParam();
PermuteTransformationTestValues testValues;
std::tie(netPrecision, targetDevice, testValues) = this->GetParam();
const auto precision = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision);
const auto input1 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape));
input1->set_friendly_name("input1");
{
const auto input1 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(testValues.inputShape));
input1->set_friendly_name("input");
const auto input2 = std::make_shared<ngraph::opset1::Parameter>(precision, ngraph::Shape(inputShape));
input2->set_friendly_name("input2");
const auto fakeQuantize = ngraph::builder::makeFakeQuantize(
input1,
precision,
256ul,
{ 1, testValues.actual.fqOutputHighIntervals.size(), 1, 1 },
testValues.actual.fqInputLowIntervals,
testValues.actual.fqInputHighIntervals,
testValues.actual.fqOutputLowIntervals,
testValues.actual.fqOutputHighIntervals);
const float k = 50.f;
const auto fakeQuantize1 = ngraph::builder::makeFakeQuantize(input1, precision, 256ul, { 1ul }, { 0.f }, { 255.f / k }, { 0.f }, { 255.f / k });
input2->set_friendly_name("fakeQuantize1");
const auto fakeQuantize2 = ngraph::builder::makeFakeQuantize(input2, precision, 256ul, { 1ul }, { 0.f }, { 255.f / k }, { 0.f }, { 255.f / k });
input2->set_friendly_name("fakeQuantize2");
const auto matMul = std::make_shared<ngraph::opset1::MatMul>(fakeQuantize1, fakeQuantize2, false, false);
input2->set_friendly_name("matMul");
const auto transpose = std::make_shared<ngraph::opset1::Transpose>(
matMul,
ngraph::opset1::Constant::create(ngraph::element::i64, ngraph::Shape{ 4ul }, { 0, 2, 1, 3 }));
transpose->set_friendly_name("transpose");
const std::shared_ptr<ngraph::Node> relu = std::make_shared<ngraph::opset1::Relu>(fakeQuantize);
ngraph::ResultVector results{ std::make_shared<ngraph::opset1::Result>(transpose) };
function = std::make_shared<ngraph::Function>(results, ngraph::ParameterVector{ input1, input2 }, "PermuteTransformation");
const std::shared_ptr<ngraph::Node> reshape = testValues.reshapeValue.empty() ?
nullptr :
std::make_shared<ngraph::opset1::Reshape>(
relu,
std::make_shared<ngraph::opset1::Constant>(ngraph::element::u32, ngraph::Shape { testValues.reshapeValue.size() }, testValues.reshapeValue),
false);
const auto transpose = std::make_shared<ngraph::opset1::Transpose>(
reshape == nullptr ? relu : reshape,
ngraph::opset1::Constant::create(ngraph::element::i64, ngraph::Shape{ testValues.permuteValue.size() }, testValues.permuteValue));
transpose->set_friendly_name("transpose");
ngraph::ResultVector results{ std::make_shared<ngraph::opset1::Result>(transpose) };
function = std::make_shared<ngraph::Function>(results, ngraph::ParameterVector{ input1 }, "PermuteTransformation");
}
validate();
}
IE_SUPPRESS_DEPRECATED_START
void fillFromDequantizationLayer(
const InferenceEngine::CNNLayer& dequantizationLayer,
std::vector<float>& dequantizationScales,
std::vector<float>& dequantizationShifts) {
if (dequantizationLayer.type != "ScaleShift") {
THROW_IE_EXCEPTION << "unexpected dequantization layer type " << dequantizationLayer.type;
}
InferenceEngine::CNNLayerPtr dequantizationLayerPtr = std::make_shared<InferenceEngine::CNNLayer>(dequantizationLayer);
InferenceEngine::Blob::Ptr weightsBlob = InferenceEngine::details::CNNNetworkHelper::getBlob(dequantizationLayerPtr, "weights");
const auto weightsBuffer = InferenceEngine::details::CNNNetworkHelper::getFloatData(weightsBlob);
InferenceEngine::Blob::Ptr shiftsBlob = InferenceEngine::details::CNNNetworkHelper::getBlob(dequantizationLayerPtr, "biases");
const auto shiftsBuffer = InferenceEngine::details::CNNNetworkHelper::getFloatData(shiftsBlob);
const size_t inputCannelsCount = InferenceEngine::details::CNNNetworkHelper::getInputChannelsCount(dequantizationLayer);
dequantizationScales.resize(inputCannelsCount);
dequantizationShifts.resize(inputCannelsCount);
for (size_t channel = 0; channel < inputCannelsCount; ++channel) {
dequantizationScales[channel] = (weightsBlob->size() == 1ul) ? weightsBuffer.get()[0] : weightsBuffer.get()[channel];
dequantizationShifts[channel] = (shiftsBlob->size() == 1ul) ? shiftsBuffer.get()[0] : shiftsBuffer.get()[channel];
}
}
void PermuteTransformation::validate() {
InferenceEngine::SizeVector inputShape;
InferenceEngine::Precision netPrecision;
InferenceEngine::details::LayerTransformation::Params params;
bool perTensor;
bool transposeChannelDim;
std::tie(netPrecision, inputShape, targetDevice, params, perTensor, transposeChannelDim) = this->GetParam();
PermuteTransformationTestValues testValues;
std::tie(netPrecision, targetDevice, testValues) = this->GetParam();
const InferenceEngine::CNNNetwork network = transform(params);
IE_SUPPRESS_DEPRECATED_START
const InferenceEngine::CNNNetwork network = transform(testValues.params);
InferenceEngine::OutputsDataMap outputs = network.getOutputsInfo();
EXPECT_EQ(1, outputs.size());
@ -88,14 +134,35 @@ void PermuteTransformation::validate() {
std::map<std::string, InferenceEngine::DataPtr>::iterator it = outputs.begin();
const InferenceEngine::CNNLayerPtr outputLayer = getCreatorLayer(it->second).lock();
EXPECT_TRUE(outputLayer != nullptr);
EXPECT_EQ("ScaleShift", outputLayer->type);
InferenceEngine::CNNLayerPtr permute;
if (testValues.expected.scales || testValues.expected.shifts) {
EXPECT_EQ("ScaleShift", outputLayer->type);
std::vector<float> dequantizationScales;
std::vector<float> dequantizationShifts;
fillFromDequantizationLayer(*outputLayer, dequantizationScales, dequantizationShifts);
if (testValues.expected.scales) {
ASSERT_TRUE(std::all_of(dequantizationScales.begin(), dequantizationScales.end(), [](const float value) { return value != 0.f; }));
}
if (testValues.expected.shifts) {
ASSERT_TRUE(std::all_of(dequantizationShifts.begin(), dequantizationShifts.end(), [](const float value) { return value != 0.f; }));
}
permute = getCreatorLayer(outputLayer->insData[0].lock()).lock();
} else {
permute = outputLayer;
}
EXPECT_EQ("Permute", permute->type);
const InferenceEngine::CNNLayerPtr layer = InferenceEngine::details::CNNNetworkHelper::getParent(*outputLayer);
checkPrecisions(*layer, netPrecision);
IE_SUPPRESS_DEPRECATED_END
checkPrecisions(*permute, testValues.expected.permutePrecision);
}
IE_SUPPRESS_DEPRECATED_END
TEST_P(PermuteTransformation, CompareWithRefImpl) {
Run();
};