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(); }