From 6f5c28fd3aba0fe7003ae989f1e37715d177cea7 Mon Sep 17 00:00:00 2001 From: Hariharan Seshadri Date: Tue, 30 Apr 2019 17:46:48 -0700 Subject: [PATCH] Accomodate missing optional 'axes' when 'steps' is present in Slice op (#945) * Accomodate missing optional axes when steps is present in Slice implementation * PR feedback --- .../core/providers/cpu/tensor/slice.cc | 12 ++--- .../providers/cpu/tensor/slice_op.test.cc | 53 +++++++++++++------ 2 files changed, 41 insertions(+), 24 deletions(-) diff --git a/onnxruntime/core/providers/cpu/tensor/slice.cc b/onnxruntime/core/providers/cpu/tensor/slice.cc index a96c5402e6..c7a2b82c71 100644 --- a/onnxruntime/core/providers/cpu/tensor/slice.cc +++ b/onnxruntime/core/providers/cpu/tensor/slice.cc @@ -221,13 +221,11 @@ void SliceBase::FillVectorsFromInput(const OpKernelContext* context, std::vector& input_ends, std::vector& input_axes, std::vector& input_steps) const { - auto start_tensor = context->Input(1); - auto ends_tensor = context->Input(2); - const Tensor* axes_tensor = nullptr; - if (context->InputCount() >= 4) - axes_tensor = context->Input(3); - // Slice V10 (optional input) + const Tensor* start_tensor = context->Input(1); + const Tensor* ends_tensor = context->Input(2); + const Tensor* axes_tensor = context->Input(3); const Tensor* steps_tensor = nullptr; + // check if this is Slice V10 - only Slice V10 has this optional input if (context->InputCount() == 5) steps_tensor = context->Input(4); @@ -235,7 +233,7 @@ void SliceBase::FillVectorsFromInput(const OpKernelContext* context, ORT_ENFORCE(nullptr != ends_tensor && ends_tensor->Shape().NumDimensions() == 1, "Ends must be a 1-D array"); ORT_ENFORCE(start_tensor->Shape() == ends_tensor->Shape(), "Starts and ends shape mismatch"); ORT_ENFORCE(nullptr == axes_tensor || start_tensor->Shape() == axes_tensor->Shape(), "Starts and axes shape mismatch"); - ORT_ENFORCE(nullptr == steps_tensor || steps_tensor->Shape() == axes_tensor->Shape(), "Steps and axes shape mismatch"); + ORT_ENFORCE(nullptr == steps_tensor || start_tensor->Shape() == steps_tensor->Shape(), "Starts and steps shape mismatch"); const auto& dtype = start_tensor->DataType(); const auto& size = start_tensor->Shape().Size(); diff --git a/onnxruntime/test/providers/cpu/tensor/slice_op.test.cc b/onnxruntime/test/providers/cpu/tensor/slice_op.test.cc index a6dc7946d7..83ee06bed5 100644 --- a/onnxruntime/test/providers/cpu/tensor/slice_op.test.cc +++ b/onnxruntime/test/providers/cpu/tensor/slice_op.test.cc @@ -18,18 +18,18 @@ void RunSliceTest(const std::vector& input_dims, const std::vector& steps, const std::vector& output_dims, const std::vector& output_vals, - bool v10_only = false) { + bool v10_only = false) { // V1-9 if (!v10_only) { - OpTester testv9("Slice", 9); - testv9.AddAttribute("starts", starts); - testv9.AddAttribute("ends", ends); - if (axes.size() != 0) - testv9.AddAttribute("axes", axes); - testv9.AddInput("data", input_dims, input_vals); - testv9.AddOutput("output", output_dims, output_vals); - testv9.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); + OpTester testv9("Slice", 9); + testv9.AddAttribute("starts", starts); + testv9.AddAttribute("ends", ends); + if (axes.size() != 0) + testv9.AddAttribute("axes", axes); + testv9.AddInput("data", input_dims, input_vals); + testv9.AddOutput("output", output_dims, output_vals); + testv9.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); } // V10 @@ -70,7 +70,7 @@ TEST(SliceTest, Slice1D_ValidStartEndRange_NoOutput) { TEST(SliceTest, Slice1D_Regular) { RunSliceTest - ({6}, + ({6}, {0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f}, {2}, {4}, @@ -236,7 +236,7 @@ TEST(SliceTest, Slice1D_WithPositiveSteps) { {2}, {3}, {0.0f, 2.0f, 4.0f}, - true); + true); } // In numpy: @@ -312,7 +312,7 @@ TEST(SliceTest, Slice2D_WithPositiveSteps_1) { {1, 2}, {1, 2}, {5.0f, 7.0f}, - true); + true); } TEST(SliceTest, Slice2D_WithPositiveSteps_2) { @@ -324,7 +324,7 @@ TEST(SliceTest, Slice2D_WithPositiveSteps_2) { {}, // default steps {1, 3}, {2.0f, 3.0f, 4.0f}, - true); + true); } TEST(SliceTest, Slice2D_WithNegativeSteps_1) { @@ -354,10 +354,10 @@ TEST(SliceTest, Slice2D_WithNegativeSteps_2) { TEST(SliceTest, Slice3D_WithPositiveSteps_AllAxes) { RunSliceTest({3, 3, 3}, {27, 20, 2, - 4, 26, 11, + 4, 26, 11, 26, 5, 17, - 0, 21, 6, + 0, 21, 6, 22, 13, 29, 19, 17, 27, @@ -370,7 +370,7 @@ TEST(SliceTest, Slice3D_WithPositiveSteps_AllAxes) { {2, 2, 2}, {2, 1, 1}, {26, 9}, - true); + true); } TEST(SliceTest, Slice3D_WithPositiveAndNegativeSteps_SubsetOfAxes_1) { @@ -414,7 +414,7 @@ TEST(SliceTest, Slice3D_WithPositiveAndNegativeSteps_SubsetOfAxes_2) { {3, -2}, {3, 1, 0}, {}, - true); + true); } // Slice for Reversing @@ -509,5 +509,24 @@ TEST(SliceTest, Slice2D_ImplicitCopyBySlicingADimensionFully) { true); } +TEST(SliceTest, OptionalAxesInputAloneMissing) { + std::vector input_dims = {6}; + auto input_vals = {0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f}; + std::initializer_list starts = {2}; + std::initializer_list ends = {4}; + std::initializer_list steps = {1}; + std::vector output_dims = {2}; + auto output_vals = {2.0f, 3.0f}; + + OpTester testv10("Slice", 10); + testv10.AddInput("data", input_dims, input_vals); + testv10.AddInput("starts", {static_cast(starts.size())}, starts); + testv10.AddInput("ends", {static_cast(ends.size())}, ends); + testv10.AddMissingOptionalInput(); + testv10.AddInput("steps", {static_cast(steps.size())}, steps); + testv10.AddOutput("output", output_dims, output_vals); + testv10.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); +} + } // namespace test } // namespace onnxruntime