Ignore DequantizeLinear nodes in CommonSubexpressionElimination optimizer (#10934)

* Ignore DequantizeLinear nodes in CommonSubexpressionElimination.

Coalescing DQ nodes results in QDQ node groups having overlaps, which the QDQ processing does not support.
This commit is contained in:
Scott McKay 2022-03-23 08:46:01 +10:00 committed by GitHub
parent b88fb68fac
commit b28e5064f3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 31 additions and 1 deletions

View file

@ -318,7 +318,13 @@ struct NodeArgPtrEquality {
};
bool IsNodeSupported(const Node& node) {
return !node.ContainsSubgraph() && optimizer_utils::IsOperationDeterministic(node.Domain(), node.OpType());
// skip control flow nodes, nodes that produce non-deterministic output, and DequantizeLinear (DQ) nodes.
// the reason for skipping DQ is that the QDQ handling looks for QDQ node groups (DQ -> fp32 node -> Q node)
// and does not allow for a DQ node to be used in multiple groups. coalescing multiple DQ nodes into one
// would result in it having multiple consumers for its output, and it being used in multiple QDQ node groups.
return !node.ContainsSubgraph() &&
optimizer_utils::IsOperationDeterministic(node.Domain(), node.OpType()) &&
!(node.Domain() == kOnnxDomain && node.OpType() == "DequantizeLinear");
}
} // namespace

View file

@ -149,6 +149,24 @@ TEST_F(GraphTransformationTests, IdentityWithSharedNodeArgNotEliminated) {
ASSERT_TRUE(op_to_count["Add"] == 1);
}
TEST_F(GraphTransformationTests, DequantizeLinearNodeNotEliminated) {
auto model_uri = MODEL_FOLDER "qdq_with_multi_consumer_dq_nodes.fixed.onnx";
std::shared_ptr<Model> model;
ASSERT_STATUS_OK(Model::Load(model_uri, model, nullptr, *logger_));
Graph& graph = model->MainGraph();
std::map<std::string, int> op_to_count = CountOpsInGraph(graph);
ASSERT_EQ(op_to_count["DequantizeLinear"], 25);
onnxruntime::GraphTransformerManager graph_transformation_mgr{5};
ASSERT_STATUS_OK(graph_transformation_mgr.Register(std::make_unique<CommonSubexpressionElimination>(),
TransformerLevel::Level1));
ASSERT_STATUS_OK(graph_transformation_mgr.ApplyTransformers(graph, TransformerLevel::Level1, *logger_));
// CommonSubexpressionElimination should skip the DequantizeLinear nodes
op_to_count = CountOpsInGraph(graph);
ASSERT_EQ(op_to_count["DequantizeLinear"], 25);
}
TEST_F(GraphTransformationTests, IdentityInputIsGraphOutputNotEliminated) {
auto model_uri = MODEL_FOLDER "scan9_sum.onnx";
std::shared_ptr<Model> model;

View file

@ -0,0 +1,6 @@
Model was created by running
python -m onnxruntime.tools.qdq_helpers.optimize_qdq_model <ORT root>\onnxruntime\test\testdata\qdq_with_multi_consumer_dq_nodes.onnx <ORT root>\onnxruntime\test\testdata\transform
qdq_with_multi_consumer_dq_nodes.fixed.onnx
This results in a model that has duplicated DequantizeLinear (DQ) nodes so that each QDQ node group has no shared nodes. The CommonSubexpressionElimination optimizer could potentially combine these duplicated DQ nodes, which would break the QDQ handling. Due to this we ignore DQ nodes in that optimizer.