diff --git a/onnxruntime/core/providers/nnapi/nnapi_builtin/builders/op_support_checker.cc b/onnxruntime/core/providers/nnapi/nnapi_builtin/builders/op_support_checker.cc index aebba40590..cf0b555778 100644 --- a/onnxruntime/core/providers/nnapi/nnapi_builtin/builders/op_support_checker.cc +++ b/onnxruntime/core/providers/nnapi/nnapi_builtin/builders/op_support_checker.cc @@ -1566,10 +1566,23 @@ class UnaryOpSupportChecker : public BaseOpSupportChecker { bool UnaryOpSupportChecker::IsOpSupportedImpl(const InitializedTensorSet& initializers, const NodeUnit& node_unit, const OpSupportCheckParams& params) const { - if (node_unit.OpType() == "QLinearSigmoid") + if (node_unit.OpType() == "QLinearSigmoid") { return IsQuantizedOpSupported(initializers, node_unit, params); - else // Everything except "QLinearSigmoid" are by default supported + } else if (node_unit.OpType() == "Sigmoid") { + Shape input_shape; + if (!GetShape(node_unit.Inputs()[0].node_arg, input_shape)) + return false; + + const auto input_size = input_shape.size(); + if (input_size > 4 || input_size == 0) { + LOGS_DEFAULT(VERBOSE) << "ANEURALNETWORKS_LOGISTIC only supports 1-4d shape, input is " + << input_size << "d shape"; + return false; + } return true; + } + // Everything else are by default supported + return true; } int32_t UnaryOpSupportChecker::GetMinSupportedNNAPIFeatureLevel(const NodeUnit& node_unit, diff --git a/onnxruntime/test/providers/nnapi/nnapi_basic_test.cc b/onnxruntime/test/providers/nnapi/nnapi_basic_test.cc index e16c4b15f8..4f372ec833 100644 --- a/onnxruntime/test/providers/nnapi/nnapi_basic_test.cc +++ b/onnxruntime/test/providers/nnapi/nnapi_basic_test.cc @@ -85,6 +85,30 @@ TEST(NnapiExecutionProviderTest, ReshapeFlattenTest) { #endif } +TEST(NnapiExecutionProviderTest, SigmoidSupportedInputRankTest) { + const ORTCHAR_T* model_file_name = ORT_TSTR("testdata/nnapi_sigmoid_input_rank_test.onnx"); + +#if defined(__ANDROID__) + std::vector dims_mul_x = {2, 1, 2, 1, 2}; + std::vector values_mul_x = {1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f}; + + OrtValue ml_value_x; + CreateMLValue(TestNnapiExecutionProvider()->GetAllocator(0, OrtMemTypeDefault), dims_mul_x, values_mul_x, + &ml_value_x); + NameMLValMap feeds; + feeds.insert(std::make_pair("X", ml_value_x)); + + RunAndVerifyOutputsWithEP(model_file_name, "NnapiExecutionProviderTest.SigmoidSupportedInputRankTest", + std::make_unique(0), + feeds, {ExpectedEPNodeAssignment::None} /* params */); +#else + // test load only + TestModelLoad(model_file_name, + [](const Graph& graph) { ASSERT_EQ(CountAssignedNodes(graph, kNnapiExecutionProvider), 0) + << "No nodes should have been taken by the NNAPI EP"; }); +#endif +} + // Since NNAPI EP does not support dynamic shape input and we now switch from the approach of immediately rejecting // the whole graph in NNAPI EP if it has a dynamic input to check at individual operator support check level, we have a // separated test here. diff --git a/onnxruntime/test/testdata/nnapi_sigmoid_input_rank_test.onnx b/onnxruntime/test/testdata/nnapi_sigmoid_input_rank_test.onnx new file mode 100644 index 0000000000..fef9e610bc --- /dev/null +++ b/onnxruntime/test/testdata/nnapi_sigmoid_input_rank_test.onnx @@ -0,0 +1,17 @@ +:{ + +XYsigmoid"SigmoidNnapi_sigmoid_input_rank_testZ +X + + + + + +b +Y + + + + + +B \ No newline at end of file diff --git a/onnxruntime/test/testdata/nnapi_sigmoid_input_rank_test.py b/onnxruntime/test/testdata/nnapi_sigmoid_input_rank_test.py new file mode 100644 index 0000000000..160e8ba73a --- /dev/null +++ b/onnxruntime/test/testdata/nnapi_sigmoid_input_rank_test.py @@ -0,0 +1,25 @@ +import onnx +from onnx import TensorProto, helper + +# Since NNAPI ANEURALNETWORKS_LOGISTIC only supports input tensor rank up to 4, we added limits in +# Sigmoid op support checker in NNAPI EP, so we don't fail hard. Added test case here. + + +def GenerateModel(model_name): + node = [ + helper.make_node("Sigmoid", ["X"], ["Y"], "sigmoid"), + ] + + graph = helper.make_graph( + node, + "Nnapi_sigmoid_input_rank_test", + [helper.make_tensor_value_info("X", TensorProto.FLOAT, [2, 1, 2, 1, 2])], # input + [helper.make_tensor_value_info("Y", TensorProto.FLOAT, [2, 1, 2, 1, 2])], # output + ) + + model = helper.make_model(graph) + onnx.save(model, model_name) + + +if __name__ == "__main__": + GenerateModel("nnapi_sigmoid_input_rank_test.onnx")