From 44313970d33a3dcc1ebd3942167cfb66160f8cfc Mon Sep 17 00:00:00 2001 From: Guoyu Wang <62914304+gwang-msft@users.noreply.github.com> Date: Fri, 20 Nov 2020 03:40:49 -0800 Subject: [PATCH] Enable scalar initializer support in NNAPI (#5875) * Add scalar initializer support in NNAPI --- .../nnapi_builtin/builders/model_builder.cc | 5 +- .../cpu/math/element_wise_ops_test.cc | 128 +++++++++++------- 2 files changed, 81 insertions(+), 52 deletions(-) diff --git a/onnxruntime/core/providers/nnapi/nnapi_builtin/builders/model_builder.cc b/onnxruntime/core/providers/nnapi/nnapi_builtin/builders/model_builder.cc index d8e0a58887..a2ba35b582 100644 --- a/onnxruntime/core/providers/nnapi/nnapi_builtin/builders/model_builder.cc +++ b/onnxruntime/core/providers/nnapi/nnapi_builtin/builders/model_builder.cc @@ -181,7 +181,10 @@ Status ModelBuilder::RegisterInitializers() { shape.push_back(SafeInt(dim)); } - ORT_RETURN_IF_NOT(!shape.empty(), "NNAPI does not support scalar initializer, tensor name, ", name); + // If we have an empty shape, this is a scalar initializer, since NNAPI does not allow empty shape, + // we will make the scalar initializer a {1} tensor + if (shape.empty()) + shape.push_back(1); Type type = Type::TENSOR_FLOAT32; switch (tensor.data_type()) { diff --git a/onnxruntime/test/providers/cpu/math/element_wise_ops_test.cc b/onnxruntime/test/providers/cpu/math/element_wise_ops_test.cc index 71920eff27..4441bdf1e8 100644 --- a/onnxruntime/test/providers/cpu/math/element_wise_ops_test.cc +++ b/onnxruntime/test/providers/cpu/math/element_wise_ops_test.cc @@ -196,21 +196,38 @@ TEST(MathOpTest, Add_Broadcast_0x0) { } TEST(MathOpTest, Add_Broadcast_0x1) { - OpTester test("Add"); + auto run = [](bool scalar_as_initializer) { + OpTester test("Add"); - test.AddInput("A", {}, {10.0f}); - test.AddInput("B", {1}, {2.0f}); - test.AddOutput("C", {1}, {12.0f}); - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kNnapiExecutionProvider}); // NNAPI: Add does not support scalar input + test.AddInput("A", {}, {10.0f}, scalar_as_initializer); + test.AddInput("B", {1}, {2.0f}); + test.AddOutput("C", {1}, {12.0f}); + test.Run(OpTester::ExpectResult::kExpectSuccess, ""); + }; + + // NNAPI only supports scalar initializer, not scalar input +#ifndef USE_NNAPI + run(false); +#endif + + run(true); } TEST(MathOpTest, Add_Broadcast_1x0) { - OpTester test("Add"); + auto run = [](bool scalar_as_initializer) { + OpTester test("Add"); - test.AddInput("A", {1}, {10.0f}); - test.AddInput("B", {}, {2.0f}); - test.AddOutput("C", {1}, {12.0f}); - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kNnapiExecutionProvider}); // NNAPI: Add does not support scalar input + test.AddInput("A", {1}, {10.0f}); + test.AddInput("B", {}, {2.0f}, scalar_as_initializer); + test.AddOutput("C", {1}, {12.0f}); + test.Run(OpTester::ExpectResult::kExpectSuccess, ""); + }; + // NNAPI only supports scalar initializer, not scalar input +#ifndef USE_NNAPI + run(false); +#endif + + run(true); } TEST(MathOpTest, Add_Broadcast_1x1) { @@ -366,18 +383,27 @@ TEST(MathOpTest, Sub) { } TEST(MathOpTest, Sub_Broadcast_Scalar) { - OpTester test("Sub"); - std::vector dims{3, 3}; - test.AddInput("A", dims, - {1.0f, 2.0f, -1.0f, - 0.0f, 1.5f, -100.0f, - -5.4f, 9.3f, -10000.0f}); - test.AddInput("B", {}, {5.0f}); - test.AddOutput("C", dims, - {-4.0f, -3.0f, -6.0f, - -5.0f, -3.5f, -105.0f, - -10.4f, 4.3f, -10005.0f}); - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kNnapiExecutionProvider}); // NNAPI: Sub does not support scalar input + auto run = [](bool scalar_as_initializer) { + OpTester test("Sub"); + std::vector dims{3, 3}; + test.AddInput("A", dims, + {1.0f, 2.0f, -1.0f, + 0.0f, 1.5f, -100.0f, + -5.4f, 9.3f, -10000.0f}); + test.AddInput("B", {}, {5.0f}, scalar_as_initializer); + test.AddOutput("C", dims, + {-4.0f, -3.0f, -6.0f, + -5.0f, -3.5f, -105.0f, + -10.4f, 4.3f, -10005.0f}); + test.Run(OpTester::ExpectResult::kExpectSuccess, ""); + }; + + // NNAPI only supports scalar initializer, not scalar input +#ifndef USE_NNAPI + run(false); +#endif + + run(true); } TEST(MathOpTest, Mul_int32) { @@ -424,11 +450,11 @@ TEST(MathOpTest, Div_int32) { test.AddInput("A", {3}, {4, 8, 8}); test.AddInput("B", {3}, {1, 3, 2}); test.AddOutput("C", {3}, {4, 2, 4}); - #if defined(OPENVINO_CONFIG_MYRIAD) || defined(OPENVINO_CONFIG_VAD_M) - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kOpenVINOExecutionProvider}); // OpenVINO EP: Hardware limitation - #else - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); //TensorRT parser:elementwise inputs must not be Int32 - #endif +#if defined(OPENVINO_CONFIG_MYRIAD) || defined(OPENVINO_CONFIG_VAD_M) + test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kOpenVINOExecutionProvider}); // OpenVINO EP: Hardware limitation +#else + test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); //TensorRT parser:elementwise inputs must not be Int32 +#endif } TEST(MathOpTest, Div_int64) { @@ -436,11 +462,11 @@ TEST(MathOpTest, Div_int64) { test.AddInput("A", {3}, {4, 8, 8}); test.AddInput("B", {3}, {2, 3, 4}); test.AddOutput("C", {3}, {2, 2, 2}); - #if defined(OPENVINO_CONFIG_MYRIAD) || defined(OPENVINO_CONFIG_VAD_M) - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kOpenVINOExecutionProvider}); // OpenVINO EP: Hardware limitation - #else - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); //TensorRT parser:elementwise inputs must not be Int32 - #endif +#if defined(OPENVINO_CONFIG_MYRIAD) || defined(OPENVINO_CONFIG_VAD_M) + test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kOpenVINOExecutionProvider}); // OpenVINO EP: Hardware limitation +#else + test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); //TensorRT parser:elementwise inputs must not be Int32 +#endif } TEST(MathOpTest, Div) { @@ -549,13 +575,13 @@ TEST(MathOpTest, Ceil) { test.AddOutput("Y", dims, {-1.0f, 1.0f, 0.0f, 11.0f}); - #if defined(OPENVINO_CONFIG_GPU_FP16) || defined(OPENVINO_CONFIG_GPU_FP32) || defined(OPENVINO_CONFIG_MYRIAD) || defined(OPENVINO_CONFIG_VAD_M) +#if defined(OPENVINO_CONFIG_GPU_FP16) || defined(OPENVINO_CONFIG_GPU_FP32) || defined(OPENVINO_CONFIG_MYRIAD) || defined(OPENVINO_CONFIG_VAD_M) //OpenVINO: Disabled due to software limitation for GPU and VPU Plugins. //This test runs fine on CPU Plugin - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kOpenVINOExecutionProvider}); - #else - test.Run(); - #endif + test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kOpenVINOExecutionProvider}); +#else + test.Run(); +#endif } TEST(MathOpTest, Reciprocal) { @@ -1518,11 +1544,11 @@ TEST(MathOpTest, Equal_int64) { test.AddInput("A", dims, {1, 0, -1, -1}); test.AddInput("B", dims, {1, 1, 2, -1}); test.AddOutput("C", dims, {true, false, false, true}); - #if defined(OPENVINO_CONFIG_MYRIAD) || defined(OPENVINO_CONFIG_VAD_M) - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kOpenVINOExecutionProvider}); - #else - test.Run(); - #endif +#if defined(OPENVINO_CONFIG_MYRIAD) || defined(OPENVINO_CONFIG_VAD_M) + test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kOpenVINOExecutionProvider}); +#else + test.Run(); +#endif } TEST(MathOpTest, Equal_float) { @@ -1713,9 +1739,9 @@ TEST(MathOpTest, Expand_8_3x3_string) { test.AddInput("data_0", {1}, {"1"}); test.AddInput("data_1", {2}, {3, 3}); test.AddOutput("result", {3, 3}, - {"1", "1", "1", - "1", "1", "1", - "1", "1", "1"}); + {"1", "1", "1", + "1", "1", "1", + "1", "1", "1"}); test.Run(); } @@ -1724,9 +1750,9 @@ TEST(MathOpTest, Expand_8_3x1_string) { test.AddInput("data_0", {3}, {"1", "2", "3"}); test.AddInput("data_1", {2}, {3, 1}); test.AddOutput("result", {3, 3}, - {"1", "2", "3", - "1", "2", "3", - "1", "2", "3"}); + {"1", "2", "3", + "1", "2", "3", + "1", "2", "3"}); test.Run(); } @@ -1735,9 +1761,9 @@ TEST(MathOpTest, Expand_8_1x3_string) { test.AddInput("data_0", {3, 1}, {"1", "2", "3"}); test.AddInput("data_1", {2}, {1, 3}); test.AddOutput("result", {3, 3}, - {"1", "1", "1", - "2", "2", "2", - "3", "3", "3"}); + {"1", "1", "1", + "2", "2", "2", + "3", "3", "3"}); test.Run(); }