From c572ba2956cd92d06cc33db5899b14e1425096ef Mon Sep 17 00:00:00 2001 From: LiangGao Date: Tue, 9 Dec 2025 15:26:10 +0800 Subject: [PATCH 01/12] change the code based on review inputs --- .../test/contrib_ops/quantize_ops_test.cc | 74 +++++++++- .../test/providers/cpu/tensor/cast_op_test.cc | 5 + .../cpu/tensor/quantize_linear_test.cc | 133 +++++++++++++++++- .../providers/cpu/tensor/resize_op_test.cc | 80 ++++++++++- .../providers/cpu/tensor/slice_op.test.cc | 1 + 5 files changed, 280 insertions(+), 13 deletions(-) diff --git a/onnxruntime/test/contrib_ops/quantize_ops_test.cc b/onnxruntime/test/contrib_ops/quantize_ops_test.cc index db685967ae5ff..5af8999206258 100644 --- a/onnxruntime/test/contrib_ops/quantize_ops_test.cc +++ b/onnxruntime/test/contrib_ops/quantize_ops_test.cc @@ -287,9 +287,46 @@ TEST(QuantizeLinearContribOpTest, QuantizeLinear_per_tensor_float_int8) { 127, -127, 127, -128, 127, -128}); + std::unordered_set excluded_providers; // Disable Tensorrt EP due to error: node1_quantize_scale_node: out of bounds channel axis 1. Number of input dimensions is 1. - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); + excluded_providers.insert(kTensorrtExecutionProvider); + // Disable OV EP due to different formulation for QuantizeLinear + excluded_providers.insert(kOpenVINOExecutionProvider); + test.ConfigExcludeEps(excluded_providers) + .RunWithConfig(); +} + +#ifdef USE_OPENVINO +TEST(QuantizeLinearContribOpTest, OVEPQuantizeLinear_per_tensor_float_int8) { + OpTester test("QuantizeLinear", 1, onnxruntime::kMSDomain); + std::vector dims{16}; + test.AddInput("x", dims, { + 0.f, 2.f, // + 3.f, -3.f, // rounding half to even + 2.9f, -2.9f, // low case + 3.1f, -3.1f, // up case + 254.f, -256.f, // critical point + 255.f, -257.f, // critical point + 256.f, -258.f, // critical point + 1000.f, -1000.f // saturate case + }); + test.AddInput("y_scale", {}, {2.0f}); + test.AddInput("y_zero_point", {}, {1}); + test.AddOutput("y", dims, + {1, 2, + 2, 0, + 2, 0, + 3, -1, + 127, -127, + 127, -128, + 127, -128, + 127, -128}); + std::vector> execution_providers; + execution_providers.emplace_back(DefaultOpenVINOExecutionProvider()); + test.ConfigEps(std::move(execution_providers)) + .RunWithConfig(); } +#endif // USE_OPENVINO // Test uint16 com.microsoft.QuantizeLinear (per tensor) TEST(QuantizeLinearContribOpTest, QuantizeLinear_per_tensor_float_uint16) { @@ -311,10 +348,41 @@ TEST(QuantizeLinearContribOpTest, QuantizeLinear_per_tensor_float_uint16) { 32769, 32765, 65535, 0, 65535, 0}); - + std::unordered_set excluded_providers; // Disable Tensorrt EP due to error: unsupported data type - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); + excluded_providers.insert(kTensorrtExecutionProvider); + // Disable OV EP due to different formulation for QuantizeLinear + excluded_providers.insert(kOpenVINOExecutionProvider); + test.ConfigExcludeEps(excluded_providers) + .RunWithConfig(); +} + +#ifdef USE_OPENVINO +TEST(QuantizeLinearContribOpTest, OVEPQuantizeLinear_per_tensor_float_uint16) { + OpTester test("QuantizeLinear", 1, onnxruntime::kMSDomain); + std::vector dims{12}; + test.AddInput("x", dims, { + 0.f, -128.f, 3.f, -3.f, // rounding half to even + 2.9f, -2.9f, // round < .5 + 3.1f, -3.1f, // round > .5 + 65536.f, -65534.f, // critical point + 70000.f, -70000.f // saturate case + }); + test.AddInput("scale", {}, {2.0f}, true); + test.AddInput("zero_point", {}, {32767}, true); + test.AddOutput("y", dims, + {32767, 32703, + 32768, 32766, + 32768, 32766, + 32769, 32765, + 65535, 0, + 65535, 0}); + std::vector> execution_providers; + execution_providers.emplace_back(DefaultOpenVINOExecutionProvider()); + test.ConfigEps(std::move(execution_providers)) + .RunWithConfig(); } +#endif // USE_OPENVINO // Test int16 com.microsoft.QuantizeLinear (per tensor) TEST(QuantizeLinearContribOpTest, QuantizeLinear_per_tensor_float_int16) { diff --git a/onnxruntime/test/providers/cpu/tensor/cast_op_test.cc b/onnxruntime/test/providers/cpu/tensor/cast_op_test.cc index 289e94397fb39..3cfce72bc48b3 100644 --- a/onnxruntime/test/providers/cpu/tensor/cast_op_test.cc +++ b/onnxruntime/test/providers/cpu/tensor/cast_op_test.cc @@ -75,6 +75,11 @@ void TestCastOp(gsl::span input, excluded_provider_types.insert(kCudaExecutionProvider); } + if (input.size() == 0) { + // The OpenVINO doesn't support 0 size input + excluded_provider_types.insert(kOpenVINOExecutionProvider); + } + if (cuda_only && (excluded_provider_types.count(kCudaExecutionProvider) > 0)) { return; } diff --git a/onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc b/onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc index bd8aad5f85514..c8808cbcc76ce 100644 --- a/onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc +++ b/onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc @@ -449,10 +449,43 @@ TEST(QuantizeLinearOpTest, Uint16) { 65535, 0, 65535, 0}); + std::unordered_set excluded_providers; // Disable Tensorrt EP due to error: unsupported data type - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); + excluded_providers.insert(kTensorrtExecutionProvider); + // Disable OV EP due to different formulation for QuantizeLinear + excluded_providers.insert(kOpenVINOExecutionProvider); + test.ConfigExcludeEps(excluded_providers) + .RunWithConfig(); } +#ifdef USE_OPENVINO +TEST(QuantizeLinearOpTest, OVEP_Uint16) { + OpTester test("QuantizeLinear", 21); + std::vector dims{12}; + test.AddInput("x", dims, { + 0.f, -128.f, 3.f, -3.f, // rounding half to even + 2.9f, -2.9f, // round < .5 + 3.1f, -3.1f, // round > .5 + 65536.f, -65534.f, // critical point + 70000.f, -70000.f // saturate case + }); + test.AddInput("scale", {}, {2.0f}, true); + test.AddInput("zero_point", {}, {32767}, true); + test.AddOutput("y", dims, + {32767, 32703, + 32768, 32766, + 32768, 32766, + 32769, 32765, + 65535, 0, + 65535, 0}); + + std::vector> execution_providers; + execution_providers.emplace_back(DefaultOpenVINOExecutionProvider()); + test.ConfigEps(std::move(execution_providers)) + .RunWithConfig(); +} +#endif // USE_OPENVINO + // Test int16 QuantizeLinear (per tensor) TEST(QuantizeLinearOpTest, Int16) { OpTester test("QuantizeLinear", 21); @@ -502,8 +535,40 @@ TEST(QuantizeLinearOpTest, Int4) { {Int4x2(-8, -7), Int4x2(-1, 1), Int4x2(2, 7), Int4x2(7, unused_val)}); - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); + std::unordered_set excluded_providers; + excluded_providers.insert(kTensorrtExecutionProvider); + // Disable OV EP due to different formulation for QuantizeLinear + excluded_providers.insert(kOpenVINOExecutionProvider); + test.ConfigExcludeEps(excluded_providers) + .RunWithConfig(); +} + +#ifdef USE_OPENVINO +TEST(QuantizeLinearOpTest, OVEP_Int4) { + OpTester test("QuantizeLinear", 21); + std::vector dims{7}; + constexpr int8_t unused_val = 0; + test.AddInput("x", dims, { + -20.0f, // Clamp to qmin + -16.0f, // Close to qmin + -3.0f, // round + 0.0f, // Zero-point + 2.9f, // round + 12.0f, // qmax + 20.0f, // Clamp to qmax + }); + test.AddInput("scale", {}, {2.0f}, true); + test.AddInput("zero_point", {}, {Int4x2(1, unused_val)}, true); + test.AddOutput("y", dims, + {Int4x2(-8, -7), Int4x2(0, 1), Int4x2(2, 7), + Int4x2(7, unused_val)}); + + std::vector> execution_providers; + execution_providers.emplace_back(DefaultOpenVINOExecutionProvider()); + test.ConfigEps(std::move(execution_providers)) + .RunWithConfig(); } +#endif // USE_OPENVINO // Test uint4 QuantizeLinear (per tensor) TEST(QuantizeLinearOpTest, UInt4) { @@ -569,7 +634,12 @@ TEST(QuantizeLinearOpTest, OddLarge_Int4) { test.AddInput("zero_point", {}, {Int4x2(zp, unused_val)}, true); test.AddOutput("y", dims, output); - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); + std::unordered_set excluded_providers; + excluded_providers.insert(kTensorrtExecutionProvider); + // Disable OV EP due to different formulation for QuantizeLinear + excluded_providers.insert(kOpenVINOExecutionProvider); + test.ConfigExcludeEps(excluded_providers) + .RunWithConfig(); } // Test uint4 QuantizeLinear (per tensor) with a "large" and odd number of input elements. @@ -595,7 +665,12 @@ TEST(QuantizeLinearOpTest, OddLarge_UInt4) { test.AddInput("zero_point", {}, {UInt4x2(zp, unused_val)}, true); test.AddOutput("y", dims, output); - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); + std::unordered_set excluded_providers; + excluded_providers.insert(kTensorrtExecutionProvider); + // Disable OV EP due to different formulation for QuantizeLinear + excluded_providers.insert(kOpenVINOExecutionProvider); + test.ConfigExcludeEps(excluded_providers) + .RunWithConfig(); } // quantize with scalar zero point and scale @@ -611,10 +686,31 @@ TEST(QuantizeLinearOpTest, Int8_NegativeZeroPoint) { test.AddInput("y_scale", {}, {.039215686f}); test.AddInput("y_zero_point", {}, {-23}); test.AddOutput("y", dims, {-23, 28, 53, 104, 127, -74, -128, -128}); + std::unordered_set excluded_providers; // Disable Tensorrt EP due to the error, node1_quantize_scale_node: out of bounds channel axis 1. Number of input dimensions is 1. - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); + excluded_providers.insert(kTensorrtExecutionProvider); + // Disable OV EP due to different formulation for QuantizeLinear + excluded_providers.insert(kOpenVINOExecutionProvider); + test.ConfigExcludeEps(excluded_providers) + .RunWithConfig(); } +#ifdef USE_OPENVINO +TEST(QuantizeLinearOpTest, OVEP_Int8_NegativeZeroPoint) { + + OpTester test("QuantizeLinear", 10); + std::vector dims{8}; + test.AddInput("x", dims, {0, 2, 3, 5, 6, -2, -5, -6}); + test.AddInput("y_scale", {}, {.039215686f}); + test.AddInput("y_zero_point", {}, {-23}); + test.AddOutput("y", dims, {-23, 28, 54, 105, 127, -74, -128, -128}); + std::vector> execution_providers; + execution_providers.emplace_back(DefaultOpenVINOExecutionProvider()); + test.ConfigEps(std::move(execution_providers)) + .RunWithConfig(); +} +#endif // USE_OPENVINO + // quantize with scalar zero point and scale TEST(QuantizeLinearOpTest, Int8_PositiveZeroPoint) { // TODO: Unskip when fixed #41968513 @@ -628,9 +724,34 @@ TEST(QuantizeLinearOpTest, Int8_PositiveZeroPoint) { test.AddInput("y_scale", {}, {.039215686f}); test.AddInput("y_zero_point", {}, {23}); test.AddOutput("y", dims, {23, 74, 99, 127, 127, -28, -104, -128}); + std::unordered_set excluded_providers; // Disable Tensorrt EP due to error:node1_quantize_scale_node: out of bounds channel axis 1. Number of input dimensions is 1. - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); + excluded_providers.insert(kTensorrtExecutionProvider); + // Disable OV EP due to different formulation for QuantizeLinear + excluded_providers.insert(kOpenVINOExecutionProvider); + test.ConfigExcludeEps(excluded_providers) + .RunWithConfig(); +} + +#ifdef USE_OPENVINO +TEST(QuantizeLinearOpTest, OVEP_Int8_PositiveZeroPoint) { + // TODO: Unskip when fixed #41968513 + if (DefaultDmlExecutionProvider().get() != nullptr) { + GTEST_SKIP() << "Skipping because of the following error: Expected equality of these values: -104 and -105"; + } + + OpTester test("QuantizeLinear", 10); + std::vector dims{8}; + test.AddInput("x", dims, {0, 2, 3, 5, 6, -2, -5, -6}); + test.AddInput("y_scale", {}, {.039215686f}); + test.AddInput("y_zero_point", {}, {23}); + test.AddOutput("y", dims, {23, 74, 100, 127, 127, -28, -104, -128}); + std::vector> execution_providers; + execution_providers.emplace_back(DefaultOpenVINOExecutionProvider()); + test.ConfigEps(std::move(execution_providers)) + .RunWithConfig(); } +#endif // USE_OPENVINO // quantize with 2D data TEST(QuantizeLinearOpTest, 2D) { diff --git a/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc b/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc index be3516437b1aa..b3f0895ee0b3c 100644 --- a/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc +++ b/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc @@ -304,10 +304,43 @@ TEST(ResizeOpTest, NhwcResizeOpLinearDownSampleTest_4DBilinear_uint8) { std::vector Y = {2, 4}; test.AddOutput("Y", {N, static_cast(H * scales[1]), static_cast(W * scales[2]), C}, Y); + std::unordered_set excluded_providers; // CUDA: result mismatch due to not implementing NHWC support - test.Run(OpTester::ExpectResult::kExpectSuccess, "", - {kCudaExecutionProvider, kCudaNHWCExecutionProvider}); + // ROCm: results mismatch + excluded_providers.insert(kCudaExecutionProvider); + excluded_providers.insert(kCudaNHWCExecutionProvider); + // Disable OV EP due to round when converting from float to uint8 + excluded_providers.insert(kOpenVINOExecutionProvider); + test.ConfigExcludeEps(excluded_providers) + .RunWithConfig(); +} + +#ifdef USE_OPENVINO +TEST(ResizeOpTest, OVEPNhwcResizeOpLinearDownSampleTest_4DBilinear_uint8) { + OpTester test("Resize", 13); + std::vector roi{}; + std::vector scales{1.0f, 0.6f, 0.6f, 1.0f}; + + test.AddAttribute("mode", "linear"); + + constexpr int64_t N = 1, H = 2, W = 4, C = 1; + std::vector X = { + 1, 2, 3, 4, + 5, 6, 7, 8}; + + test.AddInput("X", {N, H, W, C}, X); + test.AddInput("roi", {0}, roi); + test.AddInput("scales", {4}, scales); + + std::vector Y = {3, 4}; + + test.AddOutput("Y", {N, static_cast(H * scales[1]), static_cast(W * scales[2]), C}, Y); + std::vector> execution_providers; + execution_providers.emplace_back(DefaultOpenVINOExecutionProvider()); + test.ConfigEps(std::move(execution_providers)) + .RunWithConfig(); } +#endif // USE_OPENVINO TEST(ResizeOpTest, NhwcResizeOpLinearDownSampleTest_4DBilinear_int8) { OpTester test("Resize", 13); @@ -641,11 +674,50 @@ TEST(ResizeOpTest, NhwcResizeOpLinearDownSampleTest_4DBilinear_pytorch_half_pixe std::vector Y = {1, 7, 12}; test.AddOutput("Y", {N, sizes[1], sizes[2], C}, Y); + std::unordered_set excluded_providers; // CUDA: result mismatch due to not implementing NHWC support // DML: results mismatch - test.Run(OpTester::ExpectResult::kExpectSuccess, "", - {kCudaExecutionProvider, kCudaNHWCExecutionProvider, kDmlExecutionProvider}); + excluded_providers.insert(kCudaExecutionProvider); + excluded_providers.insert(kCudaNHWCExecutionProvider); + excluded_providers.insert(kDmlExecutionProvider); + // Disable OV EP due to round when converting from float to uint8 + excluded_providers.insert(kOpenVINOExecutionProvider); + test.ConfigExcludeEps(excluded_providers) + .RunWithConfig(); +} + +#ifdef USE_OPENVINO +TEST(ResizeOpTest, OVEPNhwcResizeOpLinearDownSampleTest_4DBilinear_pytorch_half_pixel_uint8) { + OpTester test("Resize", 13); + std::vector roi{}; + std::vector scales{}; + std::vector sizes{1, 3, 1, 1}; + + test.AddAttribute("mode", "linear"); + test.AddAttribute("coordinate_transformation_mode", "pytorch_half_pixel"); + + constexpr int64_t N = 1, H = 4, W = 4, C = 1; + + std::vector X = { + 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16}; + + test.AddInput("X", {N, H, W, C}, X); + test.AddInput("roi", {0}, roi); + test.AddInput("", {0}, scales); + test.AddInput("sizes", {4}, sizes); + + std::vector Y = {2, 7, 12}; + + test.AddOutput("Y", {N, sizes[1], sizes[2], C}, Y); + std::vector> execution_providers; + execution_providers.emplace_back(DefaultOpenVINOExecutionProvider()); + test.ConfigEps(std::move(execution_providers)) + .RunWithConfig(); } +#endif // USE_OPENVINO TEST(ResizeOpTest, NhwcResizeOpLinearDownSampleTest_4DBilinear_pytorch_half_pixel_int8) { OpTester test("Resize", 13); diff --git a/onnxruntime/test/providers/cpu/tensor/slice_op.test.cc b/onnxruntime/test/providers/cpu/tensor/slice_op.test.cc index 5b2865a3feed7..38bc326943c6f 100644 --- a/onnxruntime/test/providers/cpu/tensor/slice_op.test.cc +++ b/onnxruntime/test/providers/cpu/tensor/slice_op.test.cc @@ -54,6 +54,7 @@ void RunSliceTest(const std::vector& input_dims, if (onnx_shape_disagreement) { excluded_providers.insert(kCoreMLExecutionProvider); + excluded_providers.insert(kOpenVINOExecutionProvider); } if (!v10_only) { From 8952ea391e47b75a10690c1c33984e05d01a21bd Mon Sep 17 00:00:00 2001 From: LiangGao Date: Thu, 11 Dec 2025 11:17:31 +0800 Subject: [PATCH 02/12] Update the unit test based on OV test results --- .../openvino/ov_versions/data_ops.cc | 62 ++++++++++++------- .../cpu/nn/conv_transpose_op_test.cc | 2 +- .../providers/cpu/tensor/resize_op_test.cc | 52 +++++++++++++++- 3 files changed, 91 insertions(+), 25 deletions(-) diff --git a/onnxruntime/core/providers/openvino/ov_versions/data_ops.cc b/onnxruntime/core/providers/openvino/ov_versions/data_ops.cc index 373b2121a9b60..d506354968254 100644 --- a/onnxruntime/core/providers/openvino/ov_versions/data_ops.cc +++ b/onnxruntime/core/providers/openvino/ov_versions/data_ops.cc @@ -35,41 +35,21 @@ namespace openvino_ep { // Ops which are supported only in models(as intermediate nodes) and not in unit tests std::set ops_supported_only_in_model = { - "Add", - "Cast", "Celu", - "Concat", - "ConstantOfShape", - "DequantizeLinear", "Dropout", "Einsum", - "Exp", - "Expand", - "EyeLike", "GatherElements", "GatherND", "GridSample", - "Identity", "LayerNormalization", - "Loop", "LSTM", - "NonMaxSuppression", - "NonZero", - "Not", "OneHot", "Pad", - "QuantizeLinear", "RandomNormalLike", - "Range", "ReduceMin", - "Resize", - "Round", - "Shape", "Slice", - "Split", - "Tile", - "TopK", - "Trilu"}; + "TopK" + }; // Ops which are supported as functions (as composite ops) std::set ops_supported_as_function = { @@ -269,6 +249,8 @@ void DataOps::populate_types_supported() { std::make_pair(V_2020_4, ONNX_NAMESPACE::TensorProto_DataType::TensorProto_DataType_FLOAT)); supported_types_initializer_.insert( std::make_pair(V_2020_4, ONNX_NAMESPACE::TensorProto_DataType::TensorProto_DataType_INT32)); + supported_types_initializer_.insert( + std::make_pair(V_2020_4, ONNX_NAMESPACE::TensorProto_DataType::TensorProto_DataType_UINT32)); supported_types_initializer_.insert( std::make_pair(V_2020_4, ONNX_NAMESPACE::TensorProto_DataType::TensorProto_DataType_INT64)); supported_types_initializer_.insert( @@ -317,6 +299,8 @@ void DataOps::populate_types_supported() { std::make_pair(V_2020_4, ONNX_NAMESPACE::TensorProto_DataType::TensorProto_DataType_BOOL)); supported_types_cpu_.insert( std::make_pair(V_2020_4, ONNX_NAMESPACE::TensorProto_DataType::TensorProto_DataType_FLOAT)); + supported_types_cpu_.insert( + std::make_pair(V_2020_4, ONNX_NAMESPACE::TensorProto_DataType::TensorProto_DataType_UINT32)); supported_types_cpu_.insert( std::make_pair(V_2020_4, ONNX_NAMESPACE::TensorProto_DataType::TensorProto_DataType_INT32)); supported_types_cpu_.insert( @@ -367,6 +351,7 @@ void DataOps::populate_op_mode_supported() { no_dimension_supported_.push_back({"DynamicQuantizeLinear", V_2025_2, {"All"}}); no_dimension_supported_.push_back({"Equal", V_2022_1, {"CPU"}}); no_dimension_supported_.push_back({"Equal", V_2023_0, {"GPU"}}); + no_dimension_supported_.push_back({"Exp", V_2020_4, {"CPU", "GPU"}}); no_dimension_supported_.push_back({"Expand", V_2023_3, {"CPU"}}); no_dimension_supported_.push_back({"Expand", V_2024_3, {"CPU", "GPU"}}); no_dimension_supported_.push_back({"Floor", V_2020_4, {"All"}}); @@ -382,6 +367,7 @@ void DataOps::populate_op_mode_supported() { no_dimension_supported_.push_back({"Mul", V_2020_4, {"All"}}); no_dimension_supported_.push_back({"Neg", V_2023_0, {"CPU", "GPU"}}); no_dimension_supported_.push_back({"Pow", V_2023_0, {"CPU", "GPU"}}); + no_dimension_supported_.push_back({"PRelu", V_2020_4, {"CPU", "GPU"}}); no_dimension_supported_.push_back({"QuantizeLinear", V_2021_4, {"All"}}); no_dimension_supported_.push_back({"Range", V_2021_2, {"All"}}); no_dimension_supported_.push_back({"ReduceMax", V_2021_4, {"All"}}); @@ -489,6 +475,38 @@ void DataOps::populate_op_mode_supported() { }}; op_list_.insert({"Upsample", obj}); } + { + UnsupportedOpMode obj = {{V_2023_1, V_2023_2, V_2023_3, V_2024_0, V_2024_1, V_2024_2, + V_2024_3, V_2024_4, V_2024_5, V_2024_6, V_2025_0, V_2025_1, V_2025_2, V_2025_3, V_2025_4}, + [this](const Node* node, const InitializedTensorSet&) { + auto& attributes = node->GetAttributes(); + if (attributes.count("coordinate_transformation_mode") > 0) { + auto coordinate_transformation_mode = + attributes.at("coordinate_transformation_mode").s(); + if (coordinate_transformation_mode == "tf_crop_and_resize" || + coordinate_transformation_mode == "half_pixel_symmetric") { + return true; + } + } + if (attributes.count("antialias") > 0) { + auto antialias_mode = + attributes.at("antialias").i(); + auto resize_mode = attributes.at("mode").s(); + if (antialias_mode == 1 && + (resize_mode == "linear" || + resize_mode == "cubic")) { + return true; + } + } + if (attributes.count("exclude_outside") > 0) { + if (attributes.at("exclude_outside").i() == 1) { + return true; + } + } + return false; + }}; + op_list_.insert({"Resize", obj}); + } } bool DataOps::op_is_supported(std::string name, std::vector& op_list) { diff --git a/onnxruntime/test/providers/cpu/nn/conv_transpose_op_test.cc b/onnxruntime/test/providers/cpu/nn/conv_transpose_op_test.cc index 198fa07ae4ed0..4d153b67447fd 100644 --- a/onnxruntime/test/providers/cpu/nn/conv_transpose_op_test.cc +++ b/onnxruntime/test/providers/cpu/nn/conv_transpose_op_test.cc @@ -526,7 +526,7 @@ TEST(ConvTransposeTest, ConvTranspose_InvalidKernelShape) { // so drop the part that differs from the expected string "kernel_shape num_dims is not compatible with W num_dims. kernel_shape: {1,1,1,5} W: {1,1,", {kTensorrtExecutionProvider, kQnnExecutionProvider, - kDmlExecutionProvider}); // TODO: Unskip when fixed #41968513 + kDmlExecutionProvider, kOpenVINOExecutionProvider}); // TODO: Unskip when fixed #41968513 } TEST(ConvTransposeTest, ConvTranspose_onnx) { diff --git a/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc b/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc index b3f0895ee0b3c..0382cf2bc7879 100644 --- a/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc +++ b/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc @@ -827,13 +827,61 @@ TEST(ResizeOpTest, NhwcResizeOpLinearUpSampleTest_4DBilinear_asymmetric_uint8) { Y, false, .0f, 1.0f); // CUDA: result mismatch due to not implementing NHWC support test.Run(OpTester::ExpectResult::kExpectSuccess, "", - {kCudaExecutionProvider, kCudaNHWCExecutionProvider}); + {kCudaExecutionProvider, kCudaNHWCExecutionProvider, kOpenVINOExecutionProvider}); }; run_test(false); run_test(true); } +#ifdef USE_OPENVINO +TEST(ResizeOpTest, OVEPNhwcResizeOpLinearUpSampleTest_4DBilinear_asymmetric_uint8) { + // To test NNAPI EP, we need the scales/sizes to be in initializers + auto run_test = [](bool scales_in_initializer) { + OpTester test("Resize", 13); + std::vector roi{}; + std::vector scales{1.0f, 2.0f, 4.0f, 1.0f}; + + test.AddAttribute("mode", "linear"); + test.AddAttribute("coordinate_transformation_mode", "asymmetric"); + + constexpr int64_t N = 2, H = 2, W = 2, C = 1; + std::vector X = {1, 3, + 4, 8, + + 6, 2, + 7, 11}; + + test.AddInput("X", {N, H, W, C}, X); + test.AddInput("roi", {0}, roi); + test.AddInput("scales", {4}, scales, scales_in_initializer); + + std::vector Y = { + 1, 2, 2, 2, 3, 3, 3, 3, + 2, 3, 4, 5, 6, 6, 6, 6, + 4, 5, 6, 7, 8, 8, 8, 8, + 4, 5, 6, 7, 8, 8, 8, 8, + + 6, 5, 4, 3, 2, 2, 2, 2, + 6, 6, 6, 6, 6, 6, 6, 6, + 7, 8, 9, 10, 11, 11, 11, 11, + 7, 8, 9, 10, 11, 11, 11, 11}; + + // Due to Xnnpack EP has a different rounding behavior, we need to allow a tolerance of 1 + // The tolerance only works for Xnnpack EP + test.AddOutput("Y", {N, static_cast(H * scales[1]), static_cast(W * scales[2]), C}, + Y, false, .0f, 1.0f); + std::vector> execution_providers; + execution_providers.emplace_back(DefaultOpenVINOExecutionProvider()); + test.ConfigEps(std::move(execution_providers)) + .RunWithConfig(); + }; + + run_test(false); + run_test(true); +} +#endif // USE_OPENVINO + TEST(ResizeOpTest, NhwcResizeOpLinearUpSampleTest_4DBilinear_asymmetric_int8) { // To test NNAPI EP, we need the scales/sizes to be in initializers auto run_test = [](bool scales_in_initializer) { @@ -2549,7 +2597,7 @@ TEST(ResizeOpTest, NoAntialias_AlignCorners_Cubic_Floor_NHWC) { 23.0000f, 24.0000f, }; // clang-format on - InlinedVector excluded_eps = {kCudaExecutionProvider}; + InlinedVector excluded_eps = {kCudaExecutionProvider, kOpenVINOExecutionProvider}; TestAntialiasing( {{"antialias", "0"}, {"coordinate_transformation_mode", "align_corners"}, From 790e552eeb0bc16dda9ab2a9630a251bb2bf461c Mon Sep 17 00:00:00 2001 From: LiangGao Date: Thu, 11 Dec 2025 11:58:14 +0800 Subject: [PATCH 03/12] Disable loop cases --- onnxruntime/test/providers/cpu/controlflow/loop_test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/onnxruntime/test/providers/cpu/controlflow/loop_test.cc b/onnxruntime/test/providers/cpu/controlflow/loop_test.cc index 10affa538dfad..312c6872b13fa 100644 --- a/onnxruntime/test/providers/cpu/controlflow/loop_test.cc +++ b/onnxruntime/test/providers/cpu/controlflow/loop_test.cc @@ -1037,7 +1037,7 @@ TEST(Loop, IterationCountAsOutput) { test.AddOutput("loop_var_0_final", {3, 1}, {0, 1, 2}); // Disable TensorRT on unsupported data type BOOL - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); + test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider, kOpenVINOExecutionProvider}); } #if defined(USE_CUDA) From 4cebc5d8a9cc7de7a1579f2934b17a2060b08b9e Mon Sep 17 00:00:00 2001 From: LiangGao Date: Thu, 11 Dec 2025 13:52:07 +0800 Subject: [PATCH 04/12] The OV doesn't include the fix, need to disable again --- onnxruntime/core/providers/openvino/ov_versions/data_ops.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/onnxruntime/core/providers/openvino/ov_versions/data_ops.cc b/onnxruntime/core/providers/openvino/ov_versions/data_ops.cc index d506354968254..e46d258abaeff 100644 --- a/onnxruntime/core/providers/openvino/ov_versions/data_ops.cc +++ b/onnxruntime/core/providers/openvino/ov_versions/data_ops.cc @@ -35,7 +35,9 @@ namespace openvino_ep { // Ops which are supported only in models(as intermediate nodes) and not in unit tests std::set ops_supported_only_in_model = { + "Cast", "Celu", + "ConstantOfShape", "Dropout", "Einsum", "GatherElements", From bf10bd2f8ac5e5b4d94e9c46115f9a64a3f03b24 Mon Sep 17 00:00:00 2001 From: LiangGao Date: Tue, 16 Dec 2025 11:40:20 +0800 Subject: [PATCH 05/12] Fix update comments based on review inputs --- .../test/providers/cpu/tensor/quantize_linear_test.cc | 8 -------- onnxruntime/test/providers/cpu/tensor/resize_op_test.cc | 2 ++ 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc b/onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc index c8808cbcc76ce..ef9b25c882218 100644 --- a/onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc +++ b/onnxruntime/test/providers/cpu/tensor/quantize_linear_test.cc @@ -713,10 +713,6 @@ TEST(QuantizeLinearOpTest, OVEP_Int8_NegativeZeroPoint) { // quantize with scalar zero point and scale TEST(QuantizeLinearOpTest, Int8_PositiveZeroPoint) { - // TODO: Unskip when fixed #41968513 - if (DefaultDmlExecutionProvider().get() != nullptr) { - GTEST_SKIP() << "Skipping because of the following error: Expected equality of these values: -104 and -105"; - } OpTester test("QuantizeLinear", 10); std::vector dims{8}; @@ -735,10 +731,6 @@ TEST(QuantizeLinearOpTest, Int8_PositiveZeroPoint) { #ifdef USE_OPENVINO TEST(QuantizeLinearOpTest, OVEP_Int8_PositiveZeroPoint) { - // TODO: Unskip when fixed #41968513 - if (DefaultDmlExecutionProvider().get() != nullptr) { - GTEST_SKIP() << "Skipping because of the following error: Expected equality of these values: -104 and -105"; - } OpTester test("QuantizeLinear", 10); std::vector dims{8}; diff --git a/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc b/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc index 0382cf2bc7879..55cc209d49670 100644 --- a/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc +++ b/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc @@ -826,6 +826,7 @@ TEST(ResizeOpTest, NhwcResizeOpLinearUpSampleTest_4DBilinear_asymmetric_uint8) { test.AddOutput("Y", {N, static_cast(H * scales[1]), static_cast(W * scales[2]), C}, Y, false, .0f, 1.0f); // CUDA: result mismatch due to not implementing NHWC support + // Disable OV EP due to round when converting from float to uint8 test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kCudaExecutionProvider, kCudaNHWCExecutionProvider, kOpenVINOExecutionProvider}); }; @@ -2597,6 +2598,7 @@ TEST(ResizeOpTest, NoAntialias_AlignCorners_Cubic_Floor_NHWC) { 23.0000f, 24.0000f, }; // clang-format on + // OVEP: results mismatch due to OV's optimiztion for NHWC layout InlinedVector excluded_eps = {kCudaExecutionProvider, kOpenVINOExecutionProvider}; TestAntialiasing( {{"antialias", "0"}, From 8b81a2445b606cf52f9b08225d0708191ba29c1b Mon Sep 17 00:00:00 2001 From: LiangGao Date: Mon, 15 Dec 2025 13:55:47 +0800 Subject: [PATCH 06/12] Enable cast --- onnxruntime/core/providers/openvino/ov_versions/data_ops.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/onnxruntime/core/providers/openvino/ov_versions/data_ops.cc b/onnxruntime/core/providers/openvino/ov_versions/data_ops.cc index e46d258abaeff..cffbe1f127b70 100644 --- a/onnxruntime/core/providers/openvino/ov_versions/data_ops.cc +++ b/onnxruntime/core/providers/openvino/ov_versions/data_ops.cc @@ -35,7 +35,6 @@ namespace openvino_ep { // Ops which are supported only in models(as intermediate nodes) and not in unit tests std::set ops_supported_only_in_model = { - "Cast", "Celu", "ConstantOfShape", "Dropout", From 850f17be4807ad9127d73097cbd73119f8c343c2 Mon Sep 17 00:00:00 2001 From: LiangGao Date: Tue, 16 Dec 2025 11:53:42 +0800 Subject: [PATCH 07/12] Update comments --- onnxruntime/test/providers/cpu/controlflow/loop_test.cc | 1 + onnxruntime/test/providers/cpu/nn/conv_transpose_op_test.cc | 2 +- onnxruntime/test/providers/cpu/tensor/resize_op_test.cc | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/onnxruntime/test/providers/cpu/controlflow/loop_test.cc b/onnxruntime/test/providers/cpu/controlflow/loop_test.cc index 312c6872b13fa..f968fc6fc2f2e 100644 --- a/onnxruntime/test/providers/cpu/controlflow/loop_test.cc +++ b/onnxruntime/test/providers/cpu/controlflow/loop_test.cc @@ -1037,6 +1037,7 @@ TEST(Loop, IterationCountAsOutput) { test.AddOutput("loop_var_0_final", {3, 1}, {0, 1, 2}); // Disable TensorRT on unsupported data type BOOL + // Disable OV EP due to ONNX partition create new domain and OV FE can't handle it test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider, kOpenVINOExecutionProvider}); } diff --git a/onnxruntime/test/providers/cpu/nn/conv_transpose_op_test.cc b/onnxruntime/test/providers/cpu/nn/conv_transpose_op_test.cc index 4d153b67447fd..198fa07ae4ed0 100644 --- a/onnxruntime/test/providers/cpu/nn/conv_transpose_op_test.cc +++ b/onnxruntime/test/providers/cpu/nn/conv_transpose_op_test.cc @@ -526,7 +526,7 @@ TEST(ConvTransposeTest, ConvTranspose_InvalidKernelShape) { // so drop the part that differs from the expected string "kernel_shape num_dims is not compatible with W num_dims. kernel_shape: {1,1,1,5} W: {1,1,", {kTensorrtExecutionProvider, kQnnExecutionProvider, - kDmlExecutionProvider, kOpenVINOExecutionProvider}); // TODO: Unskip when fixed #41968513 + kDmlExecutionProvider}); // TODO: Unskip when fixed #41968513 } TEST(ConvTransposeTest, ConvTranspose_onnx) { diff --git a/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc b/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc index 55cc209d49670..761c227639c8f 100644 --- a/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc +++ b/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc @@ -2598,7 +2598,7 @@ TEST(ResizeOpTest, NoAntialias_AlignCorners_Cubic_Floor_NHWC) { 23.0000f, 24.0000f, }; // clang-format on - // OVEP: results mismatch due to OV's optimiztion for NHWC layout + // OVEP: results mismatch due to OVEP's optimiztions have conflict InlinedVector excluded_eps = {kCudaExecutionProvider, kOpenVINOExecutionProvider}; TestAntialiasing( {{"antialias", "0"}, From 71e12472cb72c047413e9c4879d5d3164b9a8f9b Mon Sep 17 00:00:00 2001 From: MayureshV1 <47039074+MayureshV1@users.noreply.github.com> Date: Mon, 15 Dec 2025 22:53:37 -0800 Subject: [PATCH 08/12] Update onnxruntime/test/providers/cpu/tensor/resize_op_test.cc Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- onnxruntime/test/providers/cpu/tensor/resize_op_test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc b/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc index 761c227639c8f..826772e2be384 100644 --- a/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc +++ b/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc @@ -2598,7 +2598,7 @@ TEST(ResizeOpTest, NoAntialias_AlignCorners_Cubic_Floor_NHWC) { 23.0000f, 24.0000f, }; // clang-format on - // OVEP: results mismatch due to OVEP's optimiztions have conflict + // OVEP: results mismatch due to OVEP's optimizations have conflict InlinedVector excluded_eps = {kCudaExecutionProvider, kOpenVINOExecutionProvider}; TestAntialiasing( {{"antialias", "0"}, From 7514048bd45cb37cdfc2d919a682c7dbd4259f93 Mon Sep 17 00:00:00 2001 From: LiangGao Date: Tue, 16 Dec 2025 14:54:20 +0800 Subject: [PATCH 09/12] Revert "Enable cast" This reverts commit 8b81a2445b606cf52f9b08225d0708191ba29c1b. --- onnxruntime/core/providers/openvino/ov_versions/data_ops.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/onnxruntime/core/providers/openvino/ov_versions/data_ops.cc b/onnxruntime/core/providers/openvino/ov_versions/data_ops.cc index cffbe1f127b70..e46d258abaeff 100644 --- a/onnxruntime/core/providers/openvino/ov_versions/data_ops.cc +++ b/onnxruntime/core/providers/openvino/ov_versions/data_ops.cc @@ -35,6 +35,7 @@ namespace openvino_ep { // Ops which are supported only in models(as intermediate nodes) and not in unit tests std::set ops_supported_only_in_model = { + "Cast", "Celu", "ConstantOfShape", "Dropout", From ac1e9f3d938e34dbc8bb399febe2f61b726e5b24 Mon Sep 17 00:00:00 2001 From: LiangGao Date: Tue, 16 Dec 2025 21:43:58 +0800 Subject: [PATCH 10/12] Fix review inputs --- onnxruntime/core/providers/openvino/ov_versions/data_ops.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/onnxruntime/core/providers/openvino/ov_versions/data_ops.cc b/onnxruntime/core/providers/openvino/ov_versions/data_ops.cc index e46d258abaeff..08c526f460038 100644 --- a/onnxruntime/core/providers/openvino/ov_versions/data_ops.cc +++ b/onnxruntime/core/providers/openvino/ov_versions/data_ops.cc @@ -50,8 +50,7 @@ std::set ops_supported_only_in_model = { "RandomNormalLike", "ReduceMin", "Slice", - "TopK" - }; + "TopK"}; // Ops which are supported as functions (as composite ops) std::set ops_supported_as_function = { From 81ba841b1aaa0dd223088e7ab3f4fe97c4a9bf89 Mon Sep 17 00:00:00 2001 From: LiangGao Date: Tue, 16 Dec 2025 21:45:38 +0800 Subject: [PATCH 11/12] Try to handle input has optimized and dynamic shape --- .../core/providers/openvino/backends/basic_backend.h | 7 +++++++ .../core/providers/openvino/ov_versions/capability.cc | 10 +++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/onnxruntime/core/providers/openvino/backends/basic_backend.h b/onnxruntime/core/providers/openvino/backends/basic_backend.h index 7639e024c52cb..6993e389df276 100644 --- a/onnxruntime/core/providers/openvino/backends/basic_backend.h +++ b/onnxruntime/core/providers/openvino/backends/basic_backend.h @@ -65,6 +65,8 @@ struct OnnxToOvNetworkBindings { [&onnx_name](const auto& ov_parameter_info) { return ov_parameter_info.get_names().contains(onnx_name); }); bool matched_names = it != ov_parameters.end(); + if (it == ov_parameters.end()) continue; + // For Stateful Model Compilation, the ONNX model includes KV cache (past/present) tensors. // However, these tensors are internally converted to a stateful representation, which removes them. // It's also possible that the onnx model does not contain tensors such as beam_idx, whereas our converted @@ -110,6 +112,11 @@ struct OnnxToOvNetworkBindings { info.SetFullyDynamic(has_fully_dynamic); info.SetBoundedDynamic(has_bounded_dynamic); + } else { + auto shape_size = ov::shape_size(shape.get_shape()); + if (0 == shape_size) { + has_dynamic_io_ = true; + } } input_output_map.push_back(std::move(info)); diff --git a/onnxruntime/core/providers/openvino/ov_versions/capability.cc b/onnxruntime/core/providers/openvino/ov_versions/capability.cc index 40036212ca125..bb171fb435256 100644 --- a/onnxruntime/core/providers/openvino/ov_versions/capability.cc +++ b/onnxruntime/core/providers/openvino/ov_versions/capability.cc @@ -102,8 +102,16 @@ std::vector> GetCapability::Execute() { if (unsupported_nodes.empty()) { std::vector inputs; std::vector outputs; + auto input_nodes = graph_viewer_.GetInputs(); + // Input is not a tensor, OV only handle a tensor input + for (auto& node : input_nodes) { + auto shape = node->Shape(); + if (!shape) { + return result; + } + } // Fill inputs with names - Iterable2String(inputs, graph_viewer_.GetInputs()); + Iterable2String(inputs, input_nodes); /* In scenarios, when there are no inputs or all inputs being initializers, ConstantFolding optimization in onnxruntime pre-computes the value.*/ From d0916b9b422c5c12e24e60aa07a9872d02c876e9 Mon Sep 17 00:00:00 2001 From: LiangGao Date: Thu, 18 Dec 2025 17:05:28 +0800 Subject: [PATCH 12/12] Add warnings --- .../core/providers/openvino/backends/basic_backend.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/onnxruntime/core/providers/openvino/backends/basic_backend.h b/onnxruntime/core/providers/openvino/backends/basic_backend.h index 6993e389df276..ff2d43155c307 100644 --- a/onnxruntime/core/providers/openvino/backends/basic_backend.h +++ b/onnxruntime/core/providers/openvino/backends/basic_backend.h @@ -65,7 +65,12 @@ struct OnnxToOvNetworkBindings { [&onnx_name](const auto& ov_parameter_info) { return ov_parameter_info.get_names().contains(onnx_name); }); bool matched_names = it != ov_parameters.end(); - if (it == ov_parameters.end()) continue; + if (it == ov_parameters.end()) { + LOGS_DEFAULT(WARNING) << log_tag << "The input '" << onnx_name + << "' is not used due to OpenVINO optimization. " + "This may cause issues if the input is required."; + continue; + } // For Stateful Model Compilation, the ONNX model includes KV cache (past/present) tensors. // However, these tensors are internally converted to a stateful representation, which removes them.