TopK op: Promote onnx to a newer commit and handle changed TopK spec for opset 10 (#611)

* Initial commit

* Nit fix
This commit is contained in:
Hariharan Seshadri 2019-03-13 10:21:58 -07:00 committed by GitHub
parent 7dd9bc4d78
commit cfb08c4848
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 269 additions and 102 deletions

View file

@ -49,7 +49,7 @@
"component":{
"type":"git",
"git":{
"commitHash":"a89a4a162f3d0c9b8269e97327c44297b04214a1",
"commitHash":"1ec81bc6d49ccae23cd7801515feaadd13082903",
"repositoryUrl":"https://github.com/onnx/onnx.git"
}
}

2
cmake/external/onnx vendored

@ -1 +1 @@
Subproject commit a89a4a162f3d0c9b8269e97327c44297b04214a1
Subproject commit 1ec81bc6d49ccae23cd7801515feaadd13082903

View file

@ -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<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 6, Clip)>());
@ -359,7 +360,7 @@ void RegisterOnnxOperatorKernels(KernelRegistry& kernel_registry) {
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, 9, int64_t, MatMul)>());
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, 9, uint64_t, MatMul)>());
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, Softmax)>());
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, TopK)>());
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, TopK)>());
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, 9, BatchNormalization)>());
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, Conv)>());
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, ConvTranspose)>());
@ -535,6 +536,7 @@ void RegisterOnnxOperatorKernels(KernelRegistry& kernel_registry) {
// Opset 10
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, StringNormalizer)>());
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, TopK)>());
}
// Forward declarations of ml op kernels

View file

