diff --git a/onnxruntime/core/providers/cpu/tensor/upsample.h b/onnxruntime/core/providers/cpu/tensor/upsample.h index 8ff04781f6ad0..c23347a17febc 100644 --- a/onnxruntime/core/providers/cpu/tensor/upsample.h +++ b/onnxruntime/core/providers/cpu/tensor/upsample.h @@ -125,10 +125,17 @@ void UpsampleBilinear(const int32_t batch_size, T X12 = Xdata[p.input_width_mul_y2[y] + p.in_x1[x]]; T X22 = Xdata[p.input_width_mul_y2[y] + p.in_x2[x]]; - Ydata[output_offset] = static_cast(p.dx2[x] * p.dy2[y] * X11 + - p.dx1[x] * p.dy2[y] * X21 + - p.dx2[x] * p.dy1[y] * X12 + - p.dx1[x] * p.dy1[y] * X22); + if constexpr (is_floating_point_v) { + Ydata[output_offset] = static_cast(p.dx2[x] * p.dy2[y] * X11 + + p.dx1[x] * p.dy2[y] * X21 + + p.dx2[x] * p.dy1[y] * X12 + + p.dx1[x] * p.dy1[y] * X22); + } else { + Ydata[output_offset] = static_cast(nearbyintf(p.dx2[x] * p.dy2[y] * X11 + + p.dx1[x] * p.dy2[y] * X21 + + p.dx2[x] * p.dy1[y] * X12 + + p.dx1[x] * p.dy1[y] * X22)); + } } } }); diff --git a/onnxruntime/test/optimizer/qdq_transformer_test.cc b/onnxruntime/test/optimizer/qdq_transformer_test.cc index d07977d4b97b8..fbcb1cf942f86 100644 --- a/onnxruntime/test/optimizer/qdq_transformer_test.cc +++ b/onnxruntime/test/optimizer/qdq_transformer_test.cc @@ -1924,6 +1924,52 @@ TEST(QDQTransformerTests, Resize) { test_case({2, 13, 12, 37}, rand_gen.Uniform(std::vector{4}, 1, 16), true /*use_contrib_qdq*/); } +// Regression test for a model with a Resize node using QDQ quantization. +// Tests handling of rounding issue inconsistency between int Resize and Resize with QDQ quantization. +// See https://github.com/microsoft/onnxruntime/issues/21319 for more details. +TEST(QDQTransformerTests, RegressionTest_GitHubIssue21319) { + Status status; + auto model_uri = ORT_TSTR("testdata/qdq_transformer/gh_issue_21319.onnx"); + + std::vector input0_dims{4}; + std::vector input1_dims{1, 1, 1, 2}; + std::vector input0_data = {1.0, 1.0, 1.0, 2.0}; + std::vector input1_data = {0.0, 1.0}; + + OrtValue input0; + OrtValue input1; + CreateMLValue(TestCPUExecutionProvider()->CreatePreferredAllocators()[0], input0_dims, input0_data, &input0); + CreateMLValue(TestCPUExecutionProvider()->CreatePreferredAllocators()[0], input1_dims, input1_data, &input1); + + NameMLValMap feeds{{"Concat_output_0", input0}, {"Abs_output_0", input1}}; + + std::vector output_names{"DequantizeLinear_2_output_0"}; + std::vector fetches_orig; + std::vector fetches; + + SessionOptions so; + so.session_logid = "QDQTransformerTests.RegressionTest_GitHubIssue21319"; + + { + so.graph_optimization_level = TransformerLevel::Level1; + InferenceSession session{so, GetEnvironment()}; + ASSERT_STATUS_OK(session.Load(model_uri)); + ASSERT_STATUS_OK(session.Initialize()); + ASSERT_STATUS_OK(session.Run(feeds, output_names, &fetches_orig)); + } + + { + so.graph_optimization_level = TransformerLevel::Level2; // enable qdq transformer + InferenceSession session{so, GetEnvironment()}; + ASSERT_STATUS_OK(session.Load(model_uri)); + ASSERT_STATUS_OK(session.Initialize()); + ASSERT_STATUS_OK(session.Run(feeds, output_names, &fetches)); + } + + ASSERT_THAT(fetches_orig[0].Get().DataAsSpan(), + testing::ContainerEq(fetches[0].Get().DataAsSpan())); +} + TEST(QDQTransformerTests, Resize_No_Fusion) { auto test_case = [&](const std::vector& input_shape, const std::vector& sizes_shape, diff --git a/onnxruntime/test/providers/cpu/tensor/upsample_op_test.cc b/onnxruntime/test/providers/cpu/tensor/upsample_op_test.cc index 3ac8053aef95e..a398b86fc243d 100644 --- a/onnxruntime/test/providers/cpu/tensor/upsample_op_test.cc +++ b/onnxruntime/test/providers/cpu/tensor/upsample_op_test.cc @@ -841,15 +841,15 @@ TEST(UpsampleOpTest, UpsampleOp4DBilinearTest_int32) { test.AddInput("X", {N, C, H, W}, X); std::vector Y = { - 1, 1, 2, 2, 3, 3, 3, 3, - 2, 2, 3, 3, 4, 4, 4, 4, - 3, 3, 4, 4, 5, 5, 5, 5, - 3, 3, 4, 4, 5, 5, 5, 5, - - 3, 3, 4, 4, 5, 5, 5, 5, - 5, 5, 6, 6, 7, 7, 7, 7, - 7, 7, 8, 8, 9, 9, 9, 9, - 7, 7, 8, 8, 9, 9, 9, 9}; + 1, 2 /* 1.5 */, 2, 2, 3, 3, 3, 3, + 2, 2, 3, 4 /* 3.5 */, 4, 4, 4, 4, + 3, 4 /* 3.5 */, 4, 4, 5, 5, 5, 5, + 3, 4 /* 3.5 */, 4, 4, 5, 5, 5, 5, + + 3, 4 /* 3.5 */, 4, 4, 5, 5, 5, 5, + 5, 6 /* 5.5 */, 6, 6, 7, 7, 7, 7, + 7, 8 /* 7.5 */, 8, 8, 9, 9, 9, 9, + 7, 8 /* 7.5 */, 8, 8, 9, 9, 9, 9}; test.AddOutput("Y", {N, C, (int64_t)(H * scales[2]), (int64_t)(W * scales[3])}, Y); test.Run(); diff --git a/onnxruntime/test/testdata/qdq_transformer/gh_issue_21319.onnx b/onnxruntime/test/testdata/qdq_transformer/gh_issue_21319.onnx new file mode 100644 index 0000000000000..f9052dc8d32c6 Binary files /dev/null and b/onnxruntime/test/testdata/qdq_transformer/gh_issue_21319.onnx differ