From b22f49ff35b3c7b3ae339128e21898810e4c2919 Mon Sep 17 00:00:00 2001 From: Edward Chen <18449977+edgchen1@users.noreply.github.com> Date: Fri, 1 Dec 2023 09:41:25 -0800 Subject: [PATCH] Fix unit tests failures in build with contrib ops disabled (#18659) Fix unit tests failures in build with contrib ops disabled. - QDQTransformerTests.QDQPropagation_GH11605_Opset12_19 - TransposeOptimizerTests.QnnTransposeNonConstBroadcastInput --- .../test/optimizer/qdq_transformer_test.cc | 15 ++- .../optimizer/transpose_optimizer_test.cc | 94 +++++++++---------- 2 files changed, 60 insertions(+), 49 deletions(-) diff --git a/onnxruntime/test/optimizer/qdq_transformer_test.cc b/onnxruntime/test/optimizer/qdq_transformer_test.cc index 6b0f837c14..13333f1558 100644 --- a/onnxruntime/test/optimizer/qdq_transformer_test.cc +++ b/onnxruntime/test/optimizer/qdq_transformer_test.cc @@ -3356,16 +3356,27 @@ TEST(QDQTransformerTests, QDQPropagation_GH11605_Opset12_19) { // Original: DQ -> Tr -> SoftM -> Tr // QDQ Prop inserts a Q/DQ pair to create a QDQ node group for the Transpose: DQ -> Tr -> Q -> DQ -> SoftM -> Tr // Transpose opt phase 1 moves the Tr down until it blocks on the SoftMax: DQ -> Q -> DQ -> Tr -> SoftM -> Tr - // Transpose opt phase 2 repairs the QDQ node units: DQ -> Q -> DQ -> Tr -> Q -> DQ -> SoftM -> TR + // Transpose opt phase 2 repairs the QDQ node units: DQ -> Q -> DQ -> Tr -> Q -> DQ -> SoftM -> Tr // and removes the unnecessary DQ/Q pair at the start: DQ -> Tr -> Q -> DQ -> SoftM -> Tr - // The L2 CPU EP QDQ handling converts the DQ -> Tr -> Q to a Transpose with 8-bit data. + // The L2 CPU EP QDQ handling converts the DQ -> Tr -> Q to a Transpose with 8-bit data: Tr -> DQ -> SoftM -> Tr + // Note: This L2 CPU EP QDQ handling is currently only enabled when contrib ops are enabled. auto check_graph = [&](InferenceSessionWrapper& session) { const QDQOpKeys qdq_keys = GetQDQOpKeys(use_contrib_qdq); +#if !defined(DISABLE_CONTRIB_OPS) std::vector expected_op_types_in_order{ "Transpose", qdq_keys.dequantize_linear, "Softmax", "Transpose"}; +#else + std::vector expected_op_types_in_order{ + qdq_keys.dequantize_linear, + "Transpose", + qdq_keys.quantize_linear, + qdq_keys.dequantize_linear, + "Softmax", + "Transpose"}; +#endif const auto& graph = session.GetGraph(); GraphViewer graph_viewer(graph); diff --git a/onnxruntime/test/optimizer/transpose_optimizer_test.cc b/onnxruntime/test/optimizer/transpose_optimizer_test.cc index a1649f9e6b..5a754c745f 100644 --- a/onnxruntime/test/optimizer/transpose_optimizer_test.cc +++ b/onnxruntime/test/optimizer/transpose_optimizer_test.cc @@ -4393,7 +4393,7 @@ TEST(TransposeOptimizerTests, RegressionTest_GitHubIssue12151) { testing::ContainerEq(fetches[0].Get().DataAsSpan())); } -// These tests uses internal testing EP with static kernels which requires a full build, +// These tests use the internal testing EP with static kernels which requires a full build and contrib ops, // and the NHWC Conv which requires contrib ops #if !defined(ORT_MINIMAL_BUILD) && !defined(DISABLE_CONTRIB_OPS) @@ -4529,6 +4529,52 @@ TEST(TransposeOptimizerTests, QnnResizeOpset11) { GraphViewer viewer(graph); EXPECT_EQ(graph.GetNode(viewer.GetNodesInTopologicalOrder().back())->OpType(), "Transpose"); } + +// model where layout transform results in transposing a non-const input that is broadcast. +// this inserts Unsqueeze -> Transpose between the input and the node. +// test that QDQ node units are created for Unsqueeze and Transpose by inserting Q->DQ pairs after them +TEST(TransposeOptimizerTests, QnnTransposeNonConstBroadcastInput) { + Status status; + auto model_uri = ORT_TSTR("testdata/layout_transform_nonconst_broadcast_input.onnx"); + + SessionOptions so; + + // ASSERT_STATUS_OK(so.config_options.AddConfigEntry(kDebugLayoutTransformation, "1")); + + using InternalTestingEP = onnxruntime::internal_testing_ep::InternalTestingExecutionProvider; + + // set the test EP to support all ops in the model so that the layout transform applies to all nodes + const std::unordered_set empty_set; + auto internal_testing_ep = std::make_unique(empty_set, empty_set, DataLayout::NHWC); + internal_testing_ep->EnableStaticKernels().TakeAllNodes(); + + InferenceSessionWrapper session{so, GetEnvironment()}; + ASSERT_STATUS_OK(session.RegisterExecutionProvider(std::move(internal_testing_ep))); + ASSERT_STATUS_OK(session.Load(model_uri)); + ASSERT_STATUS_OK(session.Initialize()); + + const auto& graph = session.GetGraph(); + std::map op_to_count = CountOpsInGraph(graph); + + ASSERT_EQ(op_to_count["Transpose"], 3) << "Should have Transpose on 2 inputs and one on output."; + + // all nodes should be assigned to the internal testing EP, which also means they should be in NHWC layout + std::string expected_ep(onnxruntime::utils::kInternalTestingExecutionProvider); + for (const auto& node : graph.Nodes()) { + EXPECT_EQ(node.GetExecutionProviderType(), expected_ep) << node.OpType() << " node named '" << node.Name() + << "' was not assigned to the internal testing EP."; + // all nodes should be in QDQ node units except the Cast on an input which was not in a QDQ unit + if (node.OpType() != "QuantizeLinear" && node.OpType() != "DequantizeLinear" && node.OpType() != "Cast") { + for (auto cur_input = node.InputNodesBegin(), end = node.InputNodesEnd(); cur_input != end; ++cur_input) { + EXPECT_EQ(cur_input->OpType(), "DequantizeLinear"); + } + + for (auto cur_output = node.OutputNodesBegin(), end = node.OutputNodesEnd(); cur_output != end; ++cur_output) { + EXPECT_EQ(cur_output->OpType(), "QuantizeLinear"); + } + } + } +} #endif // !defined(ORT_MINIMAL_BUILD) && !defined(DISABLE_CONTRIB_OPS) static void CheckSharedInitializerHandling(bool broadcast) { @@ -4706,51 +4752,5 @@ TEST(TransposeOptimizerTests, SharedInitializerHandlingBroadcast2) { ASSERT_THAT(fetches_orig[0].Get().DataAsSpan(), testing::ContainerEq(fetches[0].Get().DataAsSpan())); } - -// model where layout transform results in transposing a non-const input that is broadcast. -// this inserts Unsqueeze -> Transpose between the input and the node. -// test that QDQ node units are created for Unsqueeze and Transpose by inserting Q->DQ pairs after them -TEST(TransposeOptimizerTests, QnnTransposeNonConstBroadcastInput) { - Status status; - auto model_uri = ORT_TSTR("testdata/layout_transform_nonconst_broadcast_input.onnx"); - - SessionOptions so; - - // ASSERT_STATUS_OK(so.config_options.AddConfigEntry(kDebugLayoutTransformation, "1")); - - using InternalTestingEP = onnxruntime::internal_testing_ep::InternalTestingExecutionProvider; - - // set the test EP to support all ops in the model so that the layout transform applies to all nodes - const std::unordered_set empty_set; - auto internal_testing_ep = std::make_unique(empty_set, empty_set, DataLayout::NHWC); - internal_testing_ep->EnableStaticKernels().TakeAllNodes(); - - InferenceSessionWrapper session{so, GetEnvironment()}; - ASSERT_STATUS_OK(session.RegisterExecutionProvider(std::move(internal_testing_ep))); - ASSERT_STATUS_OK(session.Load(model_uri)); - ASSERT_STATUS_OK(session.Initialize()); - - const auto& graph = session.GetGraph(); - std::map op_to_count = CountOpsInGraph(graph); - - ASSERT_EQ(op_to_count["Transpose"], 3) << "Should have Transpose on 2 inputs and one on output."; - - // all nodes should be assigned to the internal testing EP, which also means they should be in NHWC layout - std::string expected_ep(onnxruntime::utils::kInternalTestingExecutionProvider); - for (const auto& node : graph.Nodes()) { - EXPECT_EQ(node.GetExecutionProviderType(), expected_ep) << node.OpType() << " node named '" << node.Name() - << "' was not assigned to the internal testing EP."; - // all nodes should be in QDQ node units except the Cast on an input which was not in a QDQ unit - if (node.OpType() != "QuantizeLinear" && node.OpType() != "DequantizeLinear" && node.OpType() != "Cast") { - for (auto cur_input = node.InputNodesBegin(), end = node.InputNodesEnd(); cur_input != end; ++cur_input) { - EXPECT_EQ(cur_input->OpType(), "DequantizeLinear"); - } - - for (auto cur_output = node.OutputNodesBegin(), end = node.OutputNodesEnd(); cur_output != end; ++cur_output) { - EXPECT_EQ(cur_output->OpType(), "QuantizeLinear"); - } - } - } -} } // namespace test } // namespace onnxruntime