[GNA] Fixed convolutions with shared transpose and un-fuse-able activations after Convolution filter (Renew PR11373) (#12152)
* Commits from PR11373: Fixed handling of transpose after convolution [GNA] Fixed calculation of dimensions for ConvolutionFilter and PWL primitives [GNA] Fixed coverity error and failed tests * Apply comments * Update src/plugins/intel_gna/gna_graph_compiler.cpp Co-authored-by: Marcin Kusmierski <marcin.kusmierski@intel.com> * Update src/plugins/intel_gna/gna_graph_compiler.cpp Co-authored-by: Marcin Kusmierski <marcin.kusmierski@intel.com> * Rollback names * Separate test data * Move coverity issue to separate request Co-authored-by: Elizaveta Lobanova <elizaveta.lobanova@intel.com> Co-authored-by: Marcin Kusmierski <marcin.kusmierski@intel.com>
This commit is contained in:
4 files changed
+185
-21
No files matched your search
@@ -1814,8 +1814,10 @@ void GNAGraphCompiler::ConvolutionFilterPrimitive(InferenceEngine::CNNLayerPtr l
|
||||
|
||||
const auto noOfInputsDivisor = gnaFlags->input_low_precision ?
|
||||
GNALimitations::noOfInputsLowPrecDivisor : GNALimitations::noOfInputsDivisor;
|
||||
const uint32_t orginalInputSize = GetDataDimSize(inputs, 1);
|
||||
const uint32_t orginalOutputSize = GetDataDimSize(outputs, 1);
|
||||
const uint32_t orginalInputSize =
|
||||
InferenceEngine::details::product(std::next(inputs->getDims().begin()), inputs->getDims().end());
|
||||
const uint32_t orginalOutputSize =
|
||||
InferenceEngine::details::product(std::next(outputs->getDims().begin()), outputs->getDims().end());
|
||||
if (orginalInputSize != orginalOutputSize) {
|
||||
THROW_GNA_LAYER_EXCEPTION(filterLayer) << "Number in inputs (" << orginalInputSize <<
|
||||
") should be equal to number of outputs (" << orginalOutputSize << ")!";
|
||||
|
||||
@@ -695,21 +695,40 @@ void RemovePermutationsNHWCToNCHWPass::run() {
|
||||
data->setLayout(layout);
|
||||
};
|
||||
|
||||
auto input_to = getInputTo(pattern_start->outData[0]);
|
||||
IE_ASSERT(!input_to.empty());
|
||||
auto current_layer = input_to.begin()->second;
|
||||
setTransposedOrder(current_layer->input());
|
||||
std::function<void(CNNLayerPtr)> propogateNHWCOrderRecursive =
|
||||
[pattern_end, &propogateNHWCOrderRecursive, &setTransposedOrder](CNNLayerPtr current_layer) {
|
||||
if (current_layer == pattern_end) return;
|
||||
for (size_t i = 0; i < current_layer->outData.size(); ++i) {
|
||||
setTransposedOrder(current_layer->outData[i]);
|
||||
auto input_to = getInputTo(current_layer->outData[i]);
|
||||
IE_ASSERT(!input_to.empty());
|
||||
propogateNHWCOrderRecursive(input_to.begin()->second);
|
||||
std::function<std::list<InferenceEngine::DataPtr>(CNNLayerPtr, const std::list<InferenceEngine::DataPtr>&)> getPathBetweenTransposes =
|
||||
[pattern_start, pattern_end, &getPathBetweenTransposes](CNNLayerPtr current_layer, const std::list<InferenceEngine::DataPtr>& path) {
|
||||
if (current_layer == pattern_end) {
|
||||
// the pattern end has been found, return the full path
|
||||
return path;
|
||||
}
|
||||
|
||||
// transpose is reached, the pattern end hasn't been found
|
||||
if (current_layer != pattern_start &&
|
||||
(LayerInfo(current_layer).isPermute() || LayerInfo(current_layer).isPermuteViaReshape())) {
|
||||
return std::list<InferenceEngine::DataPtr>();
|
||||
}
|
||||
|
||||
auto new_path(path);
|
||||
std::list<InferenceEngine::DataPtr> mergedChildPath;
|
||||
for (const auto& output : current_layer->outData) {
|
||||
new_path.push_back(output);
|
||||
for (const auto& input : getInputTo(output)) {
|
||||
auto childPath = getPathBetweenTransposes(input.second, new_path);
|
||||
// only the branch with the pattern end will return not empty list
|
||||
if (!childPath.empty()) {
|
||||
mergedChildPath.insert(std::end(mergedChildPath), std::begin(childPath), std::end(childPath));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mergedChildPath;
|
||||
};
|
||||
propogateNHWCOrderRecursive(current_layer);
|
||||
|
||||
auto path = getPathBetweenTransposes(pattern_start, std::list<InferenceEngine::DataPtr>());
|
||||
for (const auto& data : path) {
|
||||
setTransposedOrder(data);
|
||||
}
|
||||
|
||||
if ((LayerInfo(pattern_start).isPermute() || LayerInfo(pattern_start).isPermuteViaReshape()) &&
|
||||
!getInputTo(pattern_start->outData.front()).empty()) {
|
||||
@@ -1341,10 +1360,9 @@ void InsertSplitAligningFilterPass::run() {
|
||||
if (getInputTo(splitOutput).empty()) {
|
||||
gnalog() << "Output port: " << splitOutIndex << " of " << l->name << " unconnected, skipping\n";
|
||||
} else {
|
||||
auto lastDimSize = GetDataDimSize(splitOutput, 1);
|
||||
if (lastDimSize != outputSize) {
|
||||
THROW_GNA_EXCEPTION << l->name << " Convolution Filter doesn't support these input dimensions: lastDimSize="
|
||||
<< lastDimSize << ", outputSize=" << outputSize;
|
||||
if (splitOutput->getDims().size() > 1 && splitOutput->getDims().front() > 1) {
|
||||
THROW_GNA_EXCEPTION << l->name << " Convolution Filter doesn't support batch="
|
||||
<< splitOutput->getDims().front();
|
||||
}
|
||||
|
||||
// this split output not beginning from 64 bytes aligned boundary - need to correct by aligning filter layer
|
||||
|
||||
+144
-1
@@ -36,6 +36,14 @@ typedef std::tuple<
|
||||
bool // transpose to reshape
|
||||
> removePermutationsAddParamPassParams;
|
||||
|
||||
typedef std::tuple<
|
||||
InferenceEngine::Precision, // Network Precision
|
||||
std::string, // Target Device
|
||||
std::map<std::string, std::string>, // Configuration
|
||||
std::vector<size_t>, // Input shape
|
||||
size_t // Splits number
|
||||
> removeSharedPermutationPassParams;
|
||||
|
||||
namespace LayerTestsDefinitions {
|
||||
|
||||
std::vector<size_t> GetKernelShape(std::vector<size_t> input_shape, size_t kernel_size, bool output_1d = false) {
|
||||
@@ -72,7 +80,7 @@ ngraph::Shape GetLayerTransposedOutputShape(std::shared_ptr<ngraph::Node> layer)
|
||||
return nhwc_out_shape;
|
||||
}
|
||||
|
||||
std::shared_ptr<ngraph::Node> CreateConvolution(std::shared_ptr<ngraph::Node> input,
|
||||
std::shared_ptr<ngraph::Node> CreateConvolution(const ngraph::Output<ngraph::Node>& input,
|
||||
const ov::element::Type& ngPrc,
|
||||
const std::vector<size_t> &input_shape,
|
||||
bool output1D = false,
|
||||
@@ -465,6 +473,101 @@ class RemovePermutationsWithEltwiseTest : public testing::WithParamInterface<rem
|
||||
}
|
||||
};
|
||||
|
||||
class RemoveSharedPermutationTest : public testing::WithParamInterface<removeSharedPermutationPassParams>,
|
||||
public LayerTestsUtils::LayerTestsCommon {
|
||||
public:
|
||||
static std::string getTestCaseName(testing::TestParamInfo<removeSharedPermutationPassParams> obj) {
|
||||
InferenceEngine::Precision netPrecision;
|
||||
std::string targetDevice;
|
||||
std::map<std::string, std::string> configuration;
|
||||
std::vector<size_t> inputShape;
|
||||
size_t splits_num;
|
||||
std::tie(netPrecision, targetDevice, configuration, inputShape, splits_num) = obj.param;
|
||||
|
||||
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 << "_splits=" << splits_num;
|
||||
return result.str();
|
||||
}
|
||||
|
||||
protected:
|
||||
InferenceEngine::Blob::Ptr GenerateInput(const InferenceEngine::InputInfo& info) const override {
|
||||
InferenceEngine::Blob::Ptr blob = make_blob_with_precision(info.getTensorDesc());
|
||||
blob->allocate();
|
||||
|
||||
auto* rawBlobDataPtr = blob->buffer().as<float*>();
|
||||
std::vector<float> values = CommonTestUtils::generate_float_numbers(blob->size(), -0.2f, 0.2f);
|
||||
for (size_t i = 0; i < blob->size(); i++) {
|
||||
rawBlobDataPtr[i] = values[i];
|
||||
}
|
||||
return blob;
|
||||
}
|
||||
|
||||
void SetUp() override {
|
||||
// Reshape
|
||||
// |
|
||||
// Permute (order: [0, 3, 1, 2])
|
||||
// |
|
||||
// ______________Split____________________
|
||||
// | |
|
||||
// Convolution Convolution
|
||||
// | |
|
||||
// Permute (order: [0, 2, 3, 1]) Permute (order: [0, 2, 3, 1])
|
||||
// | |
|
||||
// Reshape Reshape
|
||||
// |______________________________________|
|
||||
// Concat
|
||||
InferenceEngine::Precision netPrecision;
|
||||
std::vector<size_t> inputShape;
|
||||
size_t splits_num;
|
||||
std::tie(netPrecision, targetDevice, configuration, inputShape, splits_num) = this->GetParam();
|
||||
auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision);
|
||||
|
||||
size_t shape_size = inputShape.size();
|
||||
ASSERT_GT(shape_size, 2);
|
||||
ASSERT_LT(shape_size, 5);
|
||||
|
||||
size_t in_total_dims_size = std::accumulate(std::begin(inputShape), std::end(inputShape), 1, std::multiplies<double>());
|
||||
auto params = ngraph::builder::makeParams(ngPrc, {{1, splits_num * in_total_dims_size}});
|
||||
|
||||
auto multipleInputShape = inputShape;
|
||||
size_t mul_dim = inputShape.size() == 4 && inputShape[1] > 1 ? 1 : (inputShape.size() - 2);
|
||||
multipleInputShape[mul_dim] *= splits_num;
|
||||
auto pattern = std::make_shared<ngraph::opset1::Constant>(ngraph::element::Type_t::i64,
|
||||
ngraph::Shape{multipleInputShape.size()}, multipleInputShape);
|
||||
auto reshape = std::make_shared<ngraph::opset1::Reshape>(params[0], pattern, false);
|
||||
auto permute = CreateTranspose(reshape, shape_size, true);
|
||||
auto split = ngraph::builder::makeSplit(permute, ngPrc, splits_num, inputShape.size() == 4 && inputShape[1] > 1 ?
|
||||
inputShape.size() - 2 : inputShape.size() - 1);
|
||||
|
||||
auto conv1 = CreateConvolution(split->output(0), ngPrc, inputShape);
|
||||
auto permute1 = CreateTranspose(conv1, conv1->get_output_shape(0).size(), false);
|
||||
auto conv1_out_size = std::accumulate(std::begin(conv1->get_output_shape(0)), std::end(conv1->get_output_shape(0)),
|
||||
size_t(1), std::multiplies<size_t>());
|
||||
auto pattern1 = std::make_shared<ngraph::opset1::Constant>(ngraph::element::Type_t::i64,
|
||||
ngraph::Shape{ 2 }, ngraph::Shape{ 1, conv1_out_size });
|
||||
auto reshape1 = std::make_shared<ngraph::opset1::Reshape>(permute1, pattern1, false);
|
||||
|
||||
auto conv2 = CreateConvolution(split->output(1), ngPrc, inputShape);
|
||||
auto permute2 = CreateTranspose(conv2, conv2->get_output_shape(0).size(), false);
|
||||
auto conv2_out_size = std::accumulate(std::begin(conv2->get_output_shape(0)), std::end(conv2->get_output_shape(0)),
|
||||
size_t(1), std::multiplies<size_t>());
|
||||
auto pattern2 = std::make_shared<ngraph::opset1::Constant>(ngraph::element::Type_t::i64,
|
||||
ngraph::Shape{ 2 }, ngraph::Shape{ 1, conv2_out_size });
|
||||
auto reshape2 = std::make_shared<ngraph::opset1::Reshape>(permute2, pattern2, false);
|
||||
|
||||
auto concat = ngraph::builder::makeConcat({reshape1, reshape2}, 1);
|
||||
|
||||
ngraph::ResultVector results{ std::make_shared<ngraph::opset1::Result>(concat) };
|
||||
function = std::make_shared<ngraph::Function>(results, params, "RemoveSharedPermutationTest");
|
||||
}
|
||||
};
|
||||
|
||||
TEST_P(RemovePermutationsNHWCToNCHWPassTest, CompareWithRefImpl) {
|
||||
Run();
|
||||
};
|
||||
@@ -485,6 +588,10 @@ class RemovePermutationsWithEltwiseTest : public testing::WithParamInterface<rem
|
||||
Run();
|
||||
};
|
||||
|
||||
TEST_P(RemoveSharedPermutationTest, CompareWithRefImpl) {
|
||||
Run();
|
||||
};
|
||||
|
||||
const std::vector<InferenceEngine::Precision> netPrecisions = {
|
||||
InferenceEngine::Precision::FP32,
|
||||
InferenceEngine::Precision::FP16
|
||||
@@ -525,6 +632,33 @@ class RemovePermutationsWithEltwiseTest : public testing::WithParamInterface<rem
|
||||
{1, 32, 9}
|
||||
};
|
||||
|
||||
const std::vector<std::vector<size_t>> inputShapesSplit {
|
||||
{1, 1, 160, 1},
|
||||
{1, 1, 160, 2},
|
||||
{1, 1, 168, 4},
|
||||
{1, 1, 32, 1},
|
||||
{1, 1, 32, 2},
|
||||
{1, 1, 32, 8},
|
||||
{1, 1, 32, 9},
|
||||
{1, 160, 1, 1},
|
||||
{1, 160, 1, 2},
|
||||
{1, 168, 1, 4},
|
||||
{1, 32, 1, 1},
|
||||
{1, 32, 1, 2},
|
||||
{1, 32, 1, 8},
|
||||
{1, 32, 1, 9},
|
||||
{1, 16, 8, 1},
|
||||
{1, 168, 1},
|
||||
{1, 168, 2},
|
||||
{1, 168, 4},
|
||||
{1, 32, 1},
|
||||
{1, 32, 2},
|
||||
{1, 32, 8},
|
||||
{1, 32, 9}
|
||||
};
|
||||
|
||||
const std::vector<size_t> splitsNum = {2, 4, 8};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(smoke_PermutationPass, RemovePermutationsNHWCToNCHWPassTest,
|
||||
::testing::Combine(
|
||||
::testing::ValuesIn(netPrecisions),
|
||||
@@ -569,5 +703,14 @@ class RemovePermutationsWithEltwiseTest : public testing::WithParamInterface<rem
|
||||
::testing::ValuesIn(inputShapes)),
|
||||
RemovePermutationsWithEltwiseTest::getTestCaseName);
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(smoke_PermutationPass, RemoveSharedPermutationTest,
|
||||
::testing::Combine(
|
||||
::testing::ValuesIn(netPrecisions),
|
||||
::testing::Values(CommonTestUtils::DEVICE_GNA),
|
||||
::testing::ValuesIn(configs),
|
||||
::testing::ValuesIn(inputShapesSplit),
|
||||
::testing::ValuesIn(splitsNum)),
|
||||
RemoveSharedPermutationTest::getTestCaseName);
|
||||
|
||||
} // namespace LayerTestsDefinitions
|
||||
|
||||
+2
-1
@@ -14,7 +14,8 @@ namespace {
|
||||
{{1, 64}},
|
||||
{{1, 128}},
|
||||
{{1, 96}},
|
||||
{{1, 16}}
|
||||
{{1, 16}},
|
||||
{{1, 132, 8}}
|
||||
};
|
||||
|
||||
std::vector<std::vector<size_t>> connect_index{
|
||||
|
||||
Reference in new issue
Block a user