From a8e3ff47fd61be92da391d3c16e6eed1ca41dfa5 Mon Sep 17 00:00:00 2001 From: Yufeng Li Date: Wed, 24 Jul 2019 22:29:52 -0700 Subject: [PATCH] Add no scale check for resize and upsample (#1484) Description: Describe your changes. Add no scale check for resize and upsample Motivation and Context Why is this change required? What problem does it solve? If it fixes an open issue, please link to the issue here. --- .../core/providers/cpu/tensor/upsample.cc | 27 ++-- .../providers/cpu/tensor/resize_op_test.cc | 123 ++++++++++++------ .../providers/cpu/tensor/upsample_op_test.cc | 60 ++++++--- 3 files changed, 140 insertions(+), 70 deletions(-) diff --git a/onnxruntime/core/providers/cpu/tensor/upsample.cc b/onnxruntime/core/providers/cpu/tensor/upsample.cc index c1b80f63ed..b65645ae06 100644 --- a/onnxruntime/core/providers/cpu/tensor/upsample.cc +++ b/onnxruntime/core/providers/cpu/tensor/upsample.cc @@ -256,15 +256,15 @@ void upsampleBilinear( auto output_width = static_cast(input_width * width_scale); auto output_height = static_cast(input_height * height_scale); - size_t inx_buffer_size = 2 * sizeof(int64_t) * (output_height + output_width); + size_t idx_buffer_size = 2 * sizeof(int64_t) * (output_height + output_width); size_t scale_buffer_size = 2 * sizeof(float_t) * (output_height + output_width); - auto inx_scale_data_buffer = alloc->Alloc(inx_buffer_size + scale_buffer_size); - BufferUniquePtr inx_scale_data_buffer_holder(inx_scale_data_buffer, BufferDeleter(alloc)); - auto* inx_data = static_cast(inx_scale_data_buffer_holder.get()); - int64_t* input_width_mul_y1 = inx_data; - int64_t* input_width_mul_y2 = inx_data + output_height; - int64_t* in_x1 = inx_data + 2 * output_height; - int64_t* in_x2 = inx_data + 2 * output_height + output_width; + auto inx_scale_data_buffer = alloc->Alloc(idx_buffer_size + scale_buffer_size); + BufferUniquePtr idx_scale_data_buffer_holder(inx_scale_data_buffer, BufferDeleter(alloc)); + auto* idx_data = static_cast(idx_scale_data_buffer_holder.get()); + int64_t* input_width_mul_y1 = idx_data; + int64_t* input_width_mul_y2 = idx_data + output_height; + int64_t* in_x1 = idx_data + 2 * output_height; + int64_t* in_x2 = idx_data + 2 * output_height + output_width; auto* scale_data = reinterpret_cast(in_x2 + output_width); float* dy1 = scale_data; @@ -331,12 +331,21 @@ Status Upsample::BaseCompute(OpKernelContext* context, const std::vector Y_dims; + Y_dims.reserve( dims.size() ); for (std::size_t i = 0; i < dims.size(); i++) { - Y_dims.push_back(static_cast(scales[i] * dims[i])); + int64_t dim_y = static_cast(scales[i] * dims[i]); + if (no_scale && dim_y != dims[i]) no_scale = false; + Y_dims.push_back(dim_y); } Tensor* Y = context->Output(0, Y_dims); + if (no_scale) { + memcpy(Y->MutableDataRaw(), X->DataRaw(), Y->Size() * sizeof(T)); + return Status::OK(); + } + switch (mode_) { case UpsampleMode::NN: return UpsampleNearest(X->template Data(), Y->template MutableData(), X->Shape(), Y->Shape(), scales); diff --git a/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc b/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc index d731275214..0611aa2501 100644 --- a/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc +++ b/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc @@ -27,7 +27,82 @@ TEST(ResizeOpTest, ResizeOpLineartDownSampleTest) { test.Run(); } -TEST(ResizeOpTest, ResizeOpUpsampleNearestTest) { +TEST(ResizeOpTest, ResizeOpLineartUpSampleTest) { + OpTester test("Resize", 10); + std::vector scales{1.0f, 1.0f, 2.0f, 4.0f}; + test.AddAttribute("mode", "linear"); + + const int64_t N = 2, C = 1, H = 2, W = 2; + std::vector X = {1.0f, 3.0f, + 4.0f, 8.0f, + + 6.0f, 2.0f, + 7.0f, 11.0f}; + + test.AddInput("X", {N, C, H, W}, X); + test.AddInput("scales", {4}, scales); + + std::vector Y = { + 1.0f, 1.5f, 2.0f, 2.5f, 3.0f, 3.0f, 3.0f, 3.0f, + 2.5f, 3.25f, 4.0f, 4.75f, 5.5f, 5.5f, 5.5f, 5.5f, + 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 8.0f, 8.0f, 8.0f, + 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 8.0f, 8.0f, 8.0f, + + 6.0f, 5.0f, 4.0f, 3.0f, 2.0f, 2.0f, 2.0f, 2.0f, + 6.5f, 6.5f, 6.5f, 6.5f, 6.5f, 6.5f, 6.5f, 6.5f, + 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 11.0f, 11.0f, 11.0f, + 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 11.0f, 11.0f, 11.0f}; + + test.AddOutput("Y", {N, C, (int64_t)(H * scales[2]), (int64_t)(W * scales[3])}, Y); + test.Run(); +} + +TEST(ResizeOpTest, ResizeOpLineartNoScaleTest) { + OpTester test("Resize", 10); + std::vector scales{1.0f, 1.0f, 1.0f, 1.0f}; + test.AddAttribute("mode", "linear"); + + const int64_t N = 2, C = 1, H = 2, W = 2; + std::vector X = {1.0f, 3.0f, + 4.0f, 8.0f, + + 6.0f, 2.0f, + 7.0f, 11.0f}; + + test.AddInput("X", {N, C, H, W}, X); + test.AddInput("scales", {4}, scales); + + std::vector Y = {1.0f, 3.0f, + 4.0f, 8.0f, + + 6.0f, 2.0f, + 7.0f, 11.0f}; + + test.AddOutput("Y", {N, C, H, W}, Y); + test.Run(); +} + +TEST(ResizeOpTest, ResizeOpNearestDownSampleTest) { + OpTester test("Resize", 10); + std::vector scales{1.0f, 1.0f, 0.6f, 0.6f}; + + test.AddAttribute("mode", "nearest"); + + const int64_t N = 1, C = 1, H = 2, W = 4; + std::vector X = { + 1.0f, 2.0f, 3.0f, 4.0f, + 5.0f, 6.0f, 7.0f, 8.0f}; + + test.AddInput("X", {N, C, H, W}, X); + test.AddInput("scales", {4}, scales); + + std::vector Y = {1.0f, 3.0f}; + + test.AddOutput("Y", {N, C, (int64_t)(H * scales[2]), (int64_t)(W * scales[3])}, Y); + test.Run(); +} + +TEST(ResizeOpTest, ResizeOpNearestUpSampleTest) { OpTester test("Resize", 10); std::vector scales{1.0f, 1.0f, 2.0f, 3.0f}; @@ -48,55 +123,21 @@ TEST(ResizeOpTest, ResizeOpUpsampleNearestTest) { test.Run(); } -TEST(ResizeOpTest, ResizeOpNearestTest) { +TEST(UpsampleOpTest, ResizeOpNearestNoScaleTest) { OpTester test("Resize", 10); - std::vector scales{1.0f, 1.0f, 0.6f, 0.6f}; + std::vector scales{1.0f, 1.0f, 1.0f, 1.0f}; test.AddAttribute("mode", "nearest"); - const int64_t N = 1, C = 1, H = 2, W = 4; - std::vector X = { - 1.0f, 2.0f, 3.0f, 4.0f, - 5.0f, 6.0f, 7.0f, 8.0f}; + const int64_t N = 1, C = 1, H = 2, W = 2; + std::vector X = {1.0f, 2.0f, 3.0f, 4.0f}; test.AddInput("X", {N, C, H, W}, X); test.AddInput("scales", {4}, scales); - std::vector Y = {1.0f, 3.0f}; + std::vector Y = {1.0f, 2.0f, 3.0f, 4.0f}; - test.AddOutput("Y", {N, C, (int64_t)(H * scales[2]), (int64_t)(W * scales[3])}, Y); - test.Run(); -} - -TEST(ResizeOpTest, ResizeOpBilinearTest) { - OpTester test("Resize", 10); - std::vector scales{1.0f, 1.0f, 0.5f, 0.5f}; - - test.AddAttribute("mode", "linear"); - - const int64_t N = 2, C = 1, H = 4, W = 8; - std::vector X = { - 1.0f, 1.5f, 2.0f, 2.5f, 3.0f, 3.0f, 3.0f, 3.0f, - 2.0f, 2.5f, 3.0f, 3.5f, 4.0f, 4.0f, 4.0f, 4.0f, - 3.0f, 3.5f, 4.0f, 4.5f, 5.0f, 5.0f, 5.0f, 5.0f, - 3.0f, 3.5f, 4.0f, 4.5f, 5.0f, 5.0f, 5.0f, 5.0f, - - 3.0f, 3.5f, 4.0f, 4.5f, 5.0f, 5.0f, 5.0f, 5.0f, - 5.0f, 5.5f, 6.0f, 6.5f, 7.0f, 7.0f, 7.0f, 7.0f, - 7.0f, 7.5f, 8.0f, 8.5f, 9.0f, 9.0f, 9.0f, 9.0f, - 7.0f, 7.5f, 8.0f, 8.5f, 9.0f, 9.0f, 9.0f, 9.0f}; - - test.AddInput("X", {N, C, H, W}, X); - test.AddInput("scales", {4}, scales); - - std::vector Y = { - 1.0f, 2.0f, 3.0f, 3.0f, - 3.0f, 4.0f, 5.0f, 5.0f, - - 3.0f, 4.0f, 5.0f, 5.0f, - 7.0f, 8.0f, 9.0f, 9.0f}; - - test.AddOutput("Y", {N, C, (int64_t)(H * scales[2]), (int64_t)(W * scales[3])}, Y); + test.AddOutput("Y", {N, C, H, W}, Y); test.Run(); } diff --git a/onnxruntime/test/providers/cpu/tensor/upsample_op_test.cc b/onnxruntime/test/providers/cpu/tensor/upsample_op_test.cc index 7df01e77a7..68924aa60b 100644 --- a/onnxruntime/test/providers/cpu/tensor/upsample_op_test.cc +++ b/onnxruntime/test/providers/cpu/tensor/upsample_op_test.cc @@ -70,7 +70,7 @@ TEST(UpsampleOpTest, UpsampleOpNearestTest_int32) { 7, 7, 7, 9, 9, 9}; test.AddOutput("Y", {N, C, (int64_t)(H * scales[2]), (int64_t)(W * scales[3])}, Y); - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); //TensorRT: nvinfer1::query::Ports&): Assertion `!formats.empty()' failed + test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); //TensorRT: nvinfer1::query::Ports&): Assertion `!formats.empty()' failed } TEST(UpsampleOpTest, UpsampleOpNearestTest_uint8) { @@ -170,10 +170,9 @@ TEST(UpsampleOpTest, UpsampleOpNearest222XTest) { 3.0f, 3.0f, 5.0f, 5.0f, 3.0f, 3.0f, 5.0f, 5.0f, 7.0f, 7.0f, 9.0f, 9.0f, - 7.0f, 7.0f, 9.0f, 9.0f - }; + 7.0f, 7.0f, 9.0f, 9.0f}; - test.AddOutput("Y", {N*2, C, (int64_t)(H * scales[2]), (int64_t)(W * scales[3])}, Y); + test.AddOutput("Y", {N * 2, C, (int64_t)(H * scales[2]), (int64_t)(W * scales[3])}, Y); test.Run(); } @@ -208,6 +207,32 @@ TEST(UpsampleOpTest, UpsampleOpNearest15XTest) { test.Run(); } +TEST(UpsampleOpTest, UpsampleOpNearestTest_NoScale) { + OpTester test("Upsample"); + + std::vector scales{1.0f, 1.0f, 1.0f, 1.0f}; + test.AddAttribute("mode", "nearest"); + test.AddAttribute("scales", scales); + + const int64_t N = 1, C = 2, H = 2, W = 2; + std::vector X = {1.0f, 3.0f, + 3.0f, 5.0f, + + 3.0f, 5.0f, + 7.0f, 9.0f}; + + test.AddInput("X", {N, C, H, W}, X); + + std::vector Y = {1.0f, 3.0f, + 3.0f, 5.0f, + + 3.0f, 5.0f, + 7.0f, 9.0f}; + + test.AddOutput("Y", {N, C, H, W}, Y); + test.Run(); +} + TEST(UpsampleOpTest, UpsampleOpNearest2XTest_int32) { OpTester test("Upsample"); @@ -236,7 +261,7 @@ TEST(UpsampleOpTest, UpsampleOpNearest2XTest_int32) { 7, 7, 9, 9}; test.AddOutput("Y", {N, C, (int64_t)(H * scales[2]), (int64_t)(W * scales[3])}, Y); - test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); //TensorRT: nvinfer1::query::Ports&): Assertion `!formats.empty()' failed + test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); //TensorRT: nvinfer1::query::Ports&): Assertion `!formats.empty()' failed } TEST(UpsampleOpTest, UpsampleOpBilinearTest) { @@ -270,34 +295,29 @@ TEST(UpsampleOpTest, UpsampleOpBilinearTest) { test.Run(); } -TEST(UpsampleOpTest, UpsampleOpBilinearTest2) { +TEST(UpsampleOpTest, UpsampleOpBilinearTest_NoScale) { OpTester test("Upsample"); - std::vector scales{1.0f, 1.0f, 2.0f, 4.0f}; + std::vector scales{1.0f, 1.0f, 1.0f, 1.0f}; test.AddAttribute("mode", "linear"); test.AddAttribute("scales", scales); const int64_t N = 2, C = 1, H = 2, W = 2; std::vector X = {1.0f, 3.0f, - 4.0f, 8.0f, + 3.0f, 5.0f, - 6.0f, 2.0f, - 7.0f, 11.0f}; + 3.0f, 5.0f, + 7.0f, 9.0f}; test.AddInput("X", {N, C, H, W}, X); - std::vector Y = { - 1.0f, 1.5f, 2.0f, 2.5f, 3.0f, 3.0f, 3.0f, 3.0f, - 2.5f, 3.25f, 4.0f, 4.75f, 5.5f, 5.5f, 5.5f, 5.5f, - 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 8.0f, 8.0f, 8.0f, - 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 8.0f, 8.0f, 8.0f, + std::vector Y = {1.0f, 3.0f, + 3.0f, 5.0f, - 6.0f, 5.0f, 4.0f, 3.0f, 2.0f, 2.0f, 2.0f, 2.0f, - 6.5f, 6.5f, 6.5f, 6.5f, 6.5f, 6.5f, 6.5f, 6.5f, - 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 11.0f, 11.0f, 11.0f, - 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 11.0f, 11.0f, 11.0f}; + 3.0f, 5.0f, + 7.0f, 9.0f}; - test.AddOutput("Y", {N, C, (int64_t)(H * scales[2]), (int64_t)(W * scales[3])}, Y); + test.AddOutput("Y", {N, C, H, W}, Y); test.Run(); }