From ec935a55332f8dcfabaf09e216488da614ba1292 Mon Sep 17 00:00:00 2001 From: Hector Li Date: Thu, 27 Jul 2023 09:59:46 -0700 Subject: [PATCH] [QNN EP] Check the axis attribute for LayerNorm for HTP (#16872) Check the axis attribute for LayerNorm for HTP ### Description Add code to check the axis value for LayerNorm for HTP explicitly to make sure only the last dimension is allowed. --- .../qnn/builder/opbuilder/base_op_builder.h | 1 - .../qnn/builder/opbuilder/layer_norm_op_builder.cc | 12 ++++++++++++ onnxruntime/test/providers/qnn/layer_norm_test.cc | 4 ++-- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/onnxruntime/core/providers/qnn/builder/opbuilder/base_op_builder.h b/onnxruntime/core/providers/qnn/builder/opbuilder/base_op_builder.h index df1d0ac83d..e8a1eb1901 100644 --- a/onnxruntime/core/providers/qnn/builder/opbuilder/base_op_builder.h +++ b/onnxruntime/core/providers/qnn/builder/opbuilder/base_op_builder.h @@ -135,7 +135,6 @@ class BaseOpBuilder : public IOpBuilder { {"Elu", QNN_OP_ELU}, {"Relu", QNN_OP_RELU}, {"Gelu", QNN_OP_GELU}, - {"Sigmoid", QNN_OP_SIGMOID}, {"HardSwish", QNN_OP_HARD_SWISH}, diff --git a/onnxruntime/core/providers/qnn/builder/opbuilder/layer_norm_op_builder.cc b/onnxruntime/core/providers/qnn/builder/opbuilder/layer_norm_op_builder.cc index a6bbb3b872..e224cb3454 100644 --- a/onnxruntime/core/providers/qnn/builder/opbuilder/layer_norm_op_builder.cc +++ b/onnxruntime/core/providers/qnn/builder/opbuilder/layer_norm_op_builder.cc @@ -54,6 +54,18 @@ Status LayerNormOpBuilder::IsOpSupported(QnnModelWrapper& qnn_model_wrapper, ORT_RETURN_IF(!is_quantized_model && output_data_type != float_elem_type, "QNN LayerNorm data type ", output_data_type->c_str(), " is not supported in CPU backend."); ORT_RETURN_IF(outputs.size() > 1, "QNN LayerNorm only support 1 output."); + // QNN Op validation can also do the same work, but the message is not so clear. + // Explicit check and provide clear message here + if (is_quantized_model) { + std::vector input_shape; + ORT_RETURN_IF_NOT(qnn_model_wrapper.GetOnnxShape(inputs[0].node_arg, input_shape), "Cannot get shape of input 0"); + const size_t input_rank = input_shape.size(); + int32_t default_axis = -1; + Qnn_Scalar_t axis_qnn_scalar = QNN_SCALAR_INIT; + ORT_RETURN_IF_ERROR(ProcessAxisAttribute(qnn_model_wrapper, node_unit, axis_qnn_scalar, default_axis)); + ORT_RETURN_IF(static_cast(default_axis) != input_rank - 1, "QNN LayerNorm for HTP only support axis with last input dimension"); + } + return AddToModelBuilder(qnn_model_wrapper, node_unit, logger, is_quantized_model, true); } diff --git a/onnxruntime/test/providers/qnn/layer_norm_test.cc b/onnxruntime/test/providers/qnn/layer_norm_test.cc index 97917a2816..d9512d16a1 100644 --- a/onnxruntime/test/providers/qnn/layer_norm_test.cc +++ b/onnxruntime/test/providers/qnn/layer_norm_test.cc @@ -122,8 +122,8 @@ static void RunLayerNormQDQTest(const std::vector& input_shape, // Check that QNN compiles DQ -> LayerNormalization -> Q as a single unit. // Use an input of rank 3. // Failed QNN op validation: QnnDsp Param[0] has incorrect Value 3 -TEST_F(QnnHTPBackendTests, DISABLED_TestQDQLayerNorm1DAxis0) { - RunLayerNormQDQTest({1, 2, 3}, {1, 2, 3}, ExpectedEPNodeAssignment::All); +TEST_F(QnnHTPBackendTests, TestQDQLayerNorm1DAxis0) { + RunLayerNormQDQTest({1, 2, 3}, {1, 2, 3}, ExpectedEPNodeAssignment::None); } // Failed QNN FinalizeGraphs: QnnDsp Failed to finalize graph (id: 1) with err 1002