[IE][VPU]: Fix injection in dynamic case (#4343)

* Redirect StageDependencies from injected stage to the parent of the injection.
* Change StageDependencyEdge to be Stage<->Stage connection. In fact, it affects only stages order, so it would be more natural (also more convenient) to represent it so.
* Add injectedStageDependencies to InjectionEdge to be able to distinguish those dependencies that were added to hwStage during the injection process and make the revertion correct.
This commit is contained in:
Andrew Bakalin 2021-02-17 17:39:07 +03:00 committed by GitHub
parent 7df5a98dde
commit 695d2a90ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 519 additions and 496 deletions

View File

@ -126,8 +126,6 @@ class DataNode final :
VPU_MODEL_ATTRIBUTE(StageOutput, producerEdge, nullptr)
VPU_MODEL_ATTRIBUTE_PTR_RANGE(StageInputList, consumerEdges)
VPU_MODEL_ATTRIBUTE_PTR_RANGE(StageDependencyList, dependentStagesEdges)
VPU_MODEL_ATTRIBUTE(StageTempBuffer, tempBufferEdge, nullptr)
/**
@ -282,7 +280,6 @@ private:
private:
inline DataNode() :
_consumerEdges(&StageInputEdge::_posInData),
_dependentStagesEdges(&StageDependencyEdge::_posInData),
_childDataToDataEdges(&DataToDataAllocationEdge::_posInData),
_childDataToShapeEdges(&DataToShapeAllocationEdge::_posInData),
_posInModel(this) {

View File

@ -37,28 +37,6 @@ private:
friend DataNode;
};
//
// StageDependencyEdge defines that some data should be calculated before the stage starts
// but this data is not an input for the stage, e.g. this data is used as a shape for stage output.
//
class StageDependencyEdge final :
public EnableHandle,
public EnableCustomAttributes {
VPU_MODEL_ATTRIBUTE(Data, dependency, nullptr)
VPU_MODEL_ATTRIBUTE(Stage, dependentStage, nullptr)
private:
StageDependencyEdge() : _posInData(this) {}
private:
StageDependencyPtrList::iterator _ptrPosInModel;
StageDependencyListNode _posInData;
friend ModelObj;
friend DataNode;
};
//
// StageOutputEdge
//
@ -209,6 +187,7 @@ class InjectionEdge final :
VPU_MODEL_ATTRIBUTE(Stage, parent, nullptr)
VPU_MODEL_ATTRIBUTE(StagePtr, child, nullptr)
VPU_MODEL_ATTRIBUTE(int, portInd, -1)
VPU_MODEL_ATTRIBUTE(StageDependencyVector, injectedStageDependencies, {})
private:
InjectionEdge() : _posInStage(this) {}
@ -222,4 +201,25 @@ private:
friend StageNode;
};
//
// StageDependencyEdge defines that some stage should be executed before other
//
class StageDependencyEdge final :
public EnableHandle,
public EnableCustomAttributes {
VPU_MODEL_ATTRIBUTE(Stage, parent, nullptr)
VPU_MODEL_ATTRIBUTE(Stage, child, nullptr)
private:
StageDependencyEdge() : _posInStage(this) {}
private:
StageDependencyPtrList::iterator _ptrPosInModel;
StageDependencyListNode _posInStage;
friend ModelObj;
friend StageNode;
};
} // namespace vpu

View File

@ -139,8 +139,8 @@ public:
const Data& data);
StageDependency addStageDependency(
const Stage& stage,
const Data& data);
const Stage& parent,
const Stage& child);
StageTempBuffer addTempBuffer(
const Stage& stage,
@ -158,16 +158,16 @@ public:
const StageOutput& edge,
const Data& newOutput);
void replaceStageDependency(
void replaceStageDependencyParent(
const StageDependency& edge,
const Data& newDependency);
const Stage& newParent);
void replaceDependentStage(
void replaceStageDependencyChild(
const StageDependency& edge,
const Stage& newDependentStage);
const Stage& newChild);
void removeStageDependency(const StageDependency& edge);
void removeStageDependency(const Stage& stage, const Data& dependency);
void removeStageDependency(const Stage& parent, const Stage& child);
//
// Stage <-> Stage edges

View File

@ -411,6 +411,9 @@ class StageNode :
VPU_MODEL_ATTRIBUTE_PTR_RANGE(StageTempBufferVector, tempBufferEdges)
VPU_MODEL_ATTRIBUTE_PTR_RANGE(StageDependencyVector, parentDependencyEdges)
VPU_MODEL_ATTRIBUTE_PTR_RANGE(StageDependencyVector, childDependencyEdges)
VPU_MODEL_ATTRIBUTE(Injection, parentStageEdge, nullptr)
VPU_MODEL_ATTRIBUTE(Injection, injectedStageEdge, nullptr)

View File

@ -310,22 +310,6 @@ void BackEnd::dumpModelToDot(
}
}
//
// Dump Data->Stage edges
//
for (const auto& data : model->datas()) {
for (const auto& dependentStageEdge : data->dependentStagesEdges()) {
out.append("%s -> %s [", dataDotName(data), stageDotName(dependentStageEdge->dependentStage()));
{
VPU_DOT_IDENT(out);
DotLabel lbl("Extra dependency", out);
}
out.append("];");
}
}
//
// Dump Data<->Data edges
//
@ -395,6 +379,16 @@ void BackEnd::dumpModelToDot(
}
out.append("}");
}
for (const auto& stageDependencyEdge : stage->childDependencyEdges()) {
out.append("%s -> %s [", stageDotName(stage), stageDotName(stageDependencyEdge->child()));
{
VPU_DOT_IDENT(out);
DotLabel lbl("Extra dependency", out);
}
out.append("];");
}
}
}
out.append("}");

View File

@ -217,8 +217,7 @@ bool Allocator::allocateData(const Data& data) {
VPU_INTERNAL_CHECK(data->producerEdge() != nullptr,
"Allocation check failed: data {} with usage {} must have producer, but actually it doesn't",
data->name(), data->usage());
VPU_INTERNAL_CHECK(!data->consumers().empty() || !data->childDataToShapeEdges().empty() ||
!data->dependentStagesEdges().empty(),
VPU_INTERNAL_CHECK(!data->consumers().empty() || !data->childDataToShapeEdges().empty(),
"Allocation check failed: data {} with usage {} must have at least one data/stage "
"depending on it, but it doesn't have either",
data->name(), data->usage());

View File

@ -53,13 +53,14 @@ void PassImpl::run(const Model& model) {
DataDesc(DataType::S32, DimsOrder::C, {convertedShape->desc().totalDimSize()}),
generator);
_stageBuilder->addGatherStage(model,
shape->name() + "@convert-notation",
nullptr,
shape,
gatherIndices,
convertedShape,
Dim::C);
const auto& gather = _stageBuilder->addGatherStage(
model,
shape->name() + "@convert-notation",
nullptr,
shape,
gatherIndices,
convertedShape,
Dim::C);
for (const auto& dataToShapeEdge : shape->childDataToShapeEdges()) {
model->replaceDataToShapeParent(dataToShapeEdge, convertedShape);
@ -81,18 +82,18 @@ void PassImpl::run(const Model& model) {
continue;
}
const auto& dependentStagesEdges = convertedShape->dependentStagesEdges();
const auto& stageDependencyEdges = gather->childDependencyEdges();
for (const auto& consumer : child->consumers()) {
const auto it = std::find_if(dependentStagesEdges.begin(), dependentStagesEdges.end(), [&consumer](const StageDependency& edge) {
return edge->dependentStage() == consumer;
const auto it = std::find_if(stageDependencyEdges.begin(), stageDependencyEdges.end(), [&consumer](const StageDependency& edge) {
return edge->child() == consumer;
});
if (it != dependentStagesEdges.end()) {
if (it != stageDependencyEdges.end()) {
continue;
}
model->addStageDependency(consumer, convertedShape);
model->addStageDependency(gather, consumer);
}
}
}

View File

@ -391,34 +391,25 @@ StageOutput ModelObj::addStageOutput(
return edge;
}
StageDependency ModelObj::addStageDependency(const Stage& stage, const Data& data) {
for (const auto& dependentStageEdge : data->dependentStagesEdges()) {
VPU_THROW_UNLESS(dependentStageEdge->dependentStage() != stage,
"Adding stage dependency for {} with type {} failed: data {} with usage {} is already its dependency",
stage->name(), stage->type(), data->name(), data->usage());
StageDependency ModelObj::addStageDependency(const Stage& parent, const Stage& child) {
for (const auto& dependentStageEdge : parent->childDependencyEdges()) {
VPU_THROW_UNLESS(dependentStageEdge->child() != child,
"Adding dependent stage for {} with type {} failed: stage {} with type {} is already its dependent stage",
parent->name(), parent->type(), child->name(), child->type());
}
for (const auto& input : stage->inputs()) {
VPU_THROW_UNLESS(data != input,
"Adding stage dependency for {} with type {} failed: data {} with usage {} is already its input",
stage->name(), stage->type(), data->name(), data->usage());
}
VPU_THROW_UNLESS(data->producer() != nullptr,
"Adding stage dependency for {} with type {} failed: data {} with usage {} should have producer, "
"but actually it doesn't", stage->name(), stage->type(), data->name(), data->usage());
_resetStageOrder = true;
std::shared_ptr<StageDependencyEdge> edge(new StageDependencyEdge);
edge->_ptrPosInModel = _stageDependencyEdgePtrList.emplace(_stageDependencyEdgePtrList.end(), edge);
edge->_dependency = data;
edge->_dependentStage = stage;
edge->_parent = parent;
edge->_child = child;
data->_dependentStagesEdges.push_back(edge);
parent->_childDependencyEdges.push_back(edge);
child->_parentDependencyEdges.push_back(edge);
setStagesOrder(data->producerEdge()->producer(), stage);
setStagesOrder(parent, child);
return edge;
}
@ -681,111 +672,84 @@ void ModelObj::replaceStageOutput(
}
}
void ModelObj::replaceStageDependency(
void ModelObj::replaceStageDependencyParent(
const StageDependency& edge,
const Data& newDependency) {
const auto previousDependency = edge->dependency();
const auto dependentStage = edge->dependentStage();
const Stage& newParent) {
const auto previousParent = edge->parent();
const auto child = edge->child();
for (const auto& dependentStageEdge : newDependency->dependentStagesEdges()) {
VPU_THROW_UNLESS(dependentStageEdge->dependentStage() != dependentStage,
"replaceStageDependency failed for dependency {} with usage {} and dependentStage {} with type {}: "
"new dependency {} with usage {} is already dependency for dependent stage", previousDependency->name(), previousDependency->usage(),
dependentStage->name(), dependentStage->type(), newDependency->name(), newDependency->usage());
for (const auto& dependentStageEdge : newParent->childDependencyEdges()) {
VPU_THROW_UNLESS(dependentStageEdge->child() != child,
"replaceStageDependencyParent failed for {} with type {}: stage {} with type {} is already its parent",
child->name(), child->type(), newParent->name(), newParent->type());
}
for (const auto& input : dependentStage->inputs()) {
VPU_THROW_UNLESS(newDependency != input,
"replaceStageDependency failed for dependency {} with usage {} and dependentStage {} with type {}: "
"new dependency {} with usage {} is already input for dependent stage", previousDependency->name(), previousDependency->usage(),
dependentStage->name(), dependentStage->type(), newDependency->name(), newDependency->usage());
}
VPU_THROW_UNLESS(newDependency->producer() != nullptr,
"replaceStageDependency failed for dependency {} with usage {} and dependentStage {} with type {}: "
"newDependency {} with usage {} has no producer", previousDependency->name(), previousDependency->usage(),
dependentStage->name(), dependentStage->type(), newDependency->name(), newDependency->usage());
VPU_THROW_UNLESS(previousDependency->producer() != nullptr,
"replaceStageDependency failed for dependency {} with usage {} and dependentStage {} with type {}: "
"previous dependency has no producer",
previousDependency->name(), previousDependency->usage(), dependentStage->name(), dependentStage->type());
_resetStageOrder = true;
previousDependency->_dependentStagesEdges.erase(edge);
auto& childDependencyEdges = previousParent->_childDependencyEdges;
childDependencyEdges.erase(std::remove(childDependencyEdges.begin(), childDependencyEdges.end(), edge));
removeStagesOrder(previousDependency->producer(), dependentStage);
removeStagesOrder(previousParent, child);
edge->_dependency = newDependency;
newDependency->_dependentStagesEdges.push_back(edge);
edge->_parent = newParent;
newParent->_childDependencyEdges.push_back(edge);
setStagesOrder(newDependency->producerEdge()->producer(), dependentStage);
setStagesOrder(newParent, child);
}
void ModelObj::replaceDependentStage(
void ModelObj::replaceStageDependencyChild(
const StageDependency& edge,
const Stage& newDependentStage) {
const auto dependency = edge->dependency();
const auto previousDependentStage = edge->dependentStage();
const Stage& newChild) {
const auto parent = edge->parent();
const auto previousChild = edge->child();
for (const auto& dependentStageEdge : dependency->dependentStagesEdges()) {
VPU_THROW_UNLESS(dependentStageEdge->dependentStage() != newDependentStage,
"replaceDependentStage failed for dependency {} with usage {} and dependentStage {} with type {}: "
"new dependent stage {} with type {} is already dependent stage for dependency", dependency->name(), dependency->usage(),
previousDependentStage->name(), previousDependentStage->type(), newDependentStage->name(), newDependentStage->type());
for (const auto& dependentStageEdge : parent->childDependencyEdges()) {
VPU_THROW_UNLESS(dependentStageEdge->child() != newChild,
"replaceStageDependencyChild failed for {} with type {}: stage {} with type {} is already its child",
parent->name(), parent->type(), newChild->name(), newChild->type());
}
for (const auto& input : newDependentStage->inputs()) {
VPU_THROW_UNLESS(dependency != input,
"replaceDependentStage failed for dependency {} with usage {} and dependentStage {} with type {}: "
"new dependent stage {} with type {} already has dependency as its input", dependency->name(), dependency->usage(),
previousDependentStage->name(), previousDependentStage->type(), newDependentStage->name(), newDependentStage->type());
}
VPU_THROW_UNLESS(dependency->producer() != nullptr,
"replaceDependentStage failed for dependency {} with usage {} and dependentStage {} with type {}: "
"dependency has no producer",
dependency->name(), dependency->usage(), previousDependentStage->name(), previousDependentStage->type());
_resetStageOrder = true;
removeStagesOrder(dependency->producer(), previousDependentStage);
auto& parentDependencyEdges = previousChild->_parentDependencyEdges;
parentDependencyEdges.erase(std::remove(parentDependencyEdges.begin(), parentDependencyEdges.end(), edge));
edge->_dependentStage = newDependentStage;
removeStagesOrder(parent, previousChild);
setStagesOrder(dependency->producer(), newDependentStage);
edge->_child = newChild;
newChild->_parentDependencyEdges.push_back(edge);
setStagesOrder(parent, newChild);
}
void ModelObj::removeStageDependency(const StageDependency& edge) {
const auto dependency = edge->dependency();
const auto dependentStage = edge->dependentStage();
VPU_THROW_UNLESS(dependency->producer(),
"removeStageDependency failed for dependency {} with usage {} and dependentStage {} with type {}: dependency has no producer",
dependency->name(), dependency->usage(), dependentStage->name(), dependentStage->type());
const auto parent = edge->parent();
const auto child = edge->child();
_resetStageOrder = true;
dependency->_dependentStagesEdges.erase(edge);
auto& childDependencyEdges = parent->_childDependencyEdges;
childDependencyEdges.erase(std::remove(childDependencyEdges.begin(), childDependencyEdges.end(), edge));
auto& parentDependencyEdges = child->_parentDependencyEdges;
parentDependencyEdges.erase(std::remove(parentDependencyEdges.begin(), parentDependencyEdges.end(), edge));
removeStagesOrder(dependency->producer(), dependentStage);
removeStagesOrder(parent, child);
VPU_THROW_UNLESS(edge->_ptrPosInModel != _stageDependencyEdgePtrList.end(),
"removeStageDependency failed for dependency {} with usage {} and dependentStage {} with type {}: no such edge in Model's DataToShapeEdges list",
dependency->name(), dependency->usage(), dependentStage->name(), dependentStage->type());
"removeStageDependency failed for parent {} with type {} and child {} with type {}: no such edge in Model's DataToShapeEdges list",
parent->name(), parent->type(), child->name(), child->type());
_stageDependencyEdgePtrList.erase(edge->_ptrPosInModel);
}
void ModelObj::removeStageDependency(const Stage& stage, const Data& dependency) {
const auto& dependentStagesEdges = dependency->dependentStagesEdges();
void ModelObj::removeStageDependency(const Stage& parent, const Stage& child) {
const auto& childDependencyEdges = parent->childDependencyEdges();
const auto it = std::find_if(dependentStagesEdges.begin(), dependentStagesEdges.end(), [&stage](const StageDependency& edge) {
return edge->dependentStage() == stage;
const auto it = std::find_if(childDependencyEdges.begin(), childDependencyEdges.end(), [&child](const StageDependency& edge) {
return edge->child() == child;
});
if (it != dependentStagesEdges.end()) {
if (it != childDependencyEdges.end()) {
const auto stageDependencyEdge = *it;
removeStageDependency(stageDependencyEdge);
}
@ -923,6 +887,22 @@ Injection ModelObj::injectStageImpl(
parent->_injectedStageEdge = edge;
child->_parentStageEdge = edge;
//
// Redirect child stage dependencies to parent.
//
const auto parentDependencyEdges = child->_parentDependencyEdges;
for (const auto& parentDependencyEdge : parentDependencyEdges) {
edge->_injectedStageDependencies.push_back(parentDependencyEdge);
replaceStageDependencyChild(parentDependencyEdge, parent);
}
const auto childDependencyEdges = child->_childDependencyEdges;
for (const auto& childDependencyEdge : childDependencyEdges) {
edge->_injectedStageDependencies.push_back(childDependencyEdge);
replaceStageDependencyParent(childDependencyEdge, parent);
}
//
// Redirect child inputs to parent.
//
@ -1049,6 +1029,19 @@ void ModelObj::revertInjection(const Injection& edge) {
childStage->_ptrPosInModel = _stagePtrList.emplace(_stagePtrList.end(), childStage);
//
// Redirect stage dependencies back to child.
//
for (const auto& injectedStageDependency : edge->injectedStageDependencies()) {
if (parentStage == injectedStageDependency->parent()) {
replaceStageDependencyParent(injectedStageDependency, childStage);
} else {
replaceStageDependencyChild(injectedStageDependency, childStage);
}
}
edge->_injectedStageDependencies.clear();
//
// Remove Injection Edge from parent and child Stage.
//
@ -1706,7 +1699,7 @@ DataToShapeAllocation ModelObj::connectDataWithShape(
if (childProducer && isStageDependencyNeeded(childProducer, parent)) {
// Shape and data are produced from different stages, make sure that shape is calculated before data
addStageDependency(childProducer, parent);
addStageDependency(parent->producer(), childProducer);
}
return edge;
@ -1724,11 +1717,14 @@ void ModelObj::replaceDataToShapeParent(
const auto& childProducer = child->producer();
if (childProducer != nullptr) {
removeStageDependency(childProducer, oldParent);
const auto& oldParentProducer = oldParent->producer();
if (oldParentProducer != nullptr) {
removeStageDependency(oldParent->producer(), childProducer);
}
if (isStageDependencyNeeded(childProducer, newParent)) {
// Shape and data are produced from different stages, make sure that shape is calculated before data
addStageDependency(childProducer, newParent);
addStageDependency(newParent->producer(), childProducer);
}
}
}
@ -1749,15 +1745,16 @@ void ModelObj::replaceDataToShapeChild(
newChild->_parentDataToShapeEdge = edge;
const auto& oldChildProducer = oldChild->producer();
if (oldChildProducer != nullptr) {
removeStageDependency(oldChildProducer, parent);
const auto& parentProducer = parent->producer();
if (parentProducer != nullptr && oldChildProducer != nullptr) {
removeStageDependency(parentProducer, oldChildProducer);
}
const auto& newChildProducer = newChild->producer();
if (newChildProducer && isStageDependencyNeeded(newChildProducer, parent)) {
// Shape and data are produced from different stages, make sure that shape is calculated before data
addStageDependency(newChildProducer, parent);
addStageDependency(parent->producer(), newChildProducer);
}
}
@ -1839,8 +1836,9 @@ void ModelObj::disconnectDatas(const DataToShapeAllocation& edge) {
_shapeEdgePtrList.erase(edge->_ptrPosInModel);
const auto& childProducer = child->producer();
if (childProducer != nullptr) {
removeStageDependency(childProducer, parent);
const auto& parentProducer = parent->producer();
if (parentProducer != nullptr && childProducer != nullptr) {
removeStageDependency(parentProducer, childProducer);
}
}
@ -1893,7 +1891,10 @@ void ModelObj::disconnectStage(const Stage& stage) {
for (const auto& outEdge : stage->_outputEdges) {
// Disconnect from dependency
if (const auto& dataToShapeEdge = outEdge->output()->parentDataToShapeEdge()) {
removeStageDependency(stage, dataToShapeEdge->parent());
const auto& parentProducer = dataToShapeEdge->parent()->producer();
if (parentProducer != nullptr) {
removeStageDependency(parentProducer, stage);
}
}
// Disconnect from consumers
for (const auto& consumerEdge : outEdge->_output->_consumerEdges) {

View File

@ -163,7 +163,10 @@ void TestModel::createOutputs(std::vector<DataDesc> descriptors) {
}
}
Stage TestModel::addStage(const std::vector<InputInfo>& curInputInfos, const std::vector<OutputInfo>& curOutputInfos) {
Stage TestModel::addStage(
const std::vector<InputInfo>& curInputInfos,
const std::vector<OutputInfo>& curOutputInfos,
StageType stageType) {
DataVector curInputs;
for (const auto& info : curInputInfos) {
if (info.type == InputType::Original) {
@ -188,7 +191,7 @@ Stage TestModel::addStage(const std::vector<InputInfo>& curInputInfos, const std
auto stage = _model->addNewStage<TestStage>(
formatString("Stage %m%m%d", std::setw(2), std::setfill('0'), _stages.size()),
StageType::None,
stageType,
nullptr,
curInputs,
curOutputs);

View File

@ -95,7 +95,10 @@ public:
void createInputs(std::vector<DataDesc> inputDescs = {});
void createOutputs(std::vector<DataDesc> outputDescs = {});
Stage addStage(const std::vector<InputInfo>& curInputInfos, const std::vector<OutputInfo>& curOutputInfos);
Stage addStage(
const std::vector<InputInfo>& curInputInfos,
const std::vector<OutputInfo>& curOutputInfos,
StageType stageType = StageType::None);
void setStageDataOrderInfo(
int stageInd,

View File

@ -328,12 +328,12 @@ TEST_F(DataToShapeEdgeProcessingTests, ReplaceDataToShapeParentReplacesConnectio
ASSERT_EQ(finalShape->childDataToShapeEdges().front(), dataToShapeEdge);
ASSERT_EQ(dataToShapeEdge->parent(), finalShape);
ASSERT_TRUE(initialShape->dependentStagesEdges().empty());
ASSERT_FALSE(finalShape->dependentStagesEdges().empty());
ASSERT_TRUE(firstShapeProcessor->childDependencyEdges().empty());
ASSERT_FALSE(secondShapeProcessor->childDependencyEdges().empty());
const auto& stageDependencyEdge = finalShape->dependentStagesEdges().front();
ASSERT_EQ(stageDependencyEdge->dependentStage(), dataProcessor);
ASSERT_EQ(stageDependencyEdge->dependency(), finalShape);
const auto& stageDependencyEdge = secondShapeProcessor->childDependencyEdges().front();
ASSERT_EQ(stageDependencyEdge->child(), dataProcessor);
ASSERT_EQ(stageDependencyEdge->parent(), secondShapeProcessor);
}
TEST_F(DataToShapeEdgeProcessingTests, ReplaceDataToShapeChildReplacesConnections) {
@ -372,11 +372,11 @@ TEST_F(DataToShapeEdgeProcessingTests, ReplaceDataToShapeChildReplacesConnection
ASSERT_EQ(finalData->parentDataToShapeEdge(), dataToShapeEdge);
ASSERT_EQ(dataToShapeEdge->child(), finalData);
ASSERT_FALSE(processedShape->dependentStagesEdges().empty());
const auto& stageDependencyEdge = processedShape->dependentStagesEdges().front();
ASSERT_FALSE(shapeProcessor->childDependencyEdges().empty());
const auto& stageDependencyEdge = shapeProcessor->childDependencyEdges().front();
ASSERT_EQ(stageDependencyEdge->dependentStage(), secondDataProcessor);
ASSERT_EQ(stageDependencyEdge->dependency(), processedShape);
ASSERT_EQ(stageDependencyEdge->child(), secondDataProcessor);
ASSERT_EQ(stageDependencyEdge->parent(), shapeProcessor);
}
TEST_F(DataToShapeEdgeProcessingTests, DisconnectDatasRemovesConnections) {
@ -408,7 +408,7 @@ TEST_F(DataToShapeEdgeProcessingTests, DisconnectDatasRemovesConnections) {
ASSERT_EQ(processedData->parentDataToShapeEdge(), nullptr);
ASSERT_TRUE(processedShape->childDataToShapeEdges().empty());
ASSERT_TRUE(processedShape->dependentStagesEdges().empty());
ASSERT_TRUE(shapeProcessor->childDependencyEdges().empty());
}
} // namespace vpu

View File

@ -22,266 +22,9 @@ protected:
TestModel _testModel;
};
TEST_F(StageDependencyEdgeProcessingTests, AddStageDependencyAssertsOnNetworkInput) {
//
// -> [Output]
// [Input] -> (Stage)
// -> [Output]
//
const DataDesc desc{1};
_testModel.createInputs({desc});
_testModel.createOutputs({desc, desc});
auto stage = _testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::fromNetwork(0),
OutputInfo::fromNetwork(1)});
auto model = _testModel.getBaseModel();
ASSERT_ANY_THROW(model->addStageDependency(stage, _testModel.getInputs().front()));
}
TEST_F(StageDependencyEdgeProcessingTests, AddStageDependencyAssertsOnStageInput) {
//
// -> [Output]
// [Input] -> (Stage)
// -> [Data] -> (Stage) -> [Output]
//
const DataDesc desc{1};
_testModel.createInputs({desc});
_testModel.createOutputs({desc, desc});
_testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::intermediate(desc),
OutputInfo::fromNetwork(1)});
auto stage = _testModel.addStage({InputInfo::fromPrevStage(0).output(0)}, {OutputInfo::fromNetwork(0)});
auto model = _testModel.getBaseModel();
ASSERT_ANY_THROW(model->addStageDependency(stage, stage->input(0)));
}
TEST_F(StageDependencyEdgeProcessingTests, AddStageDependencyDoesNotAssertOnOutputData) {
TEST_F(StageDependencyEdgeProcessingTests, AddStageDependencyDoesNotAssertOnOutputProducer) {
//
// -> [Data] -> (Stage) -> [Output]
// [Input] -> (Stage) |
// -> [Data] ------------> (Stage) -> [Output]
//
const DataDesc desc{1};
_testModel.createInputs({desc});
_testModel.createOutputs({desc, desc});
_testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::intermediate(desc),
OutputInfo::intermediate(desc)});
auto dependentStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(0)}, {OutputInfo::fromNetwork(0)});
auto dependencyProducer = _testModel.addStage({InputInfo::fromPrevStage(0).output(1)}, {OutputInfo::fromNetwork(1)});
auto model = _testModel.getBaseModel();
ASSERT_NO_THROW(model->addStageDependency(dependentStage, dependencyProducer->output(0)));
}
TEST_F(StageDependencyEdgeProcessingTests, AddStageDependencyAssertsIfDependencyExists) {
//
// -> [Data] -> (Stage) -> [Output]
// [Input] -> (Stage) |
// -> [Data] ------------> (Stage) -> [Output]
//
const DataDesc desc{1};
_testModel.createInputs({desc});
_testModel.createOutputs({desc, desc});
_testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::intermediate(desc),
OutputInfo::intermediate(desc)});
auto dependentStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(0)}, {OutputInfo::fromNetwork(0)});
auto dependencyProducer = _testModel.addStage({InputInfo::fromPrevStage(0).output(1)}, {OutputInfo::fromNetwork(1)});
auto model = _testModel.getBaseModel();
ASSERT_NO_THROW(model->addStageDependency(dependentStage, dependencyProducer->output(0)));
ASSERT_ANY_THROW(model->addStageDependency(dependentStage, dependencyProducer->output(0)));
}
TEST_F(StageDependencyEdgeProcessingTests, NetWithTwoStagesHasCorrectExecOrder) {
//
// -> [Data] -> (Stage) -> [Data] -> (Stage) -> [Output]
// [Input] -> (Stage) |
// -> [Data] ------------> (Stage) -> [Output]
//
const DataDesc desc{1};
_testModel.createInputs({desc});
_testModel.createOutputs({desc, desc});
_testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::intermediate(desc),
OutputInfo::intermediate(desc)});
auto dependentStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(0)}, {OutputInfo::fromNetwork(0)});
auto dependencyProducer = _testModel.addStage({InputInfo::fromPrevStage(0).output(1)}, {OutputInfo::intermediate(desc)});
_testModel.addStage({InputInfo::fromPrevStage(2)}, {OutputInfo::fromNetwork(1)});
auto model = _testModel.getBaseModel();
ASSERT_TRUE(checkExecutionOrder(model, {dependentStage->id(), dependencyProducer->id()}));
ASSERT_NO_THROW(model->addStageDependency(dependentStage, dependencyProducer->output(0)));
ASSERT_TRUE(checkExecutionOrder(model, {dependencyProducer->id(), dependentStage->id()}));
}
TEST_F(StageDependencyEdgeProcessingTests, NetWithThreeStagesHasCorrectExecOrder) {
//
// -> [Data] -> (Stage) -> [Data] -> (Stage) -> [Data] -> (Stage) -> [Output]
// [Input] -> (Stage) |
// -> [Data] ---------------------------------> (Stage) -> [Output]
//
const DataDesc desc{1};
_testModel.createInputs({desc});
_testModel.createOutputs({desc, desc});
_testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::intermediate(desc),
OutputInfo::intermediate(desc)});
auto dependentStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(0)}, {OutputInfo::fromNetwork(0)});
_testModel.addStage({InputInfo::fromPrevStage(0).output(1)}, {OutputInfo::intermediate(desc)});
auto dependencyProducer = _testModel.addStage({InputInfo::fromPrevStage(2)}, {OutputInfo::intermediate(desc)});
_testModel.addStage({InputInfo::fromPrevStage(3)}, {OutputInfo::fromNetwork(1)});
auto model = _testModel.getBaseModel();
ASSERT_TRUE(checkExecutionOrder(model, {dependentStage->id(), dependencyProducer->id()}));
ASSERT_NO_THROW(model->addStageDependency(dependentStage, dependencyProducer->output(0)));
ASSERT_TRUE(checkExecutionOrder(model, {dependencyProducer->id(), dependentStage->id()}));
}
TEST_F(StageDependencyEdgeProcessingTests, ReplaceStageDependencyAssertsOnNetworkInput) {
//
// -> [Data] -> (Stage) -> [Output]
// [Input] -> (Stage) |
// -> [Data] ------------> (Stage) -> [Output]
//
const DataDesc desc{1};
_testModel.createInputs({desc});
_testModel.createOutputs({desc, desc});
_testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::intermediate(desc),
OutputInfo::intermediate(desc)});
auto dependentStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(0)}, {OutputInfo::fromNetwork(0)});
auto dependencyProducer = _testModel.addStage({InputInfo::fromPrevStage(0).output(1)}, {OutputInfo::fromNetwork(1)});
auto model = _testModel.getBaseModel();
ASSERT_NO_THROW(model->addStageDependency(dependentStage, dependencyProducer->output(0)));
const auto edge = dependencyProducer->output(0)->dependentStagesEdges().front();
ASSERT_ANY_THROW(model->replaceStageDependency(edge, _testModel.getInputs().front()));
}
TEST_F(StageDependencyEdgeProcessingTests, ReplaceStageDependencyAssertsOnStageInput) {
//
// -> [Data] -> (Stage) -> [Output]
// [Input] -> (Stage) |
// -> [Data] ------------> (Stage) -> [Output]
//
const DataDesc desc{1};
_testModel.createInputs({desc});
_testModel.createOutputs({desc, desc});
_testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::intermediate(desc),
OutputInfo::intermediate(desc)});
auto dependentStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(0)}, {OutputInfo::fromNetwork(0)});
auto dependencyProducer = _testModel.addStage({InputInfo::fromPrevStage(0).output(1)}, {OutputInfo::fromNetwork(1)});
auto model = _testModel.getBaseModel();
ASSERT_NO_THROW(model->addStageDependency(dependentStage, dependencyProducer->output(0)));
const auto edge = dependencyProducer->output(0)->dependentStagesEdges().front();
ASSERT_ANY_THROW(model->replaceStageDependency(edge, dependentStage->input(0)));
}
TEST_F(StageDependencyEdgeProcessingTests, ReplaceStageDependencyAssertsIfDependencyExists) {
//
// -> [Data] -> (Stage) -> [Output]
// [Input] -> (Stage) |
// -> [Data] ------------> (Stage) -> [Output]
//
const DataDesc desc{1};
_testModel.createInputs({desc});
_testModel.createOutputs({desc, desc});
_testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::intermediate(desc),
OutputInfo::intermediate(desc)});
auto dependentStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(0)}, {OutputInfo::fromNetwork(0)});
auto dependencyProducer = _testModel.addStage({InputInfo::fromPrevStage(0).output(1)}, {OutputInfo::fromNetwork(1)});
auto model = _testModel.getBaseModel();
ASSERT_NO_THROW(model->addStageDependency(dependentStage, dependencyProducer->output(0)));
const auto edge = dependencyProducer->output(0)->dependentStagesEdges().front();
ASSERT_ANY_THROW(model->replaceStageDependency(edge, dependencyProducer->output(0)));
}
TEST_F(StageDependencyEdgeProcessingTests, ReplaceStageDependencyReplacesConnection) {
//
// -> [Data] -> (Stage) -> [Output]
//
// [Input] -> (Stage) -> [Data] -> (Stage) -> [Output]
// |
// -> [Data] ------------> (Stage) -> [Output]
//
const DataDesc desc{1};
_testModel.createInputs({desc});
_testModel.createOutputs({desc, desc, desc});
_testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::intermediate(desc),
OutputInfo::intermediate(desc),
OutputInfo::intermediate(desc)});
auto dependentStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(0)}, {OutputInfo::fromNetwork(0)});
auto initialDependencyProducer = _testModel.addStage({InputInfo::fromPrevStage(0).output(1)}, {OutputInfo::fromNetwork(1)});
auto resultDependencyProducer = _testModel.addStage({InputInfo::fromPrevStage(0).output(2)}, {OutputInfo::fromNetwork(2)});
auto model = _testModel.getBaseModel();
ASSERT_NO_THROW(model->addStageDependency(dependentStage, initialDependencyProducer->output(0)));
ASSERT_TRUE(checkExecutionOrder(model, {initialDependencyProducer->id(), dependentStage->id()}));
ASSERT_TRUE(checkExecutionOrder(model, {dependentStage->id(), resultDependencyProducer->id()}));
const auto edge = initialDependencyProducer->output(0)->dependentStagesEdges().front();
ASSERT_NO_THROW(model->replaceStageDependency(edge, resultDependencyProducer->output(0)));
ASSERT_EQ(initialDependencyProducer->output(0)->dependentStagesEdges().size(), 0);
ASSERT_EQ(edge->dependency(), resultDependencyProducer->output(0));
ASSERT_TRUE(checkExecutionOrder(model, {resultDependencyProducer->id(), dependentStage->id()}));
}
TEST_F(StageDependencyEdgeProcessingTests, ReplaceDependentStageAssertsOnStageInput) {
//
// -----------> [Data] -> (Stage) -> [Output]
// [Input] -> (Stage) |
// -> [Data] -> (Stage) -> [Output]
//
@ -291,25 +34,21 @@ TEST_F(StageDependencyEdgeProcessingTests, ReplaceDependentStageAssertsOnStageIn
_testModel.createInputs({desc});
_testModel.createOutputs({desc, desc});
auto dependencyProducer = _testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::intermediate(desc),
_testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::intermediate(desc),
OutputInfo::intermediate(desc)});
auto initialDependentStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(0)}, {OutputInfo::fromNetwork(0)});
auto resultDependentStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(1)}, {OutputInfo::fromNetwork(1)});
auto childStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(0)}, {OutputInfo::fromNetwork(0)});
auto parentStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(1)}, {OutputInfo::fromNetwork(1)});
auto model = _testModel.getBaseModel();
ASSERT_NO_THROW(model->addStageDependency(initialDependentStage, dependencyProducer->output(1)));
const auto edge = dependencyProducer->output(1)->dependentStagesEdges().front();
ASSERT_ANY_THROW(model->replaceDependentStage(edge, resultDependentStage));
ASSERT_NO_THROW(model->addStageDependency(parentStage, childStage));
}
TEST_F(StageDependencyEdgeProcessingTests, ReplaceDependentStageAssertsIfDependencyExists) {
TEST_F(StageDependencyEdgeProcessingTests, AddStageDependencyAssertsIfDependencyExists) {
//
// -> [Data] -> (Stage) -> [Output]
// [Input] -> (Stage) |
// -> [Data] ------------> (Stage) -> [Output]
// [Input] -> (Stage) |
// -> [Data] -> (Stage) -> [Output]
//
const DataDesc desc{1};
@ -319,25 +58,103 @@ TEST_F(StageDependencyEdgeProcessingTests, ReplaceDependentStageAssertsIfDepende
_testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::intermediate(desc),
OutputInfo::intermediate(desc)});
auto dependentStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(0)}, {OutputInfo::fromNetwork(0)});
auto dependencyProducer = _testModel.addStage({InputInfo::fromPrevStage(0).output(1)}, {OutputInfo::fromNetwork(1)});
auto childStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(0)}, {OutputInfo::fromNetwork(0)});
auto parentStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(1)}, {OutputInfo::fromNetwork(1)});
auto model = _testModel.getBaseModel();
ASSERT_NO_THROW(model->addStageDependency(dependentStage, dependencyProducer->output(0)));
const auto edge = dependencyProducer->output(0)->dependentStagesEdges().front();
ASSERT_ANY_THROW(model->replaceDependentStage(edge, dependentStage));
ASSERT_NO_THROW(model->addStageDependency(parentStage, childStage));
ASSERT_ANY_THROW(model->addStageDependency(parentStage, childStage));
}
TEST_F(StageDependencyEdgeProcessingTests, ReplaceDependentStageReplacesConnection) {
TEST_F(StageDependencyEdgeProcessingTests, NetWithTwoStagesHasCorrectExecOrder) {
//
// -> [Data] -> (Stage) -> [Data] -> (Stage) -> [Output]
// [Input] -> (Stage) |
// -> [Data] -> (Stage) -> [Output]
//
const DataDesc desc{1};
_testModel.createInputs({desc});
_testModel.createOutputs({desc, desc});
_testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::intermediate(desc),
OutputInfo::intermediate(desc)});
auto childStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(0)}, {OutputInfo::fromNetwork(0)});
auto parentStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(1)}, {OutputInfo::intermediate(desc)});
_testModel.addStage({InputInfo::fromPrevStage(2)}, {OutputInfo::fromNetwork(1)});
auto model = _testModel.getBaseModel();
ASSERT_TRUE(checkExecutionOrder(model, {childStage->id(), parentStage->id()}));
ASSERT_NO_THROW(model->addStageDependency(parentStage, childStage));
ASSERT_TRUE(checkExecutionOrder(model, {parentStage->id(), childStage->id()}));
}
TEST_F(StageDependencyEdgeProcessingTests, NetWithThreeStagesHasCorrectExecOrder) {
//
// -> [Data] -> (Stage) -> [Data] -> (Stage) -> [Data] -> (Stage) -> [Output]
// [Input] -> (Stage) |
// -> [Data] ----------------------> (Stage) -> [Output]
//
const DataDesc desc{1};
_testModel.createInputs({desc});
_testModel.createOutputs({desc, desc});
_testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::intermediate(desc),
OutputInfo::intermediate(desc)});
auto childStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(0)}, {OutputInfo::fromNetwork(0)});
_testModel.addStage({InputInfo::fromPrevStage(0).output(1)}, {OutputInfo::intermediate(desc)});
auto parentStage = _testModel.addStage({InputInfo::fromPrevStage(2)}, {OutputInfo::intermediate(desc)});
_testModel.addStage({InputInfo::fromPrevStage(3)}, {OutputInfo::fromNetwork(1)});
auto model = _testModel.getBaseModel();
ASSERT_TRUE(checkExecutionOrder(model, {childStage->id(), parentStage->id()}));
ASSERT_NO_THROW(model->addStageDependency(parentStage, childStage));
ASSERT_TRUE(checkExecutionOrder(model, {parentStage->id(), childStage->id()}));
}
TEST_F(StageDependencyEdgeProcessingTests, ReplaceStageDependencyParentAssertsIfDependencyExists) {
//
// -> [Data] -> (Stage) -> [Output]
// [Input] -> (Stage) |
// -> [Data] -> (Stage) -> [Output]
//
const DataDesc desc{1};
_testModel.createInputs({desc});
_testModel.createOutputs({desc, desc});
_testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::intermediate(desc),
OutputInfo::intermediate(desc)});
auto childStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(0)}, {OutputInfo::fromNetwork(0)});
auto parentStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(1)}, {OutputInfo::fromNetwork(1)});
auto model = _testModel.getBaseModel();
ASSERT_NO_THROW(model->addStageDependency(parentStage, childStage));
const auto edge = parentStage->childDependencyEdges().front();
ASSERT_ANY_THROW(model->replaceStageDependencyParent(edge, parentStage));
}
TEST_F(StageDependencyEdgeProcessingTests, ReplaceStageDependencyParentReplacesConnection) {
//
// -> [Data] -> (Stage) -> [Output]
//
// [Input] -> (Stage) -> [Data] -> (Stage) -> [Output]
// |
// -> [Data] ------------> (Stage) -> [Output]
// |
// -> [Data] -> (Stage) -> [Output]
//
const DataDesc desc{1};
@ -348,31 +165,32 @@ TEST_F(StageDependencyEdgeProcessingTests, ReplaceDependentStageReplacesConnecti
_testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::intermediate(desc),
OutputInfo::intermediate(desc),
OutputInfo::intermediate(desc)});
auto initialDependentStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(0)}, {OutputInfo::fromNetwork(0)});
auto resultDependentStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(1)}, {OutputInfo::fromNetwork(1)});
auto dependencyProducer = _testModel.addStage({InputInfo::fromPrevStage(0).output(2)}, {OutputInfo::fromNetwork(2)});
auto childStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(0)}, {OutputInfo::fromNetwork(0)});
auto initialParentStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(1)}, {OutputInfo::fromNetwork(1)});
auto resultParentStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(2)}, {OutputInfo::fromNetwork(2)});
auto model = _testModel.getBaseModel();
ASSERT_NO_THROW(model->addStageDependency(initialDependentStage, dependencyProducer->output(0)));
ASSERT_NO_THROW(model->addStageDependency(initialParentStage, childStage));
ASSERT_TRUE(checkExecutionOrder(model, {dependencyProducer->id(), initialDependentStage->id()}));
ASSERT_TRUE(checkExecutionOrder(model, {resultDependentStage->id(), dependencyProducer->id()}));
ASSERT_TRUE(checkExecutionOrder(model, {initialParentStage->id(), childStage->id()}));
ASSERT_TRUE(checkExecutionOrder(model, {childStage->id(), resultParentStage->id()}));
const auto edge = dependencyProducer->output(0)->dependentStagesEdges().front();
const auto edge = initialParentStage->childDependencyEdges().front();
ASSERT_NO_THROW(model->replaceDependentStage(edge, resultDependentStage));
ASSERT_NO_THROW(model->replaceStageDependencyParent(edge, resultParentStage));
ASSERT_EQ(edge->dependentStage(), resultDependentStage);
ASSERT_EQ(initialParentStage->childDependencyEdges().size(), 0);
ASSERT_EQ(edge->parent(), resultParentStage);
ASSERT_TRUE(checkExecutionOrder(model, {dependencyProducer->id(), resultDependentStage->id()}));
ASSERT_TRUE(checkExecutionOrder(model, {resultParentStage->id(), childStage->id()}));
}
TEST_F(StageDependencyEdgeProcessingTests, RemoveStageDependencyUpdatesNextPrevStages) {
TEST_F(StageDependencyEdgeProcessingTests, ReplaceStageDependencyChildAssertsIfDependencyExists) {
//
// -> [Data] -> (Stage) -> [Output]
// [Input] -> (Stage) |
// -> [Data] ------------> (Stage) -> [Output]
// [Input] -> (Stage) |
// -> [Data] -> (Stage) -> [Output]
//
const DataDesc desc{1};
@ -382,24 +200,87 @@ TEST_F(StageDependencyEdgeProcessingTests, RemoveStageDependencyUpdatesNextPrevS
_testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::intermediate(desc),
OutputInfo::intermediate(desc)});
auto dependentStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(0)}, {OutputInfo::fromNetwork(0)});
auto dependencyProducer = _testModel.addStage({InputInfo::fromPrevStage(0).output(1)}, {OutputInfo::fromNetwork(1)});
auto childStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(0)}, {OutputInfo::fromNetwork(0)});
auto parentStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(1)}, {OutputInfo::fromNetwork(1)});
auto model = _testModel.getBaseModel();
ASSERT_NO_THROW(model->addStageDependency(dependentStage, dependencyProducer->output(0)));
ASSERT_NO_THROW(model->addStageDependency(parentStage, childStage));
const auto edge = dependencyProducer->output(0)->dependentStagesEdges().front();
const auto edge = parentStage->childDependencyEdges().front();
ASSERT_ANY_THROW(model->replaceStageDependencyChild(edge, childStage));
}
TEST_F(StageDependencyEdgeProcessingTests, ReplaceStageDependencyChildReplacesConnection) {
//
// -> [Data] -> (Stage) -> [Output]
//
// [Input] -> (Stage) -> [Data] -> (Stage) -> [Output]
// |
// -> [Data] -> (Stage) -> [Output]
//
const DataDesc desc{1};
_testModel.createInputs({desc});
_testModel.createOutputs({desc, desc, desc});
_testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::intermediate(desc),
OutputInfo::intermediate(desc),
OutputInfo::intermediate(desc)});
auto initialChildStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(0)}, {OutputInfo::fromNetwork(0)});
auto resultChildStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(1)}, {OutputInfo::fromNetwork(1)});
auto parentStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(2)}, {OutputInfo::fromNetwork(2)});
auto model = _testModel.getBaseModel();
ASSERT_NO_THROW(model->addStageDependency(parentStage, initialChildStage));
ASSERT_TRUE(checkExecutionOrder(model, {parentStage->id(), initialChildStage->id()}));
ASSERT_TRUE(checkExecutionOrder(model, {resultChildStage->id(), parentStage->id()}));
const auto edge = parentStage->childDependencyEdges().front();
ASSERT_NO_THROW(model->replaceStageDependencyChild(edge, resultChildStage));
ASSERT_EQ(edge->child(), resultChildStage);
ASSERT_TRUE(checkExecutionOrder(model, {parentStage->id(), resultChildStage->id()}));
}
TEST_F(StageDependencyEdgeProcessingTests, RemoveStageDependencyUpdatesNextPrevStages) {
//
// -> [Data] -> (Stage) -> [Output]
// [Input] -> (Stage) |
// -> [Data] -> (Stage) -> [Output]
//
const DataDesc desc{1};
_testModel.createInputs({desc});
_testModel.createOutputs({desc, desc});
_testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::intermediate(desc),
OutputInfo::intermediate(desc)});
auto childStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(0)}, {OutputInfo::fromNetwork(0)});
auto parentStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(1)}, {OutputInfo::fromNetwork(1)});
auto model = _testModel.getBaseModel();
ASSERT_NO_THROW(model->addStageDependency(parentStage, childStage));
const auto edge = parentStage->childDependencyEdges().front();
ASSERT_NO_THROW(model->removeStageDependency(edge));
const auto prevStages = dependentStage->prevStages();
const auto nextStages = dependencyProducer->prevStages();
const auto prevStages = childStage->prevStages();
const auto nextStages = parentStage->prevStages();
auto it = std::find(prevStages.begin(), prevStages.end(), dependencyProducer);
auto it = std::find(prevStages.begin(), prevStages.end(), parentStage);
ASSERT_EQ(it, prevStages.end());
it = std::find(nextStages.begin(), nextStages.end(), dependentStage);
it = std::find(nextStages.begin(), nextStages.end(), childStage);
ASSERT_EQ(it, nextStages.end());
}
@ -417,22 +298,22 @@ TEST_F(StageDependencyEdgeProcessingTests, RemoveStageDependencyViaDataToShapeEd
_testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::intermediate(desc),
OutputInfo::intermediate(desc)});
auto dependentStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(0)}, {OutputInfo::fromNetwork(0)});
auto dependencyProducer = _testModel.addStage({InputInfo::fromPrevStage(0).output(1)}, {OutputInfo::fromNetwork(1)});
auto childStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(0)}, {OutputInfo::fromNetwork(0)});
auto parentStage = _testModel.addStage({InputInfo::fromPrevStage(0).output(1)}, {OutputInfo::fromNetwork(1)});
auto model = _testModel.getBaseModel();
ASSERT_NO_THROW(model->addStageDependency(dependentStage, dependencyProducer->output(0)));
ASSERT_NO_THROW(model->addStageDependency(parentStage, childStage));
ASSERT_NO_THROW(model->removeStageDependency(dependentStage, dependencyProducer->output(0)));
ASSERT_NO_THROW(model->removeStageDependency(parentStage, childStage));
const auto prevStages = dependentStage->prevStages();
const auto nextStages = dependencyProducer->prevStages();
const auto prevStages = childStage->prevStages();
const auto nextStages = parentStage->prevStages();
auto it = std::find(prevStages.begin(), prevStages.end(), dependencyProducer);
auto it = std::find(prevStages.begin(), prevStages.end(), parentStage);
ASSERT_EQ(it, prevStages.end());
it = std::find(nextStages.begin(), nextStages.end(), dependentStage);
it = std::find(nextStages.begin(), nextStages.end(), childStage);
ASSERT_EQ(it, nextStages.end());
}

View File

@ -89,16 +89,16 @@ protected:
ASSERT_EQ(edge->parent(), shape);
}
void checkStageDependency(const Data& shape, const Stage& stage) {
ASSERT_FALSE(shape->dependentStagesEdges().empty());
const auto& dependentStagesEdges = shape->dependentStagesEdges();
void checkStageDependency(const Stage& parent, const Stage& child) {
ASSERT_FALSE(parent->childDependencyEdges().empty());
const auto& childDependencyEdges = parent->childDependencyEdges();
auto it = std::find_if(dependentStagesEdges.begin(), dependentStagesEdges.end(),
[&stage](const StageDependency& edge) {
return edge->dependentStage() == stage;
auto it = std::find_if(childDependencyEdges.begin(), childDependencyEdges.end(),
[&child](const StageDependency& edge) {
return edge->child() == child;
});
ASSERT_NE(it, dependentStagesEdges.end());
ASSERT_NE(it, childDependencyEdges.end());
}
void checkNoDataToShapeDependency(const Data& shape, const Data& data) {
@ -114,15 +114,15 @@ protected:
ASSERT_EQ(it, childDataToShapeEdges.end());
}
void checkNoStageDependency(const Data& shape, const Stage& stage) {
const auto& dependentStagesEdges = shape->dependentStagesEdges();
void checkNoStageDependency(const Stage& parent, const Stage& child) {
const auto& childDependencyEdges = parent->childDependencyEdges();
auto it = std::find_if(dependentStagesEdges.begin(), dependentStagesEdges.end(),
[&stage](const StageDependency& edge) {
return edge->dependentStage() == stage;
auto it = std::find_if(childDependencyEdges.begin(), childDependencyEdges.end(),
[&child](const StageDependency& edge) {
return edge->child() == child;
});
ASSERT_EQ(it, shape->dependentStagesEdges().end());
ASSERT_EQ(it, parent->childDependencyEdges().end());
}
void checkGathers(int gathersCount) {
@ -145,8 +145,8 @@ protected:
dependentStage = dataConsumingShape->producer();
}
checkStageDependency(convertedShape, dependentStage);
checkNoStageDependency(shape, dependentStage);
checkStageDependency(convertedShape->producer(), dependentStage);
checkNoStageDependency(shape->producer(), dependentStage);
}
}

View File

@ -0,0 +1,141 @@
// Copyright (C) 2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "graph_transformer_tests.hpp"
namespace vpu {
namespace ie = InferenceEngine;
class InjectStageTests : public GraphTransformerTest {
protected:
void SetUp() override {
ASSERT_NO_FATAL_FAILURE(GraphTransformerTest::SetUp());
ASSERT_NO_FATAL_FAILURE(InitCompileEnv());
_testModel = CreateTestModel();
}
protected:
TestModel _testModel;
};
TEST_F(InjectStageTests, InjectionRedirectsChildStageDependency) {
//
// -> (Stage) -> [Output]
// [Input] -> (Stage) -> [Output]
// -> (Stage) -> [Output]
//
const DataDesc desc{1};
_testModel.createInputs({desc});
_testModel.createOutputs({desc, desc, desc});
const auto hwStage = _testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::fromNetwork(0)}, StageType::MyriadXHwOp);
const auto swStage = _testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::fromNetwork(1)}, StageType::Copy);
const auto childStage = _testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::fromNetwork(2)});
auto model = _testModel.getBaseModel();
ASSERT_NO_THROW(model->addStageDependency(swStage, childStage));
ASSERT_TRUE(checkExecutionOrder(model, {swStage->id(), childStage->id()}));
ASSERT_NO_THROW(model->injectStage()
.parentHW(hwStage)
.childSW(swStage)
.done());
ASSERT_TRUE(checkExecutionOrder(model, {hwStage->id(), childStage->id()}));
}
TEST_F(InjectStageTests, InjectionRedirectsParentStageDependency) {
//
// -> (Stage) -> [Output]
// [Input] -> (Stage) -> [Output]
// -> (Stage) -> [Output]
//
const DataDesc desc{1};
_testModel.createInputs({desc});
_testModel.createOutputs({desc, desc, desc});
const auto hwStage = _testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::fromNetwork(0)}, StageType::MyriadXHwOp);
const auto swStage = _testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::fromNetwork(1)}, StageType::Copy);
const auto parentStage = _testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::fromNetwork(2)});
auto model = _testModel.getBaseModel();
ASSERT_NO_THROW(model->addStageDependency(parentStage, swStage));
ASSERT_TRUE(checkExecutionOrder(model, {parentStage->id(), swStage->id()}));
ASSERT_NO_THROW(model->injectStage()
.parentHW(hwStage)
.childSW(swStage)
.done());
ASSERT_TRUE(checkExecutionOrder(model, {parentStage->id(), hwStage->id()}));
}
TEST_F(InjectStageTests, RevertInjectionRedirectsChildStageDependency) {
//
// -> (Stage) -> [Output]
// [Input] -> (Stage) -> [Output]
// -> (Stage) -> [Output]
//
const DataDesc desc{1};
_testModel.createInputs({desc});
_testModel.createOutputs({desc, desc, desc});
const auto hwStage = _testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::fromNetwork(0)}, StageType::MyriadXHwOp);
const auto swStage = _testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::fromNetwork(1)}, StageType::Copy);
const auto parentStage = _testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::fromNetwork(2)});
auto model = _testModel.getBaseModel();
ASSERT_NO_THROW(model->addStageDependency(parentStage, swStage));
ASSERT_TRUE(checkExecutionOrder(model, {parentStage->id(), swStage->id()}));
Injection edge;
ASSERT_NO_THROW(edge = model->injectStage()
.parentHW(hwStage)
.childSW(swStage)
.done());
ASSERT_NO_THROW(model->revertInjection(edge));
ASSERT_TRUE(checkExecutionOrder(model, {parentStage->id(), swStage->id()}));
}
TEST_F(InjectStageTests, RevertInjectionRedirectsParentStageDependency) {
//
// -> (Stage) -> [Output]
// [Input] -> (Stage) -> [Output]
// -> (Stage) -> [Output]
//
const DataDesc desc{1};
_testModel.createInputs({desc});
_testModel.createOutputs({desc, desc, desc});
const auto hwStage = _testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::fromNetwork(0)}, StageType::MyriadXHwOp);
const auto swStage = _testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::fromNetwork(1)}, StageType::Copy);
const auto parentStage = _testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::fromNetwork(2)});
auto model = _testModel.getBaseModel();
ASSERT_NO_THROW(model->addStageDependency(parentStage, swStage));
ASSERT_TRUE(checkExecutionOrder(model, {parentStage->id(), swStage->id()}));
Injection edge;
ASSERT_NO_THROW(edge = model->injectStage()
.parentHW(hwStage)
.childSW(swStage)
.done());
ASSERT_NO_THROW(model->revertInjection(edge));
ASSERT_TRUE(checkExecutionOrder(model, {parentStage->id(), swStage->id()}));
}
} // namespace vpu