@ -24,13 +24,8 @@
#include <queue>
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<float>()).TypeConstraint("I", DataTypeImpl::GetTensorType<int64_t>()),
TopK<float>);
// Helper methods
static int64_t SizeToDim(size_t k, const vector<int64_t>& dims) {
ORT_ENFORCE(k <= dims.size());
int64_t r = 1;
@ -60,17 +55,15 @@ struct ValueCmp {
}
};
template <>
Status TopK<float>::Compute(OpKernelContext* p_op_kernel_context) const {
const Tensor* X = p_op_kernel_context->Input<Tensor>(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<int64_t>& 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<float>::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<int64_t> 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<float>::Compute(OpKernelContext* p_op_kernel_context) const {
auto Indices_map = EigenMatrixMapRowMajor<int64_t>(
Indices->template MutableData<int64_t>(), 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<float, int64_t>,
vector<pair<float, int64_t>>,
ValueCmp<float>>
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<float, int64_t>,
vector<pair<float, int64_t>>,
ValueCmp<float>>
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<int64_t>("k", &k_temp).IsOK());
ORT_ENFORCE(k_temp > 0);
k_ = gsl::narrow_cast<unsigned>(k_temp);
int64_t axis_temp;
ORT_ENFORCE(op_kernel_info.GetAttr<int64_t>("axis", &axis_temp).IsOK());
axis_ = gsl::narrow_cast<int>(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<Tensor>(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<int64_t>("axis", &axis_temp).IsOK());
axis_ = gsl::narrow_cast<int>(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<Tensor>(0);
const Tensor* Y = p_op_kernel_context->Input<Tensor>(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<int64_t>& 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<unsigned>(Y->template Data<int64_t>()[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<float>()).TypeConstraint("I", DataTypeImpl::GetTensorType<int64_t>()),
TopK<9, float>);
ONNX_CPU_OPERATOR_KERNEL(
TopK,
10,
KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType<float>()).TypeConstraint("I", DataTypeImpl::GetTensorType<int64_t>()),
TopK<10, float>);
} // namespace onnxruntime

View file

@ -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 <typename T>
template <int OpSet, typename T>
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<int64_t>("k", &k_temp).IsOK());
ORT_ENFORCE(k_temp > 0);
k_ = gsl::narrow_cast<unsigned>(k_temp);
int64_t axis_temp;
ORT_ENFORCE(op_kernel_info.GetAttr<int64_t>("axis", &axis_temp).IsOK());
axis_ = gsl::narrow_cast<int>(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

View file

@ -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<float>& input_vals,
const std::vector<int64_t>& input_dimensions,
const std::vector<float>& 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<float>("X", input_dimensions, input_vals);
if (op_set == 10)
test.AddInput<int64_t>("K", {1}, {k});
// Outputs
test.AddOutput<float>("Values", expected_dimensions, expected_vals);
test.AddOutput<int64_t>("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<float> input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.3f, 0.2f};
std::vector<int64_t> input_dimensions = {2, 4};
std::vector<float> expected_vals = {0.4f, 0.3f};
std::vector<int64_t> expected_indices = {3, 1};
std::vector<int64_t> 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<float> input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.4f, 0.2f};
std::vector<int64_t> input_dimensions = {2, 4};
std::vector<float> expected_vals = {0.4f, 0.3f, 0.4f, 0.3f};
std::vector<int64_t> expected_indices = {3, 1, 2, 1};
std::vector<int64_t> 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<float> input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.4f, 0.2f};
std::vector<int64_t> input_dimensions = {2, 4};
std::vector<float> expected_vals = {0.4f, 0.3f, 0.2f, 0.4f, 0.3f, 0.2f};
std::vector<int64_t> expected_indices = {3, 1, 2, 2, 1, 3};
std::vector<int64_t> 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<float> input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.3f, 0.2f};
std::vector<int64_t> input_dimensions = {2, 4};
std::vector<float> expected_vals = {0.4f, 0.3f, 0.2f, 0.1f, 0.3f, 0.3f, 0.2f, 0.1f};
std::vector<int64_t> expected_indices = {3, 1, 2, 0, 1, 2, 3, 0};
std::vector<int64_t> 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<float> input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.3f, 0.2f};
std::vector<int64_t> input_dimensions = {4, 2};
std::vector<float> expected_vals = {0.3f, 0.4f};
std::vector<int64_t> expected_indices = {3, 1};
std::vector<int64_t> 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<float> 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<int64_t> input_dimensions = {3, 4};
std::vector<float> expected_vals = {8.0f, 9.0f, 10.0f, 11.0f, 4.0f, 5.0f, 6.0f, 7.0f};
std::vector<int64_t> expected_indices = {1, 2, 2, 0, 2, 1, 1, 1};
std::vector<int64_t> 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<float> input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.3f, 0.2f};
std::vector<int64_t> input_dimensions = {4, 2};
std::vector<float> expected_vals = {0.3f, 0.4f, 0.2f, 0.3f, 0.1f, 0.3f};
std::vector<int64_t> expected_indices = {3, 1, 1, 0, 0, 2};
std::vector<int64_t> 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<float> input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.3f, 0.2f};
std::vector<int64_t> input_dimensions = {4, 2};
std::vector<float> expected_vals = {0.3f, 0.4f, 0.2f, 0.3f, 0.1f, 0.3f, 0.1f, 0.2f};
std::vector<int64_t> expected_indices = {3, 1, 1, 0, 0, 2, 2, 3};
std::vector<int64_t> 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<float> 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<int64_t> input_dimensions = {13};
std::vector<float> 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<int64_t> expected_indices = {7, 3, 2, 12, 9, 1, 8, 11, 4, 10, 5, 6,0};
std::vector<int64_t> expected_indices = {7, 3, 2, 12, 9, 1, 8, 11, 4, 10, 5, 6, 0};
std::vector<int64_t> 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<float> input_vals = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f};
std::vector<int64_t> input_dimensions = {2, 2, 2};
std::vector<float> expected_vals = {3, 4, 7, 8};
std::vector<int64_t> expected_indices = {1, 1, 1, 1};
std::vector<int64_t> 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<float> input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.3f, 0.2f};
std::vector<int64_t> input_dimensions = {2, 4};
std::vector<float> expected_vals = {0.4f, 0.3f, 0.2f, 0.1f, 0.3f, 0.3f, 0.2f, 0.1f};
std::vector<int64_t> expected_indices = {3, 1, 2, 0, 1, 2, 3, 0};
std::vector<int64_t> 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<float> input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.3f, 0.2f};
std::vector<int64_t> input_dimensions = {2, 4};
std::vector<float> expected_vals = {0.4f, 0.3f};
std::vector<int64_t> expected_indices = {3, 1};
std::vector<int64_t> expected_dimensions = {2, 1};
RunTest(10, 1, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions);
}
TEST(TopKOperator, Top2DefaultAxisOpset10) {
std::vector<float> input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.4f, 0.2f};
std::vector<int64_t> input_dimensions = {2, 4};
std::vector<float> expected_vals = {0.4f, 0.3f, 0.4f, 0.3f};
std::vector<int64_t> expected_indices = {3, 1, 2, 1};
std::vector<int64_t> expected_dimensions = {2, 2};
RunTest(10, 2, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions);
}
TEST(TopKOperator, Top3DefaultAxisOpset10) {
std::vector<float> input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.4f, 0.2f};
std::vector<int64_t> input_dimensions = {2, 4};
std::vector<float> expected_vals = {0.4f, 0.3f, 0.2f, 0.4f, 0.3f, 0.2f};
std::vector<int64_t> expected_indices = {3, 1, 2, 2, 1, 3};
std::vector<int64_t> expected_dimensions = {2, 3};
RunTest(10, 3, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions);
}
TEST(TopKOperator, TopAllDefaultAxisOpset10) {
std::vector<float> input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.3f, 0.2f};
std::vector<int64_t> input_dimensions = {2, 4};
std::vector<float> expected_vals = {0.4f, 0.3f, 0.2f, 0.1f, 0.3f, 0.3f, 0.2f, 0.1f};
std::vector<int64_t> expected_indices = {3, 1, 2, 0, 1, 2, 3, 0};
std::vector<int64_t> expected_dimensions = {2, 4};
RunTest(10, 4, input_vals, input_dimensions, expected_vals, expected_indices, expected_dimensions);
}
TEST(TopKOperator, Top1ExplicitAxisOpset10) {
std::vector<float> input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.3f, 0.2f};
std::vector<int64_t> input_dimensions = {4, 2};
std::vector<float> expected_vals = {0.3f, 0.4f};
std::vector<int64_t> expected_indices = {3, 1};
std::vector<int64_t> 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<float> 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<int64_t> input_dimensions = {3, 4};
std::vector<float> expected_vals = {8.0f, 9.0f, 10.0f, 11.0f, 4.0f, 5.0f, 6.0f, 7.0f};
std::vector<int64_t> expected_indices = {1, 2, 2, 0, 2, 1, 1, 1};
std::vector<int64_t> 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<float> input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.3f, 0.2f};
std::vector<int64_t> input_dimensions = {4, 2};
std::vector<float> expected_vals = {0.3f, 0.4f, 0.2f, 0.3f, 0.1f, 0.3f};
std::vector<int64_t> expected_indices = {3, 1, 1, 0, 0, 2};
std::vector<int64_t> 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<float> input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.3f, 0.2f};
std::vector<int64_t> input_dimensions = {4, 2};
std::vector<float> expected_vals = {0.3f, 0.4f, 0.2f, 0.3f, 0.1f, 0.3f, 0.1f, 0.2f};
std::vector<int64_t> expected_indices = {3, 1, 1, 0, 0, 2, 2, 3};
std::vector<int64_t> 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<float> 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<int64_t> input_dimensions = {13};
std::vector<float> 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<int64_t> expected_indices = {7, 3, 2, 12, 9, 1, 8, 11, 4, 10, 5, 6, 0};
std::vector<int64_t> 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<float> input_vals = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f};
std::vector<int64_t> input_dimensions = {2, 2, 2};
std::vector<float> expected_vals = {3, 4, 7, 8};
std::vector<int64_t> expected_indices = {1, 1, 1, 1};
std::vector<int64_t> 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<float> input_vals = {0.1f, 0.3f, 0.2f, 0.4f, 0.1f, 0.3f, 0.3f, 0.2f};
std::vector<int64_t> input_dimensions = {2, 4};
std::vector<float> expected_vals = {0.4f, 0.3f, 0.2f, 0.1f, 0.3f, 0.3f, 0.2f, 0.1f};
std::vector<int64_t> expected_indices = {3, 1, 2, 0, 1, 2, 3, 0};
std::vector<int64_t> 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

View file

@ -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