Skip to content

Commit

Permalink
Fix rounding issue in int Resize vs. Resize with QDQ quantization.
Browse files Browse the repository at this point in the history
Handle rounding issue inconsistency between int Resize and Resize with QDQ quantization.
It Fix github issue 21319 #21319.
  • Loading branch information
yihonglyu committed Oct 17, 2024
1 parent 84d48b6 commit e629357
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 13 deletions.
15 changes: 11 additions & 4 deletions onnxruntime/core/providers/cpu/tensor/upsample.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<T>(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<T>) {

Check failure on line 128 in onnxruntime/core/providers/cpu/tensor/upsample.h

View workflow job for this annotation

GitHub Actions / Vcpkg

use of undeclared identifier 'is_floating_point_v'
Ydata[output_offset] = static_cast<T>(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<T>(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));
}
}
}
});
Expand Down
46 changes: 46 additions & 0 deletions onnxruntime/test/optimizer/qdq_transformer_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1924,6 +1924,52 @@ TEST(QDQTransformerTests, Resize) {
test_case({2, 13, 12, 37}, rand_gen.Uniform<int64_t>(std::vector<int64_t>{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<int64_t> input0_dims{4};
std::vector<int64_t> input1_dims{1, 1, 1, 2};
std::vector<float> input0_data = {1.0, 1.0, 1.0, 2.0};
std::vector<float> input1_data = {0.0, 1.0};

OrtValue input0;
OrtValue input1;
CreateMLValue<float>(TestCPUExecutionProvider()->CreatePreferredAllocators()[0], input0_dims, input0_data, &input0);
CreateMLValue<float>(TestCPUExecutionProvider()->CreatePreferredAllocators()[0], input1_dims, input1_data, &input1);

NameMLValMap feeds{{"Concat_output_0", input0}, {"Abs_output_0", input1}};

std::vector<std::string> output_names{"DequantizeLinear_2_output_0"};
std::vector<OrtValue> fetches_orig;
std::vector<OrtValue> 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<Tensor>().DataAsSpan<float>(),
testing::ContainerEq(fetches[0].Get<Tensor>().DataAsSpan<float>()));
}

TEST(QDQTransformerTests, Resize_No_Fusion) {
auto test_case = [&](const std::vector<int64_t>& input_shape,
const std::vector<int64_t>& sizes_shape,
Expand Down
18 changes: 9 additions & 9 deletions onnxruntime/test/providers/cpu/tensor/upsample_op_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -841,15 +841,15 @@ TEST(UpsampleOpTest, UpsampleOp4DBilinearTest_int32) {
test.AddInput<int32_t>("X", {N, C, H, W}, X);

std::vector<int32_t> 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<int32_t>("Y", {N, C, (int64_t)(H * scales[2]), (int64_t)(W * scales[3])}, Y);
test.Run();
Expand Down
Binary file not shown.

0 comments on commit e629357

Please sign in to comment.