Skip to content

Commit

Permalink
Review comments applied
Browse files Browse the repository at this point in the history
  • Loading branch information
v-Golubev committed Nov 20, 2023
1 parent 59d5b5e commit b8691c8
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 70 deletions.
46 changes: 21 additions & 25 deletions src/plugins/intel_cpu/src/graph_optimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2523,32 +2523,28 @@ void GraphOptimizer::mergeTransposeReshapeReorder(Graph& graph,
}
OPENVINO_ASSERT(edge, "Parent node '", parentNode->getName(), "' has invalid edges.");

// transposeNode support blocked input & non-blocked output, in the case, the Reorder after Transpose cannot be optimized
std::vector<int> srcPerm;
if (!reverseOrder) {
// case 1. transposeNode support blocked input & non-blocked output, in the case, the reorder
// cannot be optimized
// case 2. Transpose and Reorder do opposite permutation to each other as expected, but isOptimized is already
// set false due to some preliminarily checks. We need to reinterpret layout Transpose input without physical
// change of the memory.
auto* castedTranspose = dynamic_cast<Transpose*>(transposeNode.get());
OPENVINO_ASSERT(castedTranspose,
"[CPU] parent node of type:",
transposeNode->getTypeStr(),
" with name: ",
transposeNode->getName(),
" is not a transpose node");

auto inOrder = transposeNode->getSelectedPrimitiveDescriptor()->getConfig().inConfs[0].getMemDesc()->as<BlockedMemoryDesc>()->getOrder();
auto outOrder = reorderOutDesc->as<BlockedMemoryDesc>()->getOrder();
if (!isOptimized || inOrder.size() > outOrder.size()) {
isOptimized = false;
// inDesc should be permuted before calling reorder
auto& ord = castedTranspose->getOrder();
srcPerm = std::vector<int>(ord.size());
for (size_t i = 0; i < ord.size(); i++) {
srcPerm[ord[i]] = i;
}
auto* castedTranspose = dynamic_cast<Transpose*>(transposeNode.get());
OPENVINO_ASSERT(castedTranspose,
"[CPU] parent node of type:",
transposeNode->getTypeStr(),
" with name: ",
transposeNode->getName(),
" is not a transpose node");

auto inOrder = transposeNode->getSelectedPrimitiveDescriptor()->getConfig().inConfs[0].getMemDesc()->as<BlockedMemoryDesc>()->getOrder();
auto outOrder = reorderOutDesc->as<BlockedMemoryDesc>()->getOrder();
// Permutation must be set and reorder mustn't be optimized in 2 cases:
// 1. Transpose has blocked input & non-blocked output
// 2. Transpose and Reorder do opposite permutation to each other as expected,
// but isOptimized is already set to false due to some preliminarily checks.
if (!isOptimized || inOrder.size() > outOrder.size()) {
isOptimized = false;
// inDesc should be permuted before calling reorder
auto& ord = castedTranspose->getOrder();
srcPerm = std::vector<int>(ord.size());
for (size_t i = 0; i < ord.size(); i++) {
srcPerm[ord[i]] = i;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,29 @@
//
#include <gtest/gtest.h>

#include <common_test_utils/test_common.hpp>
#include <shape_inference/shape_inference_pass_through.hpp>

#include "edge.h"
#include "graph.h"
#include "ie_ngraph_utils.hpp"
#include "node.h"
#include "nodes/reorder.h"
#include "nodes/input.h"
#include "nodes/reorder.h"
#include "nodes/transpose.h"
#include "graph.h"
#include "edge.h"

#include "ov_models/builders.hpp"
#include <shape_inference/shape_inference_pass_through.hpp>
#include "ie_ngraph_utils.hpp"
#include "utils/rt_info/memory_formats_attribute.hpp"

#include "openvino/pass/visualize_tree.hpp"

using namespace ov::intel_cpu;

namespace MergeTransposeReorderCPUTest {
class DummyNode : public Node {
public:
DummyNode(const std::shared_ptr<ngraph::Node>& op, const GraphContext::CPtr context) :
Node(op, context, PassThroughShapeInferFactory()) {
OPENVINO_THROW("Can't create DummyNode from ngraph node");
DummyNode(const std::shared_ptr<ov::Node>& op, const GraphContext::CPtr context)
: Node(op, context, PassThroughShapeInferFactory()) {
OPENVINO_THROW("Can't create DummyNode from OV node");
}
DummyNode(const ov::Shape& shape,
const ov::element::Type_t& prc,
Expand Down Expand Up @@ -78,66 +82,100 @@ class DummyNode : public Node {
} // namespace MergeTransposeReorderCPUTest

using namespace MergeTransposeReorderCPUTest;
using LOOK = Edge::LOOK;
struct MergeTransposeReorderTestParams {
enum Result {IS_OPTIMIZED, NOT_OPTIMIZED};
MergeTransposeReorderTestParams(const ov::Shape& testShape,
ov::element::Type_t testPrec,
LayoutType firstNodeLayout,
LOOK firstNodeInplaceDirection,
LayoutType secondNodeLayout,
LOOK secondNodeInplaceDirection,
Result test_result)
: testShape(testShape),
testPrec(testPrec),
firstNodeLayout(firstNodeLayout),
firstNodeInplaceDirection(firstNodeInplaceDirection),
secondNodeLayout(secondNodeLayout),
secondNodeInplaceDirection(secondNodeInplaceDirection),
test_result(test_result) {}

ov::Shape testShape;
ov::element::Type_t testPrec;
LayoutType firstNodeLayout;
LOOK firstNodeInplaceDirection;
LayoutType secondNodeLayout;
LOOK secondNodeInplaceDirection;
Result test_result;
};
using Result = MergeTransposeReorderTestParams::Result;

/*
* MergeTransposeReorderIsOptimizedCPUTest to test the CPU plugin-in MergeTransposeReorder graph optimizer
* under the circumstance that the upstream node or downstream node is inPlaced thereby the inserted Reorder
* cannot be optimized.
*/
class MergeTransposeReorderIsOptimizedCPUTest : public ::testing::Test {
class MergeTransposeReorderIsOptimizedCPUTest : public testing::WithParamInterface<MergeTransposeReorderTestParams>,
public ov::test::TestsCommon {
public:
void Validate() const {
CheckTransposeCount(0);
CheckReorderOptimized(std::string("_fake"), false); // the fused node is of name "reshape_abcd_acdb_fake"
const bool is_optimized = GetParam().test_result == MergeTransposeReorderTestParams::Result::IS_OPTIMIZED;
CheckReorderOptimized(std::string("_fake"), is_optimized); // the fused reorder has always postfix "fake"
}

protected:
void SetUp() override {
CreateGraph();
MergeTransposeReorderTestParams params = GetParam();
CreateGraph(params.testShape,
params.testPrec,
params.firstNodeLayout,
params.firstNodeInplaceDirection,
params.secondNodeLayout,
params.secondNodeInplaceDirection);
}

protected:
/* graph typology
---------
|Input |
---------
|
----------
| Dummy | <*NOTE: fake node with laytout NCSP, and inplace from upstream*>
| Dummy | <*NOTE: fake node with firstNodeLayout, and firstNodeInplaceDirection*>
----------
|
|---------------|
| ---------- |
| |Transpose| |
| --------- |
| | |
| --------- |
| |Reorder | | <*NOTE: Reorder is inheristically inserted since Multiply is asking NSPC input.*>
| --------- |
|---------------|
----------
|Transpose| <*NOTE: Reorder is inserted before/after Transpose depending on first/second node layouts.*>
----------
|
-----------
| Dummy | <*NOTE: fake node with laytout NSPC, and inplace from downstream*>
| Dummy | <*NOTE: fake node with secondNodeLayout, and secondNodeInplaceDirection*>
-----------
|
---------
|Output |
---------
*/
void CreateGraph() {
//
void CreateGraph(const ov::Shape& testShape,
const ov::element::Type_t& testPrec,
LayoutType firstNodeLayout,
LOOK firstNodeInplaceDirection,
LayoutType secondNodeLayout,
LOOK secondNodeInplaceDirection) {
Config conf;
conf.rtCacheCapacity = 100;
auto context = std::make_shared<GraphContext>(conf, nullptr, nullptr, false);
const dnnl::engine cpuEngine = context->getEngine();

m_graph = std::unique_ptr<Graph>(new Graph());

OPENVINO_ASSERT(testShape.size() == 4 || testShape.size() == 3, "Only 4D and 3D shapes are supported");
// ov::Model with only a transpose node
ov::ParameterVector params{std::make_shared<ov::op::v0::Parameter>(testPrec, ov::Shape(testShape))};
auto order = std::vector<int32_t>{0, 3, 1, 2};
auto constOrder = ngraph::builder::makeConstant(ngraph::element::i32, {order.size()}, order);
auto transpose = std::make_shared<ngraph::opset5::Transpose>(params[0], constOrder);
ov::ResultVector results{std::make_shared<ngraph::opset5::Result>(transpose)};
ov::ParameterVector params{std::make_shared<ov::op::v0::Parameter>(testPrec, testShape)};
auto order = testShape.size() == 4 ? std::vector<int32_t>{0, 3, 1, 2} : std::vector<int32_t>{0, 2, 1};
auto constOrder = ngraph::builder::makeConstant(ov::element::i32, {order.size()}, order);
auto transpose = std::make_shared<ov::opset4::Transpose>(params[0], constOrder);
ov::ResultVector results{std::make_shared<ov::opset4::Result>(transpose)};

// Replicate
auto replicate = [&](std::vector<NodePtr> &nodes, std::vector<EdgePtr> &edges) -> void {
Expand All @@ -153,20 +191,18 @@ class MergeTransposeReorderIsOptimizedCPUTest : public ::testing::Test {

auto inputNode = std::make_shared<node::Input>(params[0], context);

// dummy ncsp + inPlace LOOK_UP
auto dummyNode1 = std::make_shared<MergeTransposeReorderCPUTest::DummyNode>(testShape, testPrec, "reshape", "DummyNode", context);
dummyNode1->setLayout(LayoutType::ncsp);
dummyNode1->setInplaceDirection(Edge::LOOK::LOOK_UP);
dummyNode1->setLayout(firstNodeLayout);
dummyNode1->setInplaceDirection(firstNodeInplaceDirection);

auto orderNode = std::make_shared<node::Input>(constOrder, context); // const order
auto transposeNode = std::make_shared<node::Transpose>(transpose, context);
transposeNode->filterSupportedPrimitiveDescriptors();

// dummy nspc + inPlace LOOK_DOWN
const ov::Shape shape_tranpose{testShape[0], testShape[3], testShape[1], testShape[2]}; // shape after transpose
auto dummyNode2 = std::make_shared<MergeTransposeReorderCPUTest::DummyNode>(shape_tranpose, testPrec, "multiply", "DummyNode", context);
dummyNode2->setLayout(LayoutType::nspc);
dummyNode2->setInplaceDirection(Edge::LOOK::LOOK_DOWN);
const auto& transpose_shape = transpose->get_output_shape(0);
auto dummyNode2 = std::make_shared<MergeTransposeReorderCPUTest::DummyNode>(transpose_shape, testPrec, "multiply", "DummyNode", context);
dummyNode2->setLayout(secondNodeLayout);
dummyNode2->setInplaceDirection(secondNodeInplaceDirection);

auto outputNode = std::make_shared<node::Input>(results[0], context);

Expand Down Expand Up @@ -215,12 +251,20 @@ class MergeTransposeReorderIsOptimizedCPUTest : public ::testing::Test {
}

private:
const ov::element::Type_t testPrec = ov::element::Type_t::f32;
const ov::Shape testShape{1, 3, 8, 16};

std::unique_ptr<Graph> m_graph;
}; // class MergeTransposeReorderIsOptimizedCPUTest
}; // class MergeTransposeReorderIsOptimizedCPUTest

TEST_F(MergeTransposeReorderIsOptimizedCPUTest, smoke_Run_MergeTransposeReorder_isOptimized) {
TEST_P(MergeTransposeReorderIsOptimizedCPUTest, smoke_Run_MergeTransposeReorder_isOptimized) {
Validate();
}
}

const std::vector<MergeTransposeReorderTestParams> params = {
{{1, 3, 8, 16}, ov::element::f32, LayoutType::ncsp, LOOK::LOOK_UP, LayoutType::nspc, LOOK::LOOK_DOWN, Result::NOT_OPTIMIZED},
{{1, 3, 8, 16}, ov::element::f32, LayoutType::ncsp, LOOK::LOOK_DOWN, LayoutType::nspc, LOOK::LOOK_UP, Result::IS_OPTIMIZED},
{{3, 8, 16}, ov::element::f32, LayoutType::nspc, LOOK::LOOK_UP, LayoutType::ncsp, LOOK::LOOK_DOWN, Result::NOT_OPTIMIZED},
{{3, 8, 16}, ov::element::f32, LayoutType::nspc, LOOK::LOOK_DOWN, LayoutType::ncsp, LOOK::LOOK_UP, Result::IS_OPTIMIZED},
};

INSTANTIATE_TEST_SUITE_P(smoke_Run_MergeTransposeReorder_isOptimized,
MergeTransposeReorderIsOptimizedCPUTest,
::testing::ValuesIn(params));

0 comments on commit b8691c8

Please sign in to comment.