From 3bf7a69df138aaf2598dd9c13fd9828ef56eac90 Mon Sep 17 00:00:00 2001 From: "Gladilov, Gleb" Date: Sun, 31 May 2020 13:17:36 +0300 Subject: [PATCH] [IE][VPU]: Faster-RCNN fixes on myriad plugin side (#665) * [IE][VPU]: Fixes deallocation data for cases of CMX allocator run The final loop tries to deallocate data objects that keep shape values for other data objects that're outputs of a model. But the case when allocator takes only CMX data into consideration was not handled and since allocation could not happen, it lead to fail on deallocation of a data object that has not been allocated. Signed-off-by: Gladilov, Gleb * [IE][VPU]: Fixes allocator with work on data to shape edges Since there is new relationship between data objects: some data objects may contain shape of other data object - allocator must properly respect that. The thing is if 2 data objects are connected in such a way, they represent unite entity (dynamic data object) and should have the same lifetime. Signed-off-by: Gladilov, Gleb --- .../src/middleend/allocator/allocator.cpp | 56 ++++++++++++++++------ .../src/middleend/passes/allocate_resources.cpp | 16 +++---- 2 files changed, 48 insertions(+), 24 deletions(-) diff --git a/inference-engine/src/vpu/graph_transformer/src/middleend/allocator/allocator.cpp b/inference-engine/src/vpu/graph_transformer/src/middleend/allocator/allocator.cpp index 5c9ee38..92663b9 100644 --- a/inference-engine/src/vpu/graph_transformer/src/middleend/allocator/allocator.cpp +++ b/inference-engine/src/vpu/graph_transformer/src/middleend/allocator/allocator.cpp @@ -92,6 +92,27 @@ void updateChildDataAllocation(const Data& data, int offsetLimitation) { } } +int getInUse(const Data& data) { + int inUse = 0; + inUse += data->numConsumers(); + for (const auto& childData : data->childDatas()) { + inUse += getInUse(childData); + } + for (const auto& childEdge : data->childDataToShapeEdges()) { + auto const& child = childEdge->child(); + if (child->usage() == DataUsage::Output) { + VPU_THROW_UNLESS(child->parentData() == nullptr, "Output data object must not have parent"); + inUse++; + } else if (child->getTopParentData() == child) { + inUse += getInUse(child); + } else { + inUse += child->numConsumers(); + } + } + return inUse; +} + + } // namespace bool Allocator::allocateData(const Data& data) { @@ -247,14 +268,9 @@ bool Allocator::allocateData(const Data& data) { if (data->usage() == DataUsage::Temp) { inUse = 1; } else { - loopOverData(data, [&inUse](const Data& subData) { - inUse += subData->numConsumers(); - return DataLoopStatus::NextChild; - }); + inUse = getInUse(data); } - inUse += data->childDataToShapeEdges().size(); - VPU_INTERNAL_CHECK(inUse >= 1, "allocateData failed: data {} with usage {} isn't used by anything", data->name(), data->usage()); @@ -356,23 +372,35 @@ void Allocator::freeData(const Data& data, DeallocationMode mode) { // Release the chunk // - if (const auto& parentDataToShapeEdge = data->parentDataToShapeEdge()) { - auto const& parent = parentDataToShapeEdge->parent(); - - if (parent->usage() == DataUsage::Intermediate || parent->usage() == DataUsage::Temp) { - auto chunk = getChunk(parent); - decreaseChunkUsage(chunk, parent); + auto topParent = data->getTopParentData(); + if (topParent != data) { + if (const auto& parentDataToShapeEdge = data->parentDataToShapeEdge()) { + const auto& parent = parentDataToShapeEdge->parent(); + + if (parent->usage() == DataUsage::Intermediate || parent->usage() == DataUsage::Temp) { + const auto dtopParent = parent->getTopParentData(); + const auto chunk = getChunk(dtopParent); + decreaseChunkUsage(chunk, dtopParent); + } } } - auto topParent = data->getTopParentData(); - if (topParent->usage() == DataUsage::Intermediate || topParent->usage() == DataUsage::Temp) { auto chunk = getChunk(topParent); switch (mode) { case DeallocationMode::JustFree: { + if (const auto& parentDataToShapeEdge = topParent->parentDataToShapeEdge()) { + const auto& parent = parentDataToShapeEdge->parent(); + + if (parent->usage() == DataUsage::Intermediate || parent->usage() == DataUsage::Temp) { + const auto dtopParent = parent->getTopParentData(); + const auto dchunk = getChunk(dtopParent); + decreaseChunkUsage(dchunk, dtopParent); + } + } + decreaseChunkUsage(chunk, topParent); break; } diff --git a/inference-engine/src/vpu/graph_transformer/src/middleend/passes/allocate_resources.cpp b/inference-engine/src/vpu/graph_transformer/src/middleend/passes/allocate_resources.cpp index b99b538..81941de 100644 --- a/inference-engine/src/vpu/graph_transformer/src/middleend/passes/allocate_resources.cpp +++ b/inference-engine/src/vpu/graph_transformer/src/middleend/passes/allocate_resources.cpp @@ -188,19 +188,15 @@ AllocationResult runAllocator(const Model& model, bool onlyCheckCMX) { // Clean up undeallocated shapes // - for (const auto& data : model->datas()) { - if (data->childDataToShapeEdges().empty()) { - continue; - } - - if (data->usage() != DataUsage::Intermediate) { + for (auto data : model->datas()) { + if (data->usage() != DataUsage::Output) { continue; } - for (const auto& dataToShapeEdge : data->childDataToShapeEdges()) { - if (dataToShapeEdge->child()->usage() == DataUsage::Output) { - allocator.freeData(data); - break; + if (const auto& parentEdge = data->parentDataToShapeEdge()) { + const auto& parent = parentEdge->parent(); + if (parent->usage() == DataUsage::Intermediate && (!onlyCheckCMX || parent->memReqs() == MemoryType::CMX)) { + allocator.freeData(parent); } } } -- 2.7.4