[IE][VPU]: Faster-RCNN fixes on myriad plugin side (#711)
* [IE][VPU]: Enables pass for propagating dynamism to network outputs If network had dynamic output and then myriad Front-End inserted convert stage at the end (to convert FP16 -> FP32 - output precision) then dynamism would not be propagated - we have convert stage that has dynamic input, but static output. As a result, we have run-time error in Convert kernel: input and output shapes do not match. At the moment, pass supports only Convert stage as output stage over which we should propagate dynamism to outputs. Signed-off-by: Gladilov, Gleb <gleb.gladilov@intel.com> * [IE][VPU]: Fixes parse DSR in case of output data Replacing stage output must be done after replacing data to shape parent, because the last one may access original parent producer, but after replacing stage output it'd not have one. Signed-off-by: Gladilov, Gleb <gleb.gladilov@intel.com> * [IE][VPU]: Fixes MacOS build * [IE][VPU]: Fixes shape data naming convention Plugin part assumes that if there is dynamic data object, that's represented as 2 different data objects (data and shape), then shape data object has name = data object name + @shape suffix. Pass that creates new dynamic data object should respect that assumption. * [IE][VPU]: Fixes dis-alignment in names of data objects representing dynamic data object MyriadInferRequest::GetResult assumes that in case of dynamic data object "data" data object and "shape" data object will have aligned names: "shape" name = "data" name + "@shape" suffix. In order to meet that expectation propagating dynamism pass must use output data object name as prefix. Additionally, propagating pass must be applied before converting shape notation pass in order to make output shape in IE notation, not MDK, as MyriadInferRequest::GetResult is expecting. Signed-off-by: Gladilov, Gleb <gleb.gladilov@intel.com>
This commit is contained in:
parent
447dd3570d
commit
4e0c7a217f
@ -243,6 +243,8 @@ public:
|
|||||||
|
|
||||||
Pass::Ptr replaceGemmByConv();
|
Pass::Ptr replaceGemmByConv();
|
||||||
|
|
||||||
|
Pass::Ptr propagateDynamismToOutputs();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
StageBuilder::Ptr _stageBuilder;
|
StageBuilder::Ptr _stageBuilder;
|
||||||
BackEnd::Ptr _backEnd;
|
BackEnd::Ptr _backEnd;
|
||||||
|
@ -91,6 +91,14 @@ PassSet::Ptr PassManager::buildMiddleEnd() {
|
|||||||
// Convert shape notation
|
// Convert shape notation
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
|
// MyriadInferRequest::GetResult expects output shape data object
|
||||||
|
// to be in IE notation in case of dynamic data object
|
||||||
|
// propagateDynamismToOutputs must be applied before convertShapeNotation
|
||||||
|
// to mark shape in IE notation, not MDK notation as output
|
||||||
|
ADD_PASS(propagateDynamismToOutputs);
|
||||||
|
ADD_DUMP_PASS("propagateDynamismToOutputs");
|
||||||
|
|
||||||
ADD_PASS(convertShapeNotation);
|
ADD_PASS(convertShapeNotation);
|
||||||
ADD_DUMP_PASS("convertShapeNotation");
|
ADD_DUMP_PASS("convertShapeNotation");
|
||||||
|
|
||||||
|
@ -0,0 +1,83 @@
|
|||||||
|
// Copyright (C) 2020 Intel Corporation
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "vpu/middleend/pass_manager.hpp"
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace vpu {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class PassImpl final : public Pass {
|
||||||
|
public:
|
||||||
|
explicit PassImpl(StageBuilder::Ptr stageBuilder) : _stageBuilder(std::move(stageBuilder)) {}
|
||||||
|
|
||||||
|
void run(const Model& model) override {
|
||||||
|
for (const auto& data : model->datas()) {
|
||||||
|
if (data->usage() != DataUsage::Output || data->parentDataToShapeEdge() != nullptr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& producer = data->producer();
|
||||||
|
VPU_THROW_UNLESS(producer, "Output data must have a producer, but {} doesn't have", data->name());
|
||||||
|
|
||||||
|
if (producer->type() != StageType::Convert) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
VPU_THROW_UNLESS(producer->numInputs() == 1,
|
||||||
|
"Only single input producers are supported, but {} has {} inputs",
|
||||||
|
producer->name(), producer->numInputs());
|
||||||
|
|
||||||
|
const auto& input = producer->input(0);
|
||||||
|
const auto& parentDataToShapeEdge = input->parentDataToShapeEdge();
|
||||||
|
if (parentDataToShapeEdge == nullptr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const auto parent = parentDataToShapeEdge->parent();
|
||||||
|
|
||||||
|
// MyriadInferRequest::GetResult assumes that dynamic data object has shape data object
|
||||||
|
// with the same name + suffix "@shape"
|
||||||
|
const auto shapeName = data->name() + "@shape";
|
||||||
|
const auto& shapeOutput = model->addOutputData(shapeName, parent->desc());
|
||||||
|
|
||||||
|
if (parent->numConsumers() > 0) {
|
||||||
|
_stageBuilder->addCopyStage(
|
||||||
|
model,
|
||||||
|
"copy-for-dynamic-output",
|
||||||
|
nullptr,
|
||||||
|
parent,
|
||||||
|
shapeOutput,
|
||||||
|
"PropagateDynamismToOutput");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
const auto parentProducerEdge = parent->producerEdge();
|
||||||
|
VPU_THROW_UNLESS(parentProducerEdge != nullptr,
|
||||||
|
"Data containing shape is expected to have a producer, but {} doesn't have", parent->name());
|
||||||
|
|
||||||
|
for (const auto& dataToShapeEdge : parent->childDataToShapeEdges()) {
|
||||||
|
model->replaceDataToShapeParent(dataToShapeEdge, shapeOutput);
|
||||||
|
}
|
||||||
|
|
||||||
|
model->replaceStageOutput(parentProducerEdge, shapeOutput);
|
||||||
|
model->removeUnusedData(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
model->connectDataWithShape(shapeOutput, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
StageBuilder::Ptr _stageBuilder;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
Pass::Ptr PassManager::propagateDynamismToOutputs() {
|
||||||
|
return std::make_shared<PassImpl>(_stageBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace vpu
|
@ -50,14 +50,13 @@ void FrontEnd::parseDSR(const Model& model, const ie::CNNLayerPtr& layer, const
|
|||||||
// Create the second output with shape in case of dynamic output
|
// Create the second output with shape in case of dynamic output
|
||||||
const auto& shapeOutput = model->addOutputData(dataOutput->name() + "@shape", shape->desc());
|
const auto& shapeOutput = model->addOutputData(dataOutput->name() + "@shape", shape->desc());
|
||||||
|
|
||||||
model->replaceStageOutput(shapeProducerEdge, shapeOutput);
|
|
||||||
model->connectDataWithShape(shapeOutput, dataOutput);
|
|
||||||
|
|
||||||
for (const auto& dataToShapeEdge : shape->childDataToShapeEdges()) {
|
for (const auto& dataToShapeEdge : shape->childDataToShapeEdges()) {
|
||||||
model->replaceDataToShapeParent(dataToShapeEdge, shapeOutput);
|
model->replaceDataToShapeParent(dataToShapeEdge, shapeOutput);
|
||||||
}
|
}
|
||||||
|
model->replaceStageOutput(shapeProducerEdge, shapeOutput);
|
||||||
model->removeUnusedData(shape);
|
model->removeUnusedData(shape);
|
||||||
|
|
||||||
|
model->connectDataWithShape(shapeOutput, dataOutput);
|
||||||
} else {
|
} else {
|
||||||
model->connectDataWithShape(shape, dataOutput);
|
model->connectDataWithShape(shape, dataOutput);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user