Skip to content

Commit

Permalink
[CPU] Fix resolve edge conflicts Convert insertion (openvinotoolkit#2…
Browse files Browse the repository at this point in the history
…5643)

### Details
- Current version does not clean extra edge in case Convert + Reorder is
inserted. In this case we need to remove an edge, which is replaced with
Convert node first, and then remove childEdge of the newly inserted
Convert node, after Reorder is inserted.
- The idea is to simplify this logic and do one thing at a time:
1. Insert Convert.
2. If Reorder is still necessary for the new inserted edge, it will be
handled later in the loop.

It seems to be impossible to write a test for x86 platform, since there
is no reorder which does not support precision conversion.
  • Loading branch information
EgorDuplensky authored Aug 16, 2024
1 parent e7e6d8b commit 8713ca2
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 45 deletions.
94 changes: 49 additions & 45 deletions src/plugins/intel_cpu/src/graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "graph.h"

#include <algorithm>
#include <cstddef>
#include <limits>
#include <map>
#include <memory>
Expand Down Expand Up @@ -557,70 +558,73 @@ void Graph::insertReorder(EdgePtr& edge, bool isOptimized, std::unordered_set<st
InsertReorder(edge, layerName, edge->getInputDesc(), edge->getOutputDesc(), isOptimized);
}

void Graph::ResolveEdgeConflicts() {
OV_ITT_SCOPE(FIRST_INFERENCE, itt::domains::intel_cpu_LT, "Graph::ResolveEdgeConflicts");
void Graph::insertConvert(EdgePtr& edge) {
const auto& inDesc = edge->getInputDesc();
const auto& outDesc = edge->getOutputDesc();

ptrdiff_t numberOfEdges = static_cast<ptrdiff_t>(graphEdges.size());
std::string convertName = edge->getParent()->getName() + "_" +
inDesc.getPrecision().get_type_name() + "_" + outDesc.getPrecision().get_type_name();

auto convertNode = std::make_shared<node::Convert>(inDesc.getShape(), inDesc.getPrecision(), outDesc.getPrecision(),
convertName, context);
convertNode->setDescs(inDesc, outDesc);
InsertNode(edge, convertNode, true);
}

static std::unordered_set<std::string> getUniqueLayerNames(const std::vector<NodePtr>& graphNodes) {
std::unordered_set<std::string> uniqueLayerNames;
uniqueLayerNames.reserve(graphNodes.size());

for (auto node : graphNodes) {
uniqueLayerNames.insert(node->getName());
}

auto updateEdge = [&](ptrdiff_t& i) {
graphEdges.erase(graphEdges.begin() + i);
i--;
numberOfEdges--;
};
return uniqueLayerNames;
}

for (ptrdiff_t i = 0; i < numberOfEdges; i++) {
auto edge = graphEdges[i];
auto reorderStatus = graphEdges[i]->needReorder();
DEBUG_LOG(graphEdges[i]->name(), " reorderStatus = ", reorderStatus);
if (reorderStatus == Edge::ReorderStatus::Regular) {
Edge::ReorderStatus reorderStatusInternal = Edge::ReorderStatus::Regular;
// Check if there is a reorder that needs the precision conversion
if (edge->getInputDesc().getPrecision() != edge->getOutputDesc().getPrecision() &&
!isReorderAvailable(edge->getInputPortDesc()->getMemDesc(),
edge->getOutputPortDesc()->getMemDesc(),
this->getEngine())) {
// If we are here, then we need to insert Convert, because there are no reorders that support such type conversion
const auto& inDesc = edge->getInputDesc();
const auto& outDesc = edge->getOutputDesc();

std::string convertName = edge->getParent()->getName() + "_" +
inDesc.getPrecision().get_type_name() + "_" + outDesc.getPrecision().get_type_name();

auto convertNode = std::make_shared<node::Convert>(inDesc.getShape(), inDesc.getPrecision(), outDesc.getPrecision(),
convertName, context);
convertNode->setDescs(inDesc, outDesc);
InsertNode(edge, convertNode, true);

//Check if reorder is still needed
reorderStatusInternal = convertNode->getChildEdgeAt(0)->needReorder();
if (reorderStatusInternal != Edge::ReorderStatus::No)
edge = convertNode->getChildEdgeAt(0);
}
if (reorderStatusInternal != Edge::ReorderStatus::No) {
insertReorder(edge, reorderStatusInternal == Edge::ReorderStatus::Optimized, uniqueLayerNames);
void Graph::ResolveEdgeConflicts() {
OV_ITT_SCOPE(FIRST_INFERENCE, itt::domains::intel_cpu_LT, "Graph::ResolveEdgeConflicts");

std::unordered_set<std::string> uniqueLayerNames = getUniqueLayerNames(graphNodes);

/* When inserting convert / reorder, two new edges are added (pushed to the end) to the graphEdges.
So use a plain for loop, to handle newly inserted edges as well */
for (size_t i = 0; i < graphEdges.size(); i++) {
auto& edge = graphEdges[i];
auto reorderStatus = edge->needReorder();
DEBUG_LOG(*edge, " reorderStatus = ", reorderStatus);

switch (reorderStatus) {
case Edge::ReorderStatus::Regular: {
if (reorderStatus == Edge::ReorderStatus::Regular &&
edge->getInputDesc().getPrecision() != edge->getOutputDesc().getPrecision() &&
!isReorderAvailable(edge->getInputPortDesc()->getMemDesc(),
edge->getOutputPortDesc()->getMemDesc(),
this->getEngine())) {
// just insert convert. If layout reorder is still needed, it will be inserted later in the traverse
insertConvert(edge);
} else {
insertReorder(edge, false, uniqueLayerNames);
}
updateEdge(i);
} else if (reorderStatus == Edge::ReorderStatus::Optimized) {
break;
}
case Edge::ReorderStatus::Optimized:
insertReorder(edge, true, uniqueLayerNames);
updateEdge(i);
break;
case Edge::ReorderStatus::No:
break;
}
}

RemoveDroppedEdges();
}

void Graph::ResolveComplexInplaceConflicts() {
OV_ITT_SCOPE(FIRST_INFERENCE, itt::domains::intel_cpu_LT, "Graph::ResolveComplexInplaceConflicts");

ptrdiff_t numberOfEdges = static_cast<ptrdiff_t>(graphEdges.size());

std::unordered_set<std::string> uniqueLayerNames;
for (auto node : graphNodes) {
uniqueLayerNames.insert(node->getName());
}
std::unordered_set<std::string> uniqueLayerNames = getUniqueLayerNames(graphNodes);

auto updateEdge = [&](ptrdiff_t& i) {
graphEdges.erase(graphEdges.begin() + i);
Expand Down
1 change: 1 addition & 0 deletions src/plugins/intel_cpu/src/graph.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ class Graph {
void EnforceInferencePrecision();
void EnforceBF16();
void insertReorder(EdgePtr& edge, bool isOptimized, std::unordered_set<std::string>& uniqueLayerNames);
void insertConvert(EdgePtr& edge);
};

using GraphPtr = std::shared_ptr<Graph>;
Expand Down

0 comments on commit 8713ca2

Please sign in to comment.