diff --git a/cgmanifest.json b/cgmanifest.json index dc7917a49d..9d5fd7c7d0 100644 --- a/cgmanifest.json +++ b/cgmanifest.json @@ -49,7 +49,7 @@ "component":{ "type":"git", "git":{ - "commitHash":"a89a4a162f3d0c9b8269e97327c44297b04214a1", + "commitHash":"1ec81bc6d49ccae23cd7801515feaadd13082903", "repositoryUrl":"https://github.com/onnx/onnx.git" } } diff --git a/cmake/external/onnx b/cmake/external/onnx index a89a4a162f..1ec81bc6d4 160000 --- a/cmake/external/onnx +++ b/cmake/external/onnx @@ -1 +1 @@ -Subproject commit a89a4a162f3d0c9b8269e97327c44297b04214a1 +Subproject commit 1ec81bc6d49ccae23cd7801515feaadd13082903 diff --git a/onnxruntime/core/providers/cpu/cpu_execution_provider.cc b/onnxruntime/core/providers/cpu/cpu_execution_provider.cc index 94dc7d194a..9a946c8270 100644 --- a/onnxruntime/core/providers/cpu/cpu_execution_provider.cc +++ b/onnxruntime/core/providers/cpu/cpu_execution_provider.cc @@ -96,7 +96,7 @@ class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOn class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, 9, int64_t, MatMul); class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, 9, uint64_t, MatMul); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, Softmax); -class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, TopK); +class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, TopK); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, 9, BatchNormalization); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, Conv); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, ConvTranspose); @@ -271,6 +271,7 @@ class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, // Opset 10 class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, StringNormalizer); +class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, TopK); void RegisterOnnxOperatorKernels(KernelRegistry& kernel_registry) { kernel_registry.Register(BuildKernelCreateInfo()); @@ -359,7 +360,7 @@ void RegisterOnnxOperatorKernels(KernelRegistry& kernel_registry) { kernel_registry.Register(BuildKernelCreateInfo()); kernel_registry.Register(BuildKernelCreateInfo()); kernel_registry.Register(BuildKernelCreateInfo()); - kernel_registry.Register(BuildKernelCreateInfo()); + kernel_registry.Register(BuildKernelCreateInfo()); kernel_registry.Register(BuildKernelCreateInfo()); kernel_registry.Register(BuildKernelCreateInfo()); kernel_registry.Register(BuildKernelCreateInfo()); @@ -535,6 +536,7 @@ void RegisterOnnxOperatorKernels(KernelRegistry& kernel_registry) { // Opset 10 kernel_registry.Register(BuildKernelCreateInfo()); + kernel_registry.Register(BuildKernelCreateInfo()); } // Forward declarations of ml op kernels diff --git a/onnxruntime/core/providers/cpu/math/top_k.cc b/onnxruntime/core/providers/cpu/math/top_k.cc index cdf428cc3c..0981fa6c2a 100644 --- a/onnxruntime/core/providers/cpu/math/top_k.cc +++ b/onnxruntime/core/providers/cpu/math/top_k.cc @@ -24,13 +24,8 @@ #include using namespace std; namespace onnxruntime { -// spec https://github.com/onnx/onnx/blob/master/docs/Operators.md#TopK -ONNX_CPU_OPERATOR_KERNEL( - TopK, - 1, - KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType()).TypeConstraint("I", DataTypeImpl::GetTensorType()), - TopK); +// Helper methods static int64_t SizeToDim(size_t k, const vector& dims) { ORT_ENFORCE(k <= dims.size()); int64_t r = 1; @@ -60,17 +55,15 @@ struct ValueCmp { } }; -template <> -Status TopK::Compute(OpKernelContext* p_op_kernel_context) const { - const Tensor* X = p_op_kernel_context->Input(0); - if (X == nullptr) return Status(common::ONNXRUNTIME, common::FAIL, "input count mismatch"); +// Core TopK implementation +Status TopKImpl(OpKernelContext* p_op_kernel_context, const Tensor* X, const int axis, const unsigned k) { const vector& in_dims = X->Shape().GetDims(); // Will return axis_ as is if positive or fixes it in case it is negative - auto axis_parsed = HandleNegativeAxis(axis_, in_dims.size()); - // Check to ensure k_ is within the bounds of what is available in that specific axis - if (in_dims.at(axis_parsed) < k_) { + auto axis_parsed = HandleNegativeAxis(axis, in_dims.size()); + // Check to ensure k is within the bounds of what is available in that specific axis + if (in_dims.at(axis_parsed) < k) { ostringstream err_msg; - err_msg << "k argment [" << k_ << "] should not be greater than specified axis dim value [" << in_dims.at(axis_parsed) << "]"; + err_msg << "k argment [" << k << "] should not be greater than specified axis dim value [" << in_dims.at(axis_parsed) << "]"; return Status(common::ONNXRUNTIME, common::FAIL, err_msg.str()); } @@ -82,10 +75,10 @@ Status TopK::Compute(OpKernelContext* p_op_kernel_context) const { cols); // Resize output tensors to be the same shape as the input except - // for the specified dimension ((i.e.) axis_parsed), which will be of size k_. E.x. for an input tensor - // of shape [3, 4, 5] and k_=2 with axis_parsed=1, both of these will be shape [3, 2, 5] + // for the specified dimension ((i.e.) axis_parsed), which will be of size k. E.x. for an input tensor + // of shape [3, 4, 5] and k=2 with axis_parsed=1, both of these will be shape [3, 2, 5] vector output_linear_shape = in_dims; - output_linear_shape[axis_parsed] = k_; + output_linear_shape[axis_parsed] = k; auto* Values = p_op_kernel_context->Output(0, output_linear_shape); auto* Indices = p_op_kernel_context->Output(1, output_linear_shape); @@ -96,40 +89,100 @@ Status TopK::Compute(OpKernelContext* p_op_kernel_context) const { auto Indices_map = EigenMatrixMapRowMajor( Indices->template MutableData(), rows, reduced_cols); - // This is basically the number of elements within each of the "k_" rows - const int64_t block_slice = reduced_cols / k_; + // This is basically the number of elements within each of the "k" rows + const int64_t block_slice = reduced_cols / k; // Sort preserving Indices for (int64_t i = 0; i < rows; ++i) { - for (int64_t j = 0; j < block_slice; ++j) { - // Build a min-heap, the heap element is pair of (value, idx) - // the top of the heap is the smallest value - priority_queue< - pair, - vector>, - ValueCmp> - min_heap; - // Maintain the size of heap to be less or equal to k_, so the - // heap will hold the k_ largest Values - for (int64_t k = 0; k < in_dims[axis_parsed]; ++k) { - const auto value = input_map(i, k * block_slice + j); - if (min_heap.size() < k_ || value > min_heap.top().first) { - min_heap.push({value, k}); - } - if (min_heap.size() > k_) { - min_heap.pop(); - } - } - // Extract these k_ elements and place them in the results placeholder - for (int64_t l = 0; l < k_; ++l) { - auto& pqElem = min_heap.top(); - auto col_index = (k_ - l -1) * block_slice + j; - Values_map(i, col_index) = pqElem.first; - Indices_map(i, col_index) = pqElem.second; - min_heap.pop(); - } - } + for (int64_t j = 0; j < block_slice; ++j) { + // Build a min-heap, the heap element is pair of (value, idx) + // the top of the heap is the smallest value + priority_queue< + pair, + vector>, + ValueCmp> + min_heap; + // Maintain the size of heap to be less or equal to k_, so the + // heap will hold the k largest Values + for (int64_t l = 0; l < in_dims[axis_parsed]; ++l) { + const auto value = input_map(i, l * block_slice + j); + if (min_heap.size() < k || value > min_heap.top().first) { + min_heap.push({value, l}); + } + if (min_heap.size() > k) { + min_heap.pop(); + } + } + // Extract these k elements and place them in the results placeholder + for (int64_t l = 0; l < k; ++l) { + auto& pqElem = min_heap.top(); + auto col_index = (k - l - 1) * block_slice + j; + Values_map(i, col_index) = pqElem.first; + Indices_map(i, col_index) = pqElem.second; + min_heap.pop(); + } + } } return Status::OK(); } -} // namespace onnxruntime + +// Opset ver - 1 to 9 +template <> +TopK<9, float>::TopK(const OpKernelInfo& op_kernel_info) : OpKernel(op_kernel_info) { + int64_t k_temp; + ORT_ENFORCE(op_kernel_info.GetAttr("k", &k_temp).IsOK()); + ORT_ENFORCE(k_temp > 0); + k_ = gsl::narrow_cast(k_temp); + + int64_t axis_temp; + ORT_ENFORCE(op_kernel_info.GetAttr("axis", &axis_temp).IsOK()); + axis_ = gsl::narrow_cast(axis_temp); +} + +// Opset ver - 1 to 9 +template <> +Status TopK<9, float>::Compute(OpKernelContext* p_op_kernel_context) const { + const Tensor* X = p_op_kernel_context->Input(0); + if (X == nullptr) return Status(common::ONNXRUNTIME, common::FAIL, + "input count mismatch, expected 1 input - the tensor to be processed"); + return TopKImpl(p_op_kernel_context, X, axis_, k_); +} + +// Opset ver - 10 +template <> +TopK<10, float>::TopK(const OpKernelInfo& op_kernel_info) : OpKernel(op_kernel_info) { + int64_t axis_temp; + ORT_ENFORCE(op_kernel_info.GetAttr("axis", &axis_temp).IsOK()); + axis_ = gsl::narrow_cast(axis_temp); +} + +// Opset ver - 10 +template <> +Status TopK<10, float>::Compute(OpKernelContext* p_op_kernel_context) const { + const Tensor* X = p_op_kernel_context->Input(0); + const Tensor* Y = p_op_kernel_context->Input(1); + if (X == nullptr || Y == nullptr) return Status(common::ONNXRUNTIME, common::FAIL, + "input count mismatch, expected 2 inputs - " + "the tensor to be processed and a tensor containing k value"); + const vector& y_shape = Y->Shape().GetDims(); + if (y_shape.size() != 1 || y_shape[0] != 1) return Status(common::ONNXRUNTIME, common::FAIL, "k tensor should be a 1D tensor of size 1"); + unsigned parsed_input_k = gsl::narrow_cast(Y->template Data()[0]); + if (parsed_input_k <= 0) return Status(common::ONNXRUNTIME, common::FAIL, "value of k should be greater than 0"); + return TopKImpl(p_op_kernel_context, X, axis_, parsed_input_k); +} + +// Register necessary kernels +// spec https://github.com/onnx/onnx/blob/master/docs/Operators.md#TopK +ONNX_CPU_OPERATOR_VERSIONED_KERNEL( + TopK, + 1, 9, + KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType()).TypeConstraint("I", DataTypeImpl::GetTensorType()), + TopK<9, float>); + +ONNX_CPU_OPERATOR_KERNEL( + TopK, + 10, + KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType()).TypeConstraint("I", DataTypeImpl::GetTensorType()), + TopK<10, float>); + +} // namespace onnxruntime \ No newline at end of file diff --git a/onnxruntime/core/providers/cpu/math/top_k.h b/onnxruntime/core/providers/cpu/math/top_k.h index 0cc87b148b..b973020be7 100644 --- a/onnxruntime/core/providers/cpu/math/top_k.h +++ b/onnxruntime/core/providers/cpu/math/top_k.h @@ -1,27 +1,15 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -#include "core/common/common.h" -#include "core/common/exceptions.h" +#pragma once + #include "core/framework/op_kernel.h" -#include "core/framework/tensor.h" -#include "core/util/math_cpuonly.h" -#include "gsl/gsl_util" namespace onnxruntime { -template +template class TopK final : public OpKernel { public: - TopK(const OpKernelInfo& op_kernel_info) : OpKernel(op_kernel_info) { - int64_t k_temp; - ORT_ENFORCE(op_kernel_info.GetAttr("k", &k_temp).IsOK()); - ORT_ENFORCE(k_temp > 0); - k_ = gsl::narrow_cast(k_temp); - - int64_t axis_temp; - ORT_ENFORCE(op_kernel_info.GetAttr("axis", &axis_temp).IsOK()); - axis_ = gsl::narrow_cast(axis_temp); - } + TopK(const OpKernelInfo& op_kernel_info); Status Compute(OpKernelContext* p_op_kernel_context) const override; @@ -29,4 +17,4 @@ class TopK final : public OpKernel { int axis_; unsigned k_; }; -} // namespace onnxruntime +} // namespace onnxruntime \ No newline at end of file diff --git a/onnxruntime/test/providers/cpu/math/topk_op_test.cc b/onnxruntime/test/providers/cpu/math/topk_op_test.cc index 5c28ba8fc4..745bc0d72f 100644 --- a/onnxruntime/test/providers/cpu/math/topk_op_test.cc +++ b/onnxruntime/test/providers/cpu/math/topk_op_test.cc @@ -8,7 +8,8 @@ namespace onnxruntime { namespace test { -static void RunTest(int64_t k, +static void RunTest(int op_set, + int64_t k, const std::vector& input_vals, const std::vector& input_dimensions, const std::vector& expected_vals, @@ -17,122 +18,131 @@ static void RunTest(int64_t k, int64_t axis = -1, OpTester::ExpectResult expect_result = OpTester::ExpectResult::kExpectSuccess, const std::string& expected_err_str = "") { - OpTester test("TopK"); - test.AddAttribute("k", k); - if (axis != -1) { - test.AddAttribute("axis", axis); - } + OpTester test("TopK", op_set); + // Attributes + if (axis != -1) + test.AddAttribute("axis", axis); + if (op_set <= 9) + test.AddAttribute("k", k); + + // Inputs test.AddInput("X", input_dimensions, input_vals); + if (op_set == 10) + test.AddInput("K", {1}, {k}); + + // Outputs test.AddOutput("Values", expected_dimensions, expected_vals); test.AddOutput("Indices", expected_dimensions, expected_indices); + + // Run test and check results test.Run(expect_result, expected_err_str); } -TEST(TopKOperator, Top1DefaultAxis) { +TEST(TopKOperator, Top1DefaultAxisOpset9) { std::vector input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.3f, 0.2f}; std::vector input_dimensions = {2, 4}; std::vector expected_vals = {0.4f, 0.3f}; std::vector expected_indices = {3, 1}; std::vector expected_dimensions = {2, 1}; - RunTest(1, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions); + RunTest(9, 1, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions); } -TEST(TopKOperator, Top2DefaultAxis) { +TEST(TopKOperator, Top2DefaultAxisOpset9) { std::vector input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.4f, 0.2f}; std::vector input_dimensions = {2, 4}; std::vector expected_vals = {0.4f, 0.3f, 0.4f, 0.3f}; std::vector expected_indices = {3, 1, 2, 1}; std::vector expected_dimensions = {2, 2}; - RunTest(2, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions); + RunTest(9, 2, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions); } -TEST(TopKOperator, Top3DefaultAxis) { +TEST(TopKOperator, Top3DefaultAxisOpset9) { std::vector input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.4f, 0.2f}; std::vector input_dimensions = {2, 4}; std::vector expected_vals = {0.4f, 0.3f, 0.2f, 0.4f, 0.3f, 0.2f}; std::vector expected_indices = {3, 1, 2, 2, 1, 3}; std::vector expected_dimensions = {2, 3}; - RunTest(3, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions); + RunTest(9, 3, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions); } -TEST(TopKOperator, TopAllDefaultAxis) { +TEST(TopKOperator, TopAllDefaultAxisOpset9) { std::vector input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.3f, 0.2f}; std::vector input_dimensions = {2, 4}; std::vector expected_vals = {0.4f, 0.3f, 0.2f, 0.1f, 0.3f, 0.3f, 0.2f, 0.1f}; std::vector expected_indices = {3, 1, 2, 0, 1, 2, 3, 0}; std::vector expected_dimensions = {2, 4}; - RunTest(4, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions); + RunTest(9, 4, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions); } -TEST(TopKOperator, Top1ExplicitAxis) { +TEST(TopKOperator, Top1ExplicitAxisOpset9) { std::vector input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.3f, 0.2f}; std::vector input_dimensions = {4, 2}; std::vector expected_vals = {0.3f, 0.4f}; std::vector expected_indices = {3, 1}; std::vector expected_dimensions = {1, 2}; int64_t axis = 0; - RunTest(1, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions, axis); + RunTest(9, 1, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions, axis); } -TEST(TopKOperator, Top2ExplicitAxis) { +TEST(TopKOperator, Top2ExplicitAxisOpset9) { std::vector input_vals = {0.0f, 1.0f, 2.0f, 11.0f, 08.0f, 5.0f, 6.0f, 7.0f, 4.0f, 9.0f, 10.0f, 3.0f}; std::vector input_dimensions = {3, 4}; std::vector expected_vals = {8.0f, 9.0f, 10.0f, 11.0f, 4.0f, 5.0f, 6.0f, 7.0f}; std::vector expected_indices = {1, 2, 2, 0, 2, 1, 1, 1}; std::vector expected_dimensions = {2, 4}; int64_t axis = 0; - RunTest(2, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions, axis); + RunTest(9, 2, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions, axis); } -TEST(TopKOperator, Top3ExplicitAxis) { +TEST(TopKOperator, Top3ExplicitAxisOpset9) { std::vector input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.3f, 0.2f}; std::vector input_dimensions = {4, 2}; std::vector expected_vals = {0.3f, 0.4f, 0.2f, 0.3f, 0.1f, 0.3f}; std::vector expected_indices = {3, 1, 1, 0, 0, 2}; std::vector expected_dimensions = {3, 2}; int64_t axis = 0; - RunTest(3, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions, axis); + RunTest(9, 3, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions, axis); } - -TEST(TopKOperator, TopAllExplicitAxis) { +TEST(TopKOperator, TopAllExplicitAxisOpset9) { std::vector input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.3f, 0.2f}; std::vector input_dimensions = {4, 2}; std::vector expected_vals = {0.3f, 0.4f, 0.2f, 0.3f, 0.1f, 0.3f, 0.1f, 0.2f}; std::vector expected_indices = {3, 1, 1, 0, 0, 2, 2, 3}; std::vector expected_dimensions = {4, 2}; int64_t axis = 0; - RunTest(4, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions, axis); + RunTest(9, 4, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions, axis); } -TEST(TopKOperator, TopAllExplicitAxis1DInput) { +TEST(TopKOperator, TopAllExplicitAxis1DInputOpset9) { std::vector input_vals = {93.0f, 695.0f, 971.0f, 978.0f, 483.0f, 247.0f, 242.0f, 983.0f, 531.0f, 723.0f, 285.0f, 527.0f, 862.0f}; std::vector input_dimensions = {13}; std::vector expected_vals = {983.0f, 978.0f, 971.0f, 862.0f, 723.0f, 695.0f, 531.0f, 527.0f, 483.0f, 285.0f, 247.0f, 242.0f, 93.0f}; - std::vector expected_indices = {7, 3, 2, 12, 9, 1, 8, 11, 4, 10, 5, 6,0}; + std::vector expected_indices = {7, 3, 2, 12, 9, 1, 8, 11, 4, 10, 5, 6, 0}; std::vector expected_dimensions = {13}; int64_t axis = 0; - RunTest(13, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions, axis); + RunTest(9, 13, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions, axis); } -TEST(TopKOperator, Top1ExplicitAxisMultiDInput) { +TEST(TopKOperator, Top1ExplicitAxisMultiDInputOpset9) { std::vector input_vals = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f}; std::vector input_dimensions = {2, 2, 2}; std::vector expected_vals = {3, 4, 7, 8}; std::vector expected_indices = {1, 1, 1, 1}; std::vector expected_dimensions = {2, 1, 2}; int64_t axis = 1; - RunTest(1, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions, axis); + RunTest(9, 1, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions, axis); } -TEST(TopKOperator, InvalidK) { +TEST(TopKOperator, InvalidKOpset9) { std::vector input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.3f, 0.2f}; std::vector input_dimensions = {2, 4}; std::vector expected_vals = {0.4f, 0.3f, 0.2f, 0.1f, 0.3f, 0.3f, 0.2f, 0.1f}; std::vector expected_indices = {3, 1, 2, 0, 1, 2, 3, 0}; std::vector expected_dimensions = {2, 4}; - RunTest(0, + RunTest(9, + 0, input_vals, input_dimensions, expected_vals, @@ -143,5 +153,119 @@ TEST(TopKOperator, InvalidK) { "Invalid value for attribute k"); } +TEST(TopKOperator, Top1DefaultAxisOpset10) { + std::vector input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.3f, 0.2f}; + std::vector input_dimensions = {2, 4}; + std::vector expected_vals = {0.4f, 0.3f}; + std::vector expected_indices = {3, 1}; + std::vector expected_dimensions = {2, 1}; + RunTest(10, 1, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions); +} + +TEST(TopKOperator, Top2DefaultAxisOpset10) { + std::vector input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.4f, 0.2f}; + std::vector input_dimensions = {2, 4}; + std::vector expected_vals = {0.4f, 0.3f, 0.4f, 0.3f}; + std::vector expected_indices = {3, 1, 2, 1}; + std::vector expected_dimensions = {2, 2}; + RunTest(10, 2, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions); +} + +TEST(TopKOperator, Top3DefaultAxisOpset10) { + std::vector input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.4f, 0.2f}; + std::vector input_dimensions = {2, 4}; + std::vector expected_vals = {0.4f, 0.3f, 0.2f, 0.4f, 0.3f, 0.2f}; + std::vector expected_indices = {3, 1, 2, 2, 1, 3}; + std::vector expected_dimensions = {2, 3}; + RunTest(10, 3, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions); +} + +TEST(TopKOperator, TopAllDefaultAxisOpset10) { + std::vector input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.3f, 0.2f}; + std::vector input_dimensions = {2, 4}; + std::vector expected_vals = {0.4f, 0.3f, 0.2f, 0.1f, 0.3f, 0.3f, 0.2f, 0.1f}; + std::vector expected_indices = {3, 1, 2, 0, 1, 2, 3, 0}; + std::vector expected_dimensions = {2, 4}; + RunTest(10, 4, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions); +} + +TEST(TopKOperator, Top1ExplicitAxisOpset10) { + std::vector input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.3f, 0.2f}; + std::vector input_dimensions = {4, 2}; + std::vector expected_vals = {0.3f, 0.4f}; + std::vector expected_indices = {3, 1}; + std::vector expected_dimensions = {1, 2}; + int64_t axis = 0; + RunTest(10, 1, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions, axis); +} + +TEST(TopKOperator, Top2ExplicitAxisOpset10) { + std::vector input_vals = {0.0f, 1.0f, 2.0f, 11.0f, 08.0f, 5.0f, 6.0f, 7.0f, 4.0f, 9.0f, 10.0f, 3.0f}; + std::vector input_dimensions = {3, 4}; + std::vector expected_vals = {8.0f, 9.0f, 10.0f, 11.0f, 4.0f, 5.0f, 6.0f, 7.0f}; + std::vector expected_indices = {1, 2, 2, 0, 2, 1, 1, 1}; + std::vector expected_dimensions = {2, 4}; + int64_t axis = 0; + RunTest(10, 2, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions, axis); +} + +TEST(TopKOperator, Top3ExplicitAxisOpset10) { + std::vector input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.3f, 0.2f}; + std::vector input_dimensions = {4, 2}; + std::vector expected_vals = {0.3f, 0.4f, 0.2f, 0.3f, 0.1f, 0.3f}; + std::vector expected_indices = {3, 1, 1, 0, 0, 2}; + std::vector expected_dimensions = {3, 2}; + int64_t axis = 0; + RunTest(10, 3, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions, axis); +} + +TEST(TopKOperator, TopAllExplicitAxisOpset10) { + std::vector input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.3f, 0.2f}; + std::vector input_dimensions = {4, 2}; + std::vector expected_vals = {0.3f, 0.4f, 0.2f, 0.3f, 0.1f, 0.3f, 0.1f, 0.2f}; + std::vector expected_indices = {3, 1, 1, 0, 0, 2, 2, 3}; + std::vector expected_dimensions = {4, 2}; + int64_t axis = 0; + RunTest(10, 4, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions, axis); +} + +TEST(TopKOperator, TopAllExplicitAxis1DInputOpset10) { + std::vector input_vals = {93.0f, 695.0f, 971.0f, 978.0f, 483.0f, 247.0f, 242.0f, 983.0f, 531.0f, 723.0f, 285.0f, 527.0f, 862.0f}; + std::vector input_dimensions = {13}; + std::vector expected_vals = {983.0f, 978.0f, 971.0f, 862.0f, 723.0f, 695.0f, 531.0f, 527.0f, 483.0f, 285.0f, 247.0f, 242.0f, 93.0f}; + std::vector expected_indices = {7, 3, 2, 12, 9, 1, 8, 11, 4, 10, 5, 6, 0}; + std::vector expected_dimensions = {13}; + int64_t axis = 0; + RunTest(10, 13, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions, axis); +} + +TEST(TopKOperator, Top1ExplicitAxisMultiDInputOpset10) { + std::vector input_vals = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f}; + std::vector input_dimensions = {2, 2, 2}; + std::vector expected_vals = {3, 4, 7, 8}; + std::vector expected_indices = {1, 1, 1, 1}; + std::vector expected_dimensions = {2, 1, 2}; + int64_t axis = 1; + RunTest(10, 1, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions, axis); +} + +TEST(TopKOperator, InvalidKOpset10) { + std::vector input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.3f, 0.2f}; + std::vector input_dimensions = {2, 4}; + std::vector expected_vals = {0.4f, 0.3f, 0.2f, 0.1f, 0.3f, 0.3f, 0.2f, 0.1f}; + std::vector expected_indices = {3, 1, 2, 0, 1, 2, 3, 0}; + std::vector expected_dimensions = {2, 4}; + RunTest(10, + 0, + input_vals, + input_dimensions, + expected_vals, + expected_indices, + expected_dimensions, + 1, + OpTester::ExpectResult::kExpectFailure, + "value of k should be greater than 0"); +} + } // namespace test -} // namespace onnxruntime +} // namespace onnxruntime \ No newline at end of file diff --git a/tools/ci_build/github/linux/docker/scripts/install_deps.sh b/tools/ci_build/github/linux/docker/scripts/install_deps.sh index 2e393184bf..0a0ce75df4 100755 --- a/tools/ci_build/github/linux/docker/scripts/install_deps.sh +++ b/tools/ci_build/github/linux/docker/scripts/install_deps.sh @@ -38,8 +38,8 @@ else #5af210ca8a1c73aa6bae8754c9346ec54d0a756e is v1.2.3 #bae6333e149a59a3faa9c4d9c44974373dcf5256 is v1.3.0 #9e55ace55aad1ada27516038dfbdc66a8a0763db is v1.4.1 - #873ddbbc33c6e54d90c5628387edd391fb651dfc is v1.4.1 latest - for onnx_version in "5af210ca8a1c73aa6bae8754c9346ec54d0a756e" "bae6333e149a59a3faa9c4d9c44974373dcf5256" "9e55ace55aad1ada27516038dfbdc66a8a0763db" "a89a4a162f3d0c9b8269e97327c44297b04214a1"; do + #1ec81bc6d49ccae23cd7801515feaadd13082903 is v1.4.1 latest + for onnx_version in "5af210ca8a1c73aa6bae8754c9346ec54d0a756e" "bae6333e149a59a3faa9c4d9c44974373dcf5256" "9e55ace55aad1ada27516038dfbdc66a8a0763db" "1ec81bc6d49ccae23cd7801515feaadd13082903"; do if [ -z ${lastest_onnx_version+x} ]; then echo "first pass"; else