[VPU][GT] Refine edges methods (#550)
* [VPU][GT] Extract order manipulation into separate methods * [VPU][GT] Rename data -> dependency * [VPU][GT] Extend unit tests * [VPU][GT] Introduce replacement and removal methods for StageDependency * [VPU][GT] Update DataToShape connection methods
This commit is contained in:
parent
5c2eb05990
commit
d337b4ed97
@ -45,7 +45,7 @@ private:
|
||||
class StageDependencyEdge final :
|
||||
public EnableHandle,
|
||||
public EnableCustomAttributes {
|
||||
VPU_MODEL_ATTRIBUTE(Data, data, nullptr)
|
||||
VPU_MODEL_ATTRIBUTE(Data, dependency, nullptr)
|
||||
VPU_MODEL_ATTRIBUTE(Stage, dependentStage, nullptr)
|
||||
|
||||
private:
|
||||
|
@ -157,6 +157,16 @@ public:
|
||||
const StageOutput& edge,
|
||||
const Data& newOutput);
|
||||
|
||||
void replaceStageDependency(
|
||||
const StageDependency& edge,
|
||||
const Data& newDependency);
|
||||
|
||||
void replaceDependentStage(
|
||||
const StageDependency& edge,
|
||||
const Stage& newDependentStage);
|
||||
|
||||
void removeStageDependency(const StageDependency& edge);
|
||||
|
||||
//
|
||||
// Stage <-> Stage edges
|
||||
//
|
||||
@ -288,6 +298,10 @@ public:
|
||||
|
||||
void reorderStages(const StageComparator& comparator = {});
|
||||
|
||||
void setStagesOrder(const Stage& parent, const Stage& child);
|
||||
|
||||
void removeStagesOrder(const Stage& parent, const Stage& child);
|
||||
|
||||
//
|
||||
// Nodes accessors
|
||||
//
|
||||
|
@ -316,8 +316,7 @@ StageInput ModelObj::addStageInput(
|
||||
if (data->_producerEdge != nullptr) {
|
||||
IE_ASSERT(stage->_parentStageEdge == nullptr);
|
||||
IE_ASSERT(data->_producerEdge->_producer->_parentStageEdge == nullptr);
|
||||
++data->_producerEdge->_producer->_nextStages[stage];
|
||||
++stage->_prevStages[data->_producerEdge->_producer];
|
||||
setStagesOrder(data->producerEdge()->producer(), stage);
|
||||
}
|
||||
|
||||
if (stage->_prevStages.empty()) {
|
||||
@ -381,8 +380,7 @@ StageOutput ModelObj::addStageOutput(
|
||||
for (const auto& consumerEdge : data->_consumerEdges) {
|
||||
IE_ASSERT(stage->_parentStageEdge == nullptr);
|
||||
IE_ASSERT(consumerEdge->_consumer->_parentStageEdge == nullptr);
|
||||
++consumerEdge->_consumer->_prevStages[stage];
|
||||
++stage->_nextStages[consumerEdge->_consumer];
|
||||
setStagesOrder(stage, consumerEdge->consumer());
|
||||
|
||||
_initialStages.erase(consumerEdge->_consumer);
|
||||
}
|
||||
@ -391,22 +389,33 @@ StageOutput ModelObj::addStageOutput(
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
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->_data = data;
|
||||
edge->_dependency = data;
|
||||
edge->_dependentStage = stage;
|
||||
|
||||
data->_dependentStagesEdges.push_back(edge);
|
||||
|
||||
VPU_THROW_UNLESS(data->_producerEdge != 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());
|
||||
|
||||
++data->_producerEdge->_producer->_nextStages[stage];
|
||||
++stage->_prevStages[data->_producerEdge->_producer];
|
||||
setStagesOrder(data->producerEdge()->producer(), stage);
|
||||
|
||||
return edge;
|
||||
}
|
||||
@ -501,19 +510,7 @@ void ModelObj::replaceStageInput(
|
||||
//
|
||||
|
||||
if (edge->_input->_producerEdge != nullptr) {
|
||||
auto it1 = edge->_input->_producerEdge->_producer->_nextStages.find(edge->_consumer);
|
||||
IE_ASSERT(it1 != edge->_input->_producerEdge->_producer->_nextStages.end());
|
||||
--it1->second;
|
||||
if (it1->second <= 0) {
|
||||
edge->_input->_producerEdge->_producer->_nextStages.erase(it1);
|
||||
}
|
||||
|
||||
auto it2 = edge->_consumer->_prevStages.find(edge->_input->_producerEdge->_producer);
|
||||
IE_ASSERT(it2 != edge->_consumer->_prevStages.end());
|
||||
--it2->second;
|
||||
if (it2->second <= 0) {
|
||||
edge->_consumer->_prevStages.erase(it2);
|
||||
}
|
||||
removeStagesOrder(edge->input()->producer(), edge->consumer());
|
||||
}
|
||||
|
||||
//
|
||||
@ -530,8 +527,7 @@ void ModelObj::replaceStageInput(
|
||||
if (newInput->_producerEdge != nullptr) {
|
||||
IE_ASSERT(edge->_consumer->_parentStageEdge == nullptr);
|
||||
IE_ASSERT(newInput->_producerEdge->_producer->_parentStageEdge == nullptr);
|
||||
++newInput->_producerEdge->_producer->_nextStages[edge->_consumer];
|
||||
++edge->_consumer->_prevStages[newInput->_producerEdge->_producer];
|
||||
setStagesOrder(newInput->producerEdge()->producer(), edge->consumer());
|
||||
|
||||
_initialStages.erase(edge->_consumer);
|
||||
}
|
||||
@ -608,19 +604,7 @@ void ModelObj::replaceStageOutput(
|
||||
//
|
||||
|
||||
for (const auto& consumerEdge : edge->_output->_consumerEdges) {
|
||||
auto it1 = consumerEdge->_consumer->_prevStages.find(edge->_producer);
|
||||
IE_ASSERT(it1 != consumerEdge->_consumer->_prevStages.end());
|
||||
--it1->second;
|
||||
if (it1->second <= 0) {
|
||||
consumerEdge->_consumer->_prevStages.erase(it1);
|
||||
}
|
||||
|
||||
auto it2 = edge->_producer->_nextStages.find(consumerEdge->_consumer);
|
||||
IE_ASSERT(it2 != edge->_producer->_nextStages.end());
|
||||
--it2->second;
|
||||
if (it2->second <= 0) {
|
||||
edge->_producer->_nextStages.erase(it2);
|
||||
}
|
||||
removeStagesOrder(edge->producer(), consumerEdge->consumer());
|
||||
|
||||
if (consumerEdge->_consumer->_prevStages.empty()) {
|
||||
_initialStages.emplace(consumerEdge->_consumer);
|
||||
@ -643,13 +627,109 @@ void ModelObj::replaceStageOutput(
|
||||
for (const auto& consumerEdge : newOutput->_consumerEdges) {
|
||||
IE_ASSERT(edge->_producer->_parentStageEdge == nullptr);
|
||||
IE_ASSERT(consumerEdge->_consumer->_parentStageEdge == nullptr);
|
||||
++consumerEdge->_consumer->_prevStages[edge->_producer];
|
||||
++edge->_producer->_nextStages[consumerEdge->_consumer];
|
||||
setStagesOrder(edge->producer(), consumerEdge->consumer());
|
||||
|
||||
_initialStages.erase(consumerEdge->_consumer);
|
||||
}
|
||||
}
|
||||
|
||||
void ModelObj::replaceStageDependency(
|
||||
const StageDependency& edge,
|
||||
const Data& newDependency) {
|
||||
const auto previousDependency = edge->dependency();
|
||||
const auto dependentStage = edge->dependentStage();
|
||||
|
||||
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& 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);
|
||||
|
||||
removeStagesOrder(previousDependency->producer(), dependentStage);
|
||||
|
||||
edge->_dependency = newDependency;
|
||||
newDependency->_dependentStagesEdges.push_back(edge);
|
||||
|
||||
setStagesOrder(newDependency->producerEdge()->producer(), dependentStage);
|
||||
}
|
||||
|
||||
void ModelObj::replaceDependentStage(
|
||||
const StageDependency& edge,
|
||||
const Stage& newDependentStage) {
|
||||
const auto dependency = edge->dependency();
|
||||
const auto previousDependentStage = edge->dependentStage();
|
||||
|
||||
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& 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);
|
||||
|
||||
edge->_dependentStage = newDependentStage;
|
||||
|
||||
setStagesOrder(dependency->producer(), newDependentStage);
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
_resetStageOrder = true;
|
||||
|
||||
dependency->_dependentStagesEdges.erase(edge);
|
||||
|
||||
removeStagesOrder(dependency->producer(), dependentStage);
|
||||
|
||||
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());
|
||||
|
||||
_stageDependencyEdgePtrList.erase(edge->_ptrPosInModel);
|
||||
}
|
||||
|
||||
ModelObj::InjectStageHelper::~InjectStageHelper() {
|
||||
//
|
||||
// Check that `done` was called.
|
||||
@ -1511,6 +1591,39 @@ DataToDataAllocation ModelObj::connectDataWithDataImpl(
|
||||
return edge;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool isStageDependencyNeeded(
|
||||
const Stage& dependentStage,
|
||||
const Data& dependency) {
|
||||
const auto& dependencyProducer = dependency->producer();
|
||||
|
||||
if (dependencyProducer == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dependentStage == dependencyProducer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check one level above, it covers current cases while checking all the levels might be computationally expensive
|
||||
for (const auto& prevStage : dependencyProducer->prevStages()) {
|
||||
if (prevStage == dependentStage) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& prevStage : dependentStage->prevStages()) {
|
||||
if (prevStage == dependencyProducer) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
DataToShapeAllocation ModelObj::connectDataWithShape(
|
||||
const Data& parent,
|
||||
const Data& child) {
|
||||
@ -1528,16 +1641,11 @@ DataToShapeAllocation ModelObj::connectDataWithShape(
|
||||
parent->_childDataToShapeEdges.push_back(edge);
|
||||
child->_parentDataToShapeEdge = edge;
|
||||
|
||||
const auto& parentStage = parent->producer();
|
||||
const auto& childStage = child->producer();
|
||||
const auto& childProducer = child->producer();
|
||||
|
||||
const auto& areStagesDifferent = [](const Stage& lhs, const Stage& rhs) {
|
||||
return lhs && rhs && lhs != rhs;
|
||||
};
|
||||
|
||||
if (areStagesDifferent(parentStage, childStage)) {
|
||||
if (childProducer && isStageDependencyNeeded(childProducer, parent)) {
|
||||
// Shape and data are produced from different stages, make sure that shape is calculated before data
|
||||
addStageDependency(childStage, parent);
|
||||
addStageDependency(childProducer, parent);
|
||||
}
|
||||
|
||||
return edge;
|
||||
@ -1546,18 +1654,41 @@ DataToShapeAllocation ModelObj::connectDataWithShape(
|
||||
void ModelObj::replaceDataToShapeParent(
|
||||
const DataToShapeAllocation& edge,
|
||||
const Data& newParent) {
|
||||
auto oldParent = edge->parent();
|
||||
auto child = edge->child();
|
||||
const auto oldParent = edge->parent();
|
||||
const auto child = edge->child();
|
||||
|
||||
oldParent->_childDataToShapeEdges.erase(edge);
|
||||
edge->_parent = newParent;
|
||||
newParent->_childDataToShapeEdges.push_back(edge);
|
||||
|
||||
const auto& childProducer = child->producer();
|
||||
|
||||
if (childProducer != nullptr) {
|
||||
const auto& dependentStagesEdges = oldParent->dependentStagesEdges();
|
||||
|
||||
const auto it = std::find_if(dependentStagesEdges.begin(), dependentStagesEdges.end(), [&childProducer](const StageDependency& edge) {
|
||||
return edge->dependentStage() == childProducer;
|
||||
});
|
||||
|
||||
if (it != dependentStagesEdges.end()) {
|
||||
const auto edge = *it;
|
||||
removeStageDependency(edge);
|
||||
}
|
||||
|
||||
if (isStageDependencyNeeded(childProducer, newParent)) {
|
||||
// Shape and data are produced from different stages, make sure that shape is calculated before data
|
||||
addStageDependency(childProducer, newParent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ModelObj::replaceDataToShapeChild(
|
||||
const DataToShapeAllocation& edge,
|
||||
const Data& newChild) {
|
||||
edge->_child->_parentDataToShapeEdge = nullptr;
|
||||
const auto parent = edge->parent();
|
||||
const auto oldChild = edge->child();
|
||||
|
||||
oldChild->_parentDataToShapeEdge = nullptr;
|
||||
edge->_child = newChild;
|
||||
|
||||
VPU_THROW_UNLESS(newChild->_parentDataToShapeEdge == nullptr,
|
||||
@ -1565,6 +1696,28 @@ void ModelObj::replaceDataToShapeChild(
|
||||
newChild->name(), newChild->usage(), newChild->_parentDataToShapeEdge->parent()->name(), newChild->_parentDataToShapeEdge->parent()->usage());
|
||||
|
||||
newChild->_parentDataToShapeEdge = edge;
|
||||
|
||||
const auto& oldChildProducer = oldChild->producer();
|
||||
|
||||
if (oldChildProducer != nullptr) {
|
||||
const auto &dependentStagesEdges = parent->dependentStagesEdges();
|
||||
|
||||
const auto it = std::find_if(dependentStagesEdges.begin(), dependentStagesEdges.end(), [&oldChildProducer](const StageDependency &edge) {
|
||||
return edge->dependentStage() == oldChildProducer;
|
||||
});
|
||||
|
||||
if (it != dependentStagesEdges.end()) {
|
||||
const auto edge = *it;
|
||||
removeStageDependency(edge);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void ModelObj::replaceDataToDataParent(
|
||||
@ -1638,8 +1791,26 @@ void ModelObj::disconnectDatas(const DataToShapeAllocation& edge) {
|
||||
child->_parentDataToShapeEdge = nullptr;
|
||||
parent->_childDataToShapeEdges.erase(edge);
|
||||
|
||||
IE_ASSERT(edge->_ptrPosInModel != _shapeEdgePtrList.end());
|
||||
VPU_THROW_UNLESS(edge->_ptrPosInModel != _shapeEdgePtrList.end(),
|
||||
"disconnect Datas (parent {} with usage {} and child {} with usage {}) with DataToShape connection failed: "
|
||||
"no such edge in Model's DataToShapeEdges list", parent->name(), parent->usage(), child->name(), child->usage());
|
||||
|
||||
_shapeEdgePtrList.erase(edge->_ptrPosInModel);
|
||||
|
||||
const auto& childProducer = child->producer();
|
||||
|
||||
if (childProducer != nullptr) {
|
||||
const auto &dependentStagesEdges = parent->dependentStagesEdges();
|
||||
|
||||
const auto it = std::find_if(dependentStagesEdges.begin(), dependentStagesEdges.end(), [&childProducer](const StageDependency &edge) {
|
||||
return edge->dependentStage() == childProducer;
|
||||
});
|
||||
|
||||
if (it != dependentStagesEdges.end()) {
|
||||
const auto edge = *it;
|
||||
removeStageDependency(edge);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ModelObj::disconnectStage(const Stage& stage) {
|
||||
@ -1824,6 +1995,31 @@ void ModelObj::reorderStages(
|
||||
_resetStageOrder = true;
|
||||
}
|
||||
|
||||
void ModelObj::setStagesOrder(const Stage& parent, const Stage& child) {
|
||||
++parent->_nextStages[child];
|
||||
++child->_prevStages[parent];
|
||||
}
|
||||
|
||||
void ModelObj::removeStagesOrder(const Stage& parent, const Stage& child) {
|
||||
auto parentNextStage = parent->_nextStages.find(child);
|
||||
VPU_THROW_UNLESS(parentNextStage != parent->_nextStages.end(),
|
||||
"removeStagesOrder failed: parent {} with type {} doesn't have {} with type {} as its next stage",
|
||||
parent->name(), parent->type(), child->name(), child->type());
|
||||
--parentNextStage->second;
|
||||
if (parentNextStage->second <= 0) {
|
||||
parent->_nextStages.erase(parentNextStage);
|
||||
}
|
||||
|
||||
auto childPrevStage = child->_prevStages.find(parent);
|
||||
VPU_THROW_UNLESS(childPrevStage != child->_prevStages.end(),
|
||||
"removeStagesOrder failed: child {} with type {} doesn't have {} with type {} as its previous stage",
|
||||
child->name(), child->type(), parent->name(), parent->type());
|
||||
--childPrevStage->second;
|
||||
if (childPrevStage->second <= 0) {
|
||||
child->_prevStages.erase(childPrevStage);
|
||||
}
|
||||
}
|
||||
|
||||
void ModelObj::runDFS(
|
||||
const Stage& stage,
|
||||
StageMap<bool>& visitedMap) const {
|
||||
|
@ -33,7 +33,6 @@ void FrontEnd::parseDSR(const Model& model, const ie::CNNLayerPtr& layer, const
|
||||
VPU_THROW_UNLESS(shapeProducerEdge != nullptr, "Parsing layer {} of type {} failed: input with index {} (of name {}) must have a producer",
|
||||
layer->name, layer->type, 1, shape->name());
|
||||
|
||||
model->replaceStageOutput(dataProducerEdge, dataOutput);
|
||||
if (auto dataToShapeEdge = data->parentDataToShapeEdge()) {
|
||||
const auto& parent = dataToShapeEdge->parent();
|
||||
VPU_THROW_UNLESS(parent == shape, "Myriad plugin encountered layer of type \"{}\" and name \"{}\" with input #{} (data input with name \"{}\") that "
|
||||
@ -44,6 +43,7 @@ void FrontEnd::parseDSR(const Model& model, const ie::CNNLayerPtr& layer, const
|
||||
layer->type, layer->name, 0, data->name(), 1, shape->name(), layer->type, parent->name(), layer->type, layer->type);
|
||||
model->disconnectDatas(dataToShapeEdge);
|
||||
}
|
||||
model->replaceStageOutput(dataProducerEdge, dataOutput);
|
||||
model->removeUnusedData(data);
|
||||
|
||||
if (dataOutput->usage() == DataUsage::Output) {
|
||||
|
@ -114,15 +114,14 @@ TEST_F(DataToShapeEdgeProcessingTests, DataToShapeEdgeSharesMemory) {
|
||||
|
||||
ASSERT_NO_THROW(_middleEnd->run(model));
|
||||
|
||||
Stage shapeProducer = nullptr;
|
||||
for (const auto& stage : model->getStages()) {
|
||||
// Find shape produced stage
|
||||
if (stage->numOutputs() == 2) {
|
||||
shapeProducer = stage;
|
||||
}
|
||||
}
|
||||
// Find shape producer
|
||||
auto it = std::find_if(model->getStages().begin(), model->getStages().end(), [](const Stage& stage) {
|
||||
return stage->numOutputs() == 2;
|
||||
});
|
||||
|
||||
ASSERT_NE(shapeProducer, nullptr);
|
||||
ASSERT_NE(it, model->getStages().end());
|
||||
|
||||
auto shapeProducer = *it;
|
||||
|
||||
const auto& data = shapeProducer->output(0);
|
||||
const auto& shape = shapeProducer->output(1);
|
||||
@ -147,15 +146,14 @@ TEST_F(DataToShapeEdgeProcessingTests, ShapeProcessingOnceSharesMemory) {
|
||||
|
||||
ASSERT_NO_THROW(_middleEnd->run(model));
|
||||
|
||||
Stage shapeProducer = nullptr;
|
||||
for (const auto& stage : model->getStages()) {
|
||||
// Find shape produced stage
|
||||
if (stage->numOutputs() == 2) {
|
||||
shapeProducer = stage;
|
||||
}
|
||||
}
|
||||
// Find shape producer
|
||||
auto it = std::find_if(model->getStages().begin(), model->getStages().end(), [](const Stage& stage) {
|
||||
return stage->numOutputs() == 2;
|
||||
});
|
||||
|
||||
ASSERT_NE(shapeProducer, nullptr);
|
||||
ASSERT_NE(it, model->getStages().end());
|
||||
|
||||
auto shapeProducer = *it;
|
||||
|
||||
const auto& data = shapeProducer->output(0);
|
||||
const auto& shape = shapeProducer->output(1);
|
||||
@ -183,15 +181,14 @@ TEST_F(DataToShapeEdgeProcessingTests, ShapeProcessingOnceHasCorrectExecutionOrd
|
||||
|
||||
ASSERT_NO_THROW(_middleEnd->run(model));
|
||||
|
||||
Stage shapeProducer = nullptr;
|
||||
for (const auto& stage : model->getStages()) {
|
||||
// Find shape produced stage
|
||||
if (stage->numOutputs() == 2) {
|
||||
shapeProducer = stage;
|
||||
}
|
||||
}
|
||||
// Find shape producer
|
||||
auto it = std::find_if(model->getStages().begin(), model->getStages().end(), [](const Stage& stage) {
|
||||
return stage->numOutputs() == 2;
|
||||
});
|
||||
|
||||
ASSERT_NE(shapeProducer, nullptr);
|
||||
ASSERT_NE(it, model->getStages().end());
|
||||
|
||||
auto shapeProducer = *it;
|
||||
|
||||
const auto dataProcessor = shapeProducer->output(0)->singleConsumer();
|
||||
const auto shapeProcessor = shapeProducer->output(1)->singleConsumer();
|
||||
@ -212,15 +209,14 @@ TEST_F(DataToShapeEdgeProcessingTests, ShapeProcessingTwiceSharesMemory) {
|
||||
|
||||
ASSERT_NO_THROW(_middleEnd->run(model));
|
||||
|
||||
Stage shapeProducer = nullptr;
|
||||
for (const auto& stage : model->getStages()) {
|
||||
// Find shape produced stage
|
||||
if (stage->numOutputs() == 2) {
|
||||
shapeProducer = stage;
|
||||
}
|
||||
}
|
||||
// Find shape producer
|
||||
auto it = std::find_if(model->getStages().begin(), model->getStages().end(), [](const Stage& stage) {
|
||||
return stage->numOutputs() == 2;
|
||||
});
|
||||
|
||||
ASSERT_NE(shapeProducer, nullptr);
|
||||
ASSERT_NE(it, model->getStages().end());
|
||||
|
||||
auto shapeProducer = *it;
|
||||
|
||||
const auto& data = shapeProducer->output(0);
|
||||
const auto& shape = shapeProducer->output(1);
|
||||
@ -257,15 +253,14 @@ TEST_F(DataToShapeEdgeProcessingTests, ShapeProcessingTwiceHasCorrectExecutionOr
|
||||
|
||||
ASSERT_NO_THROW(_middleEnd->run(model));
|
||||
|
||||
Stage shapeProducer = nullptr;
|
||||
for (const auto& stage : model->getStages()) {
|
||||
// Find shape produced stage
|
||||
if (stage->numOutputs() == 2) {
|
||||
shapeProducer = stage;
|
||||
}
|
||||
}
|
||||
// Find shape producer
|
||||
auto it = std::find_if(model->getStages().begin(), model->getStages().end(), [](const Stage& stage) {
|
||||
return stage->numOutputs() == 2;
|
||||
});
|
||||
|
||||
ASSERT_NE(shapeProducer, nullptr);
|
||||
ASSERT_NE(it, model->getStages().end());
|
||||
|
||||
auto shapeProducer = *it;
|
||||
|
||||
const auto dataFirstProcessor = shapeProducer->output(0)->singleConsumer();
|
||||
const auto shapeFirstProcessor = shapeProducer->output(1)->singleConsumer();
|
||||
@ -278,4 +273,123 @@ TEST_F(DataToShapeEdgeProcessingTests, ShapeProcessingTwiceHasCorrectExecutionOr
|
||||
ASSERT_TRUE(checkExecutionOrder(model, {shapeSecondProcessor->id(), dataSecondProcessor->id()}));
|
||||
}
|
||||
|
||||
TEST_F(DataToShapeEdgeProcessingTests, ReplaceDataToShapeParentReplacesConnections) {
|
||||
//
|
||||
// -> [Shape] -> (ShapeProc) -> [Shape]
|
||||
// |
|
||||
// [Input] -> (Stage) -> [Data] -> (DataProc) -> [Data]
|
||||
// |
|
||||
// -> [Shape] -> (ShapeProc) -> [Shape]
|
||||
//
|
||||
|
||||
const auto& desc = DataDesc({1});
|
||||
|
||||
_testModel.createInputs({desc});
|
||||
_testModel.createOutputs({desc, desc, desc});
|
||||
|
||||
const auto dataAndShapeParent = _testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::intermediate(desc),
|
||||
OutputInfo::intermediate(desc),
|
||||
OutputInfo::intermediate(desc)});
|
||||
const auto firstShapeProcessor = _testModel.addStage({InputInfo::fromPrevStage(0).output(0)}, {OutputInfo::fromNetwork(0)});
|
||||
const auto dataProcessor = _testModel.addStage({InputInfo::fromPrevStage(0).output(1)}, {OutputInfo::fromNetwork(1)});
|
||||
const auto secondShapeProcessor = _testModel.addStage({InputInfo::fromPrevStage(0).output(2)}, {OutputInfo::fromNetwork(2)});
|
||||
|
||||
const auto& model = _testModel.getBaseModel();
|
||||
const auto& processedData = dataProcessor->output(0);
|
||||
const auto& initialShape = firstShapeProcessor->output(0);
|
||||
const auto& finalShape = secondShapeProcessor->output(0);
|
||||
ASSERT_NO_THROW(model->connectDataWithShape(initialShape, processedData));
|
||||
|
||||
const auto& dataToShapeEdge = processedData->parentDataToShapeEdge();
|
||||
ASSERT_NE(dataToShapeEdge, nullptr);
|
||||
|
||||
ASSERT_NO_THROW(model->replaceDataToShapeParent(dataToShapeEdge, finalShape));
|
||||
|
||||
ASSERT_TRUE(initialShape->childDataToShapeEdges().empty());
|
||||
ASSERT_EQ(finalShape->childDataToShapeEdges().front(), dataToShapeEdge);
|
||||
ASSERT_EQ(dataToShapeEdge->parent(), finalShape);
|
||||
|
||||
ASSERT_TRUE(initialShape->dependentStagesEdges().empty());
|
||||
ASSERT_FALSE(finalShape->dependentStagesEdges().empty());
|
||||
|
||||
const auto& stageDependencyEdge = finalShape->dependentStagesEdges().front();
|
||||
ASSERT_EQ(stageDependencyEdge->dependentStage(), dataProcessor);
|
||||
ASSERT_EQ(stageDependencyEdge->dependency(), finalShape);
|
||||
}
|
||||
|
||||
TEST_F(DataToShapeEdgeProcessingTests, ReplaceDataToShapeChildReplacesConnections) {
|
||||
//
|
||||
// -> [Data] -> (DataProc) -> [Data]
|
||||
// |
|
||||
// [Input] -> (Stage) -> [Shape] -> (ShapeProc) -> [Shape]
|
||||
// |
|
||||
// -> [Data] -> (DataProc) -> [Data]
|
||||
//
|
||||
|
||||
const auto& desc = DataDesc({1});
|
||||
|
||||
_testModel.createInputs({desc});
|
||||
_testModel.createOutputs({desc, desc, desc});
|
||||
|
||||
const auto dataAndShapeParent = _testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::intermediate(desc),
|
||||
OutputInfo::intermediate(desc),
|
||||
OutputInfo::intermediate(desc)});
|
||||
const auto firstDataProcessor = _testModel.addStage({InputInfo::fromPrevStage(0).output(0)}, {OutputInfo::fromNetwork(0)});
|
||||
const auto shapeProcessor = _testModel.addStage({InputInfo::fromPrevStage(0).output(1)}, {OutputInfo::fromNetwork(1)});
|
||||
const auto secondDataProcessor = _testModel.addStage({InputInfo::fromPrevStage(0).output(2)}, {OutputInfo::fromNetwork(2)});
|
||||
|
||||
const auto& model = _testModel.getBaseModel();
|
||||
const auto& processedShape = shapeProcessor->output(0);
|
||||
const auto& initialData = firstDataProcessor->output(0);
|
||||
const auto& finalData = secondDataProcessor->output(0);
|
||||
ASSERT_NO_THROW(model->connectDataWithShape(processedShape, initialData));
|
||||
|
||||
const auto& dataToShapeEdge = processedShape->childDataToShapeEdges().front();
|
||||
ASSERT_NE(dataToShapeEdge, nullptr);
|
||||
|
||||
ASSERT_NO_THROW(model->replaceDataToShapeChild(dataToShapeEdge, finalData));
|
||||
|
||||
ASSERT_EQ(initialData->parentDataToShapeEdge(), nullptr);
|
||||
ASSERT_EQ(finalData->parentDataToShapeEdge(), dataToShapeEdge);
|
||||
ASSERT_EQ(dataToShapeEdge->child(), finalData);
|
||||
|
||||
ASSERT_FALSE(processedShape->dependentStagesEdges().empty());
|
||||
const auto& stageDependencyEdge = processedShape->dependentStagesEdges().front();
|
||||
|
||||
ASSERT_EQ(stageDependencyEdge->dependentStage(), secondDataProcessor);
|
||||
ASSERT_EQ(stageDependencyEdge->dependency(), processedShape);
|
||||
}
|
||||
|
||||
TEST_F(DataToShapeEdgeProcessingTests, DisconnectDatasRemovesConnections) {
|
||||
//
|
||||
// -> [Shape] -> (ShapeProc) -> [Shape]
|
||||
// [Input] -> (Stage) |
|
||||
// -> [Data] -> (DataProc) -> [Data]
|
||||
//
|
||||
|
||||
const auto& desc = DataDesc({1});
|
||||
|
||||
_testModel.createInputs({desc});
|
||||
_testModel.createOutputs({desc, desc});
|
||||
|
||||
const auto dataAndShapeParent = _testModel.addStage({InputInfo::fromNetwork()}, {OutputInfo::intermediate(desc),
|
||||
OutputInfo::intermediate(desc)});
|
||||
const auto dataProcessor = _testModel.addStage({InputInfo::fromPrevStage(0).output(0)}, {OutputInfo::fromNetwork(0)});
|
||||
const auto shapeProcessor = _testModel.addStage({InputInfo::fromPrevStage(0).output(1)}, {OutputInfo::fromNetwork(1)});
|
||||
|
||||
const auto& model = _testModel.getBaseModel();
|
||||
const auto& processedData = dataProcessor->output(0);
|
||||
const auto& processedShape = shapeProcessor->output(0);
|
||||
ASSERT_NO_THROW(model->connectDataWithShape(processedShape, processedData));
|
||||
|
||||
const auto& dataToShapeEdge = processedShape->childDataToShapeEdges().front();
|
||||
ASSERT_NE(dataToShapeEdge, nullptr);
|
||||
|
||||
ASSERT_NO_THROW(model->disconnectDatas(dataToShapeEdge));
|
||||
|
||||
ASSERT_EQ(processedData->parentDataToShapeEdge(), nullptr);
|
||||
ASSERT_TRUE(processedShape->childDataToShapeEdges().empty());
|
||||
ASSERT_TRUE(processedShape->dependentStagesEdges().empty());
|
||||
}
|
||||
|
||||
} // namespace vpu
|
||||
|
@ -15,15 +15,54 @@ protected:
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(InitCompileEnv());
|
||||
|
||||
_middleEnd = passManager->buildMiddleEnd();
|
||||
_testModel = CreateTestModel();
|
||||
}
|
||||
|
||||
protected:
|
||||
TestModel _testModel;
|
||||
PassSet::Ptr _middleEnd = nullptr;
|
||||
};
|
||||
|
||||
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) {
|
||||
//
|
||||
// -> [Data] -> (Stage) -> [Output]
|
||||
@ -46,6 +85,29 @@ TEST_F(StageDependencyEdgeProcessingTests, AddStageDependencyDoesNotAssertOnOutp
|
||||
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]
|
||||
@ -101,4 +163,244 @@ TEST_F(StageDependencyEdgeProcessingTests, NetWithThreeStagesHasCorrectExecOrder
|
||||
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]
|
||||
//
|
||||
|
||||
const DataDesc desc{1};
|
||||
|
||||
_testModel.createInputs({desc});
|
||||
_testModel.createOutputs({desc, desc});
|
||||
|
||||
auto dependencyProducer = _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 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));
|
||||
}
|
||||
|
||||
TEST_F(StageDependencyEdgeProcessingTests, ReplaceDependentStageAssertsIfDependencyExists) {
|
||||
//
|
||||
// -> [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->replaceDependentStage(edge, dependentStage));
|
||||
}
|
||||
|
||||
TEST_F(StageDependencyEdgeProcessingTests, ReplaceDependentStageReplacesConnection) {
|
||||
//
|
||||
// -> [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 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 model = _testModel.getBaseModel();
|
||||
|
||||
ASSERT_NO_THROW(model->addStageDependency(initialDependentStage, dependencyProducer->output(0)));
|
||||
|
||||
ASSERT_TRUE(checkExecutionOrder(model, {dependencyProducer->id(), initialDependentStage->id()}));
|
||||
ASSERT_TRUE(checkExecutionOrder(model, {resultDependentStage->id(), dependencyProducer->id()}));
|
||||
|
||||
const auto edge = dependencyProducer->output(0)->dependentStagesEdges().front();
|
||||
|
||||
ASSERT_NO_THROW(model->replaceDependentStage(edge, resultDependentStage));
|
||||
|
||||
ASSERT_EQ(edge->dependentStage(), resultDependentStage);
|
||||
|
||||
ASSERT_TRUE(checkExecutionOrder(model, {dependencyProducer->id(), resultDependentStage->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 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_NO_THROW(model->removeStageDependency(edge));
|
||||
|
||||
const auto prevStages = dependentStage->prevStages();
|
||||
const auto nextStages = dependencyProducer->prevStages();
|
||||
|
||||
auto it = std::find(prevStages.begin(), prevStages.end(), dependencyProducer);
|
||||
ASSERT_EQ(it, prevStages.end());
|
||||
|
||||
it = std::find(nextStages.begin(), nextStages.end(), dependentStage);
|
||||
ASSERT_EQ(it, nextStages.end());
|
||||
}
|
||||
|
||||
} // namespace vpu
|
Loading…
Reference in New Issue
Block a user