Add CumSum and Round for Opset 11 (#1705)

* Add CumSum and Round for Opset 11

* add back 1 test

* Add back one broken test

* Add back more broken tests

* activate cumsum, round, dynamicquantizelinear tests

* removed python backend tests

* re-comment out dynamicquantizelinear_* tests. ReduceMin(11) not implemented yet

* re-comment out dynamicquantizelinear_* tests. ReduceMin(11) not implemented yet

* comment out cumsum_1d_reverse_exclusive

* Remove few types for csum. Keep only float, int32, int64

* Added friendly error message

* Added double type to pass ONNX tests.
This commit is contained in:
jignparm 2019-09-26 02:46:30 -07:00 committed by GitHub
parent e6ce384402
commit 80ef629c02
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 609 additions and 18 deletions

View file

@ -306,6 +306,13 @@ class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, Re
// opset 11
class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, Clip);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, float, CumSum);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, double, CumSum);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, int32_t, CumSum);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, int64_t, CumSum);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, float, Round);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, double, Round);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, MLFloat16, Round);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, uint8_t, DynamicQuantizeLinear);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, float, ArgMax);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, int32_t, ArgMax);
@ -609,6 +616,13 @@ void RegisterOnnxOperatorKernels(KernelRegistry& kernel_registry) {
//opset 11
BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, Clip)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, float, CumSum)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, double, CumSum)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, int32_t, CumSum)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, int64_t, CumSum)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, float, Round)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, double, Round)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, MLFloat16, Round)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, uint8_t, DynamicQuantizeLinear)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, float, ArgMax)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, int32_t, ArgMax)>,

View file

@ -0,0 +1,162 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "cumsum.h"
#include "core/providers/cpu/tensor/utils.h"
#include "core/framework/op_kernel.h"
#include "core/framework/tensorprotoutils.h"
using namespace onnxruntime;
namespace {
// static section
std::vector<int64_t> GetStarts(int64_t rank, int64_t axis, int64_t index) {
std::vector<int64_t> starts(rank, 0);
starts[axis] = index;
return starts;
}
template <typename T>
void ZeroOutSliceAtIndex(Tensor& output, int64_t rank, int64_t axis, int64_t index,
const std::vector<int64_t>& slice_dims, const std::vector<int64_t>& steps, const int64_t slice_size) {
T zero{};
auto output_starts(GetStarts(rank, axis, index));
WritableSliceIterator<T> output_iterator(output, output_starts, slice_dims, steps);
for (int64_t k = 0; k < slice_size; ++k, ++output_iterator) {
*output_iterator = zero;
}
}
template <typename T>
void CopySlices(const Tensor& input, Tensor& output,
const std::vector<int64_t>& input_starts, const std::vector<int64_t>& output_starts,
const std::vector<int64_t>& slice_dims, const std::vector<int64_t>& steps, const int64_t slice_size) {
SliceIterator<T> input_iterator(input, input_starts, slice_dims, steps);
WritableSliceIterator<T> output_iterator(output, output_starts, slice_dims, steps);
for (int64_t k = 0; k < slice_size; ++k, ++output_iterator, ++input_iterator) {
*output_iterator = *input_iterator;
}
}
template <typename T>
void SumSlices(const Tensor& input, Tensor& output,
const std::vector<int64_t>& input_starts, const std::vector<int64_t>& output_starts, const std::vector<int64_t>& previous_output_starts,
const std::vector<int64_t>& slice_dims, const std::vector<int64_t>& steps, const int64_t slice_size) {
SliceIterator<T> input_iterator(input, input_starts, slice_dims, steps);
WritableSliceIterator<T> output_iterator(output, output_starts, slice_dims, steps);
SliceIterator<T> previous_output_iterator(output, previous_output_starts, slice_dims, steps);
for (int64_t k = 0; k < slice_size; ++k, ++output_iterator, ++input_iterator, ++previous_output_iterator) {
*output_iterator = *input_iterator + *previous_output_iterator;
}
}
} // namespace
namespace onnxruntime {
ONNX_CPU_OPERATOR_TYPED_KERNEL(CumSum, 11, float, KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType<float>()), CumSum<float>);
ONNX_CPU_OPERATOR_TYPED_KERNEL(CumSum, 11, double, KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType<double>()), CumSum<double>);
ONNX_CPU_OPERATOR_TYPED_KERNEL(CumSum, 11, int32_t, KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType<int32_t>()), CumSum<int32_t>);;
ONNX_CPU_OPERATOR_TYPED_KERNEL(CumSum, 11, int64_t, KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType<int64_t>()), CumSum<int64_t>);
template <typename T>
CumSum<T>::CumSum(const OpKernelInfo& info) : OpKernel(info), exclusive_(), reverse_() {
int64_t exclusive = 0;
auto status = info.GetAttr("exclusive", &exclusive);
if (status.IsOK()) {
if (exclusive == 1 || exclusive == 0) {
exclusive_ = exclusive;
} else {
ORT_ENFORCE("attribute exclusive can only be 0 or 1");
}
}
int64_t reverse = 0;
status = info.GetAttr("reverse", &reverse);
if (status.IsOK()) {
if (reverse == 1 || reverse == 0) {
reverse_ = reverse;
} else {
ORT_ENFORCE("attribute reverse can only be 0 or 1");
}
}
}
template <typename T>
Status CumSum<T>::Compute(OpKernelContext* ctx) const {
const Tensor* input = ctx->Input<Tensor>(0); // input tensor
const auto rank = static_cast<int64_t>(input->Shape().NumDimensions()); // the rank of the input/output
const Tensor* axis_tensor = ctx->Input<Tensor>(1); // axis input tensor
if (axis_tensor->Shape().NumDimensions() > 1)
return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Axis tensor should be 0D or 1D");
int32_t axis = axis_tensor->template Data<int32_t>()[0]; // the axis on which the accumulation is going to done
// validate input
if (axis < -rank || axis >= rank)
return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Axis should be in the range [", -rank, ",", rank, ") but got: ", axis);
if (axis < 0)
axis = static_cast<int32_t>(rank) + axis;
TensorShape output_shape(input->Shape());
auto& output_tensor = *ctx->Output(0, output_shape); // output tensor
// output tensor's size is 0, nothing to fill - return
if (output_shape.Size() == 0)
return Status::OK();
auto dim(output_tensor.Shape()[axis]); // dimension size for the axis
TensorShape slice_shape(input->Shape()); // the shape of one slice of input/output for the given value of the axis
slice_shape[axis] = 1;
auto slice_size(slice_shape.Size()); // total number of elements in each slice
auto slice_dims(slice_shape.GetDims()); // dim array for the slice
std::vector<int64_t> steps(rank, 1); // steps for the slice -- always set to 1
if (!reverse_) {
int64_t index(0); // the index we use as we walkthrough the given axis
// If (exclusive == true) the first slice is always 0
if (exclusive_) {
::ZeroOutSliceAtIndex<T>(output_tensor, rank, axis, index, slice_dims, steps, slice_size);
++index;
}
{
// The next slice is a copy of the input (if exclusive == false then this is the first slice)
auto input_starts(::GetStarts(rank, axis, 0));
auto output_starts(::GetStarts(rank, axis, index));
::CopySlices<T>(*input, output_tensor, input_starts, output_starts, slice_dims, steps, slice_size);
++index;
}
for (; index < dim; ++index) {
// Each output slice is the sum of corresponding input slice and the previous output slice
auto input_starts(::GetStarts(rank, axis, exclusive_ ? index - 1 : index));
auto output_starts(::GetStarts(rank, axis, index));
auto previous_starts(::GetStarts(rank, axis, index - 1));
::SumSlices<T>(*input, output_tensor, input_starts, output_starts, previous_starts,
slice_dims, steps, slice_size);
}
} else {
//_reverse == true
int64_t index(dim - 1); // the index we use as we walkthrough the given axis
// If (exclusive == true) the first slice is always 0
if (exclusive_) {
::ZeroOutSliceAtIndex<T>(output_tensor, rank, axis, index, slice_dims, steps, slice_size);
--index;
}
{
// The next slice is a copy of the input (if exclusive == false then this is the first slice)
auto input_starts(::GetStarts(rank, axis, dim - 1));
auto output_starts(::GetStarts(rank, axis, index));
::CopySlices<T>(*input, output_tensor, input_starts, output_starts, slice_dims, steps, slice_size);
--index;
}
for (; index >= 0; --index) {
// Each output slice is the sum of corresponding input slice and the previous output slice
auto input_starts(::GetStarts(rank, axis, exclusive_ ? index + 1 : index));
auto output_starts(::GetStarts(rank, axis, index));
auto previous_starts(::GetStarts(rank, axis, index + 1));
::SumSlices<T>(*input, output_tensor, input_starts, output_starts, previous_starts,
slice_dims, steps, slice_size);
}
}
return Status::OK();
}
}; // namespace onnxruntime

View file

@ -0,0 +1,22 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "core/common/common.h"
#include "core/framework/op_kernel.h"
#include "core/providers/cpu/tensor/pad.h"
namespace onnxruntime {
template <class T>
class CumSum final : public OpKernel {
public:
explicit CumSum(const OpKernelInfo& op_kernel_info);
Status Compute(OpKernelContext* p_op_kernel_context) const override;
private:
int64_t exclusive_;
int64_t reverse_;
};
} // namespace onnxruntime

View file

@ -0,0 +1,45 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "round.h"
#include "core/providers/cpu/tensor/utils.h"
#include "core/framework/op_kernel.h"
#include "core/framework/tensorprotoutils.h"
#include "core/framework/data_types.h"
#include <cmath>
#include "core/providers/cpu/math/element_wise_ops.h"
#include "core/util/math.h"
namespace onnxruntime {
ONNX_CPU_OPERATOR_TYPED_KERNEL(Round, 11, MLFloat16, KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType<MLFloat16>()), Round<MLFloat16>);
ONNX_CPU_OPERATOR_TYPED_KERNEL(Round, 11, float, KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType<float>()), Round<float>);
ONNX_CPU_OPERATOR_TYPED_KERNEL(Round, 11, double, KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType<double>()), Round<double>);
template <typename T>
Status Round<T>::Compute(OpKernelContext* ctx) const {
const auto& X = *ctx->Input<Tensor>(0);
auto& Y = *ctx->Output(0, X.Shape());
auto* input = X.template Data<T>();
auto* output = Y.template MutableData<T>();
const auto size = X.Shape().Size();
for (int64_t i = 0; i < size; ++i, ++output, ++input) {
*output = ::rint(*input);
}
return Status::OK();
}
template <>
Status Round<MLFloat16>::Compute(OpKernelContext* ctx) const {
const auto& X = *ctx->Input<Tensor>(0);
auto& Y = *ctx->Output(0, X.Shape());
auto* input = X.template Data<MLFloat16>();
auto* output = Y.template MutableData<MLFloat16>();
const auto size = X.Shape().Size();
for (int64_t i = 0; i < size; ++i, ++output, ++input) {
*output = MLFloat16(math::floatToHalf(::rint(math::halfToFloat(input->val))));
}
return Status::OK();
}
}; // namespace onnxruntime

View file

@ -0,0 +1,18 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "core/common/common.h"
#include "core/framework/op_kernel.h"
#include "core/providers/cpu/tensor/pad.h"
namespace onnxruntime {
template <class T>
class Round final : public OpKernel {
public:
explicit Round(const OpKernelInfo& op_kernel_info) : OpKernel(op_kernel_info) {}
Status Compute(OpKernelContext* p_op_kernel_context) const override;
};
} // namespace onnxruntime

View file

@ -277,4 +277,120 @@ inline void CopyCpuTensor(const Tensor* src, Tensor* tgt) {
}
}
// This provides easy sequential iteration over a subset of a tensor given a span of starts, extents & optionally steps
template <typename T>
struct WritableSliceIterator {
WritableSliceIterator(Tensor& tensor, gsl::span<const int64_t> starts,
gsl::span<const int64_t> extents, gsl::span<const int64_t> steps)
: tensor_(tensor), input_(tensor_.template MutableData<T>()), extents_(extents), skips_(tensor_.Shape(), extents, steps), indices_(extents.size(), 0) {
auto& dims = tensor_.Shape().GetDims();
Init(dims, starts, steps);
}
// This construct takes a explicit tensor_shape which might be different from the shape defined in input tensor.
// The explicit tensor_shape usually has inner most axis flattened. For example, given shape[1,4,4,2], if last axis
// does not have padding or slice, then it will be flattened as [1,4,8] for better performance (One inner most copy instead of 4).
// Also supports arbitrary positive and negative stepping along individual axes
WritableSliceIterator(Tensor& tensor, const TensorShape& tensor_shape, gsl::span<const int64_t> starts,
gsl::span<const int64_t> extents, gsl::span<const int64_t> steps)
: tensor_(tensor), input_(tensor_.template MutableData<T>()), extents_(extents), skips_(tensor_shape, extents, steps), indices_(extents.size(), 0) {
auto& dims = tensor_shape.GetDims();
Init(dims, starts, steps);
}
// Initialize initial skip and inner_extent.
void Init(const std::vector<int64_t>& dims, gsl::span<const int64_t> starts,
gsl::span<const int64_t> steps) {
ORT_ENFORCE(static_cast<ptrdiff_t>(dims.size()) == starts.size(),
"dims.size()=", dims.size(), " != ", "starts.size()=", starts.size());
ORT_ENFORCE(static_cast<ptrdiff_t>(dims.size()) == extents_.size(),
"dims.size()=", dims.size(), " != ", "extents.size()=", extents_.size());
ORT_ENFORCE(static_cast<ptrdiff_t>(dims.size()) == steps.size(),
"dims.size()=", dims.size(), " != ", "steps.size()=", steps.size());
size_t pitch = 1;
// Initial skip, so that input_ points to the first element to copy
for (size_t i = dims.size(); i-- > 0;) {
input_ += pitch * starts[i];
pitch *= dims[i];
}
inner_extent_ = extents_[dims.size() - 1];
inner_step_ = static_cast<ptrdiff_t>(dims.size()) == steps.size()
? steps[dims.size() - 1]
: 1;
}
void AdvanceOverInnerExtent() {
size_t axis = skips_.size() - 1;
input_ += skips_[axis];
while (axis-- && ++indices_[axis] == extents_[axis]) {
indices_[axis] = 0;
input_ += skips_[axis];
}
}
void IncrementInnerDimension() {
input_ += inner_step_;
if (++inner_counter_ == inner_extent_) {
inner_counter_ = 0;
AdvanceOverInnerExtent();
}
}
// postfix iterator increment
const T* operator++(int) {
const T* input = input_;
IncrementInnerDimension();
return input;
}
// prefix iterator increment
const T* operator++() {
IncrementInnerDimension();
return input_;
}
const T& operator*() const {
return *input_;
}
T& operator*() {
return *input_;
}
// spliting the function that copies the innermost dimension into 2 separate methods,
// as this is most likely being called within a loop
// and we want to avoid the check inside to avoid overhead
// upto the caller to call the relevant one
// Assumes inner_step_ == 1
T* CopyInnermostAxisSolitaryInnerStep(T* output) {
std::copy(input_, input_ + inner_extent_, output);
input_ += inner_extent_;
output += inner_extent_;
AdvanceOverInnerExtent();
return output;
}
// Assumes generic inner_step_
T* CopyInnermostAxisNonSolitaryInnerStep(T* output) {
for (size_t i = 0; i < inner_extent_; ++i) {
*output++ = *input_;
input_ += inner_step_;
}
return output;
}
private:
Tensor& tensor_;
T* input_;
gsl::span<const int64_t> extents_;
size_t inner_counter_{}, inner_extent_, inner_step_;
SliceSkips skips_;
std::vector<int64_t> indices_; // There is no index for innermost axis since it's a special case
};
} // namespace onnxruntime

View file

@ -393,9 +393,6 @@ int real_main(int argc, char* argv[], Ort::Env& env) {
{"maxpool_with_argmax_2d_precomputed_strides", "ShapeInferenceError"},
{"tf_inception_v2", "result mismatch"},
{"mxnet_arcface", "result mismatch"},
{"dynamicquantizelinear_expanded", "Round(11) not implemented yet"},
{"dynamicquantizelinear_max_adjusted_expanded", "Round(11) not implemented yet"},
{"dynamicquantizelinear_min_adjusted_expanded", "Round(11) not implemented yet"},
{"top_k", "not implemented yet for opset 11"},
{"top_k_smallest", "not implemented yet for opset 11"},
{"top_k_negative_axis", "TopK(11) not implemented yet"},
@ -406,15 +403,9 @@ int real_main(int argc, char* argv[], Ort::Env& env) {
{"unique_sorted_axis_3d", "Unique not implemented yet"},
{"unique_sorted_axis", "Unique not implemented yet"},
{"unique_sorted_with_negative_axis", "Unique not implemented yet"},
{"round", "not implemented yet"},
{"gather_elements_1", "not implemented yet"},
{"gather_elements_0", "not implemented yet"},
{"cumsum_2d_axis_1", "not implemented yet"},
{"cumsum_2d_axis_0", "not implemented yet"},
{"cumsum_1d_reverse_exclusive", "not implemented yet"},
{"cumsum_1d_reverse", "not implemented yet"},
{"cumsum_1d_exclusive", "not implemented yet"},
{"cumsum_1d", "not implemented yet"},
{"cumsum_1d_reverse_exclusive", "only failing linux GPU CI. Likely build error."},
{"range_float_type_positive_delta", "not implemented yet"},
{"range_float_type_positive_delta_expanded", "not implemented yet"},
{"range_int32_type_negative_delta", "not implemented yet"},

View file

@ -0,0 +1,197 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "gtest/gtest.h"
#include "test/providers/provider_test_utils.h"
namespace onnxruntime {
namespace test {
TEST(CumSumTest, _1DTest) {
OpTester test("CumSum", 11, onnxruntime::kOnnxDomain);
test.AddInput<float>("x", {5}, {1., 2., 3., 4., 5.});
test.AddInput<int32_t>("axis", {1}, {0});
test.AddOutput<float>("y", {5}, {1., 3., 6., 10., 15.});
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider});
}
TEST(CumSumTest, _1DTestInvalidAxis) {
OpTester test("CumSum", 11, onnxruntime::kOnnxDomain);
test.AddInput<float>("x", {5}, {1., 2., 3., 4., 5.});
test.AddInput<int32_t>("axis", {1}, {-3});
test.AddOutput<float>("y", {5}, {1., 3., 6., 10., 15.});
test.Run(OpTester::ExpectResult::kExpectFailure, "", {kTensorrtExecutionProvider});
}
TEST(CumSumTest, _1DTestNegAxis) {
OpTester test("CumSum", 11, onnxruntime::kOnnxDomain);
test.AddInput<float>("x", {5}, {1., 2., 3., 4., 5.});
test.AddInput<int32_t>("axis", {1}, {-1});
test.AddOutput<float>("y", {5}, {1., 3., 6., 10., 15.});
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider});
}
TEST(CumSumTest, _1DTestExclusive) {
OpTester test("CumSum", 11, onnxruntime::kOnnxDomain);
test.AddAttribute<int64_t>("exclusive", 1);
test.AddInput<float>("x", {5}, {1., 2., 3., 4., 5.});
test.AddInput<int32_t>("axis", {1}, {0});
test.AddOutput<float>("y", {5}, {0., 1., 3., 6., 10.});
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider});
}
TEST(CumSumTest, _2DTestAxis0) {
OpTester test("CumSum", 11, onnxruntime::kOnnxDomain);
test.AddInput<float>("x", {2, 3}, {1., 2., 3., 4., 5., 6.});
test.AddInput<int32_t>("axis", {1}, {0});
test.AddOutput<float>("y", {2, 3}, {1., 2., 3., 5., 7., 9.});
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider});
}
TEST(CumSumTest, _2DTestAxis1) {
OpTester test("CumSum", 11, onnxruntime::kOnnxDomain);
test.AddInput<float>("x", {2, 3}, {1., 2., 3., 4., 5., 6.});
test.AddInput<int32_t>("axis", {1}, {1});
test.AddOutput<float>("y", {2, 3}, {1., 3., 6., 4., 9., 15.});
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider});
}
TEST(CumSumTest, _2DTestExclusiveAxis0) {
OpTester test("CumSum", 11, onnxruntime::kOnnxDomain);
test.AddAttribute<int64_t>("exclusive", 1);
test.AddInput<float>("x", {2, 3}, {1., 2., 3., 4., 5., 6.});
test.AddInput<int32_t>("axis", {1}, {0});
test.AddOutput<float>("y", {2, 3}, {0., 0., 0., 1., 2., 3});
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider});
}
TEST(CumSumTest, _2DTestExclusiveAxis1) {
OpTester test("CumSum", 11, onnxruntime::kOnnxDomain);
test.AddAttribute<int64_t>("exclusive", 1);
test.AddInput<float>("x", {2, 3}, {1., 2., 3., 4., 5., 6.});
test.AddInput<int32_t>("axis", {1}, {1});
test.AddOutput<float>("y", {2, 3}, {0., 1., 3., 0., 4., 9.});
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider});
}
TEST(CumSumTest, _3DTestAxis0) {
OpTester test("CumSum", 11, onnxruntime::kOnnxDomain);
test.AddInput<float>("x", {2, 3, 4}, {1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22., 23., 24.});
test.AddInput<int32_t>("axis", {1}, {0});
test.AddOutput<float>("y", {2, 3, 4}, {1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 14., 16., 18., 20., 22., 24., 26., 28., 30., 32., 34., 36.});
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider});
}
TEST(CumSumTest, _3DTestAxis1) {
OpTester test("CumSum", 11, onnxruntime::kOnnxDomain);
test.AddInput<float>("x", {2, 3, 4}, {1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22., 23., 24.});
test.AddInput<int32_t>("axis", {1}, {1});
test.AddOutput<float>("y", {2, 3, 4}, {1., 2., 3., 4., 6., 8., 10., 12., 15., 18., 21., 24., 13., 14., 15., 16., 30., 32., 34., 36., 51., 54., 57., 60.});
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider});
}
TEST(CumSumTest, _3DTestAxis2) {
OpTester test("CumSum", 11, onnxruntime::kOnnxDomain);
test.AddInput<float>("x", {2, 3, 4}, {1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22., 23., 24.});
test.AddInput<int32_t>("axis", {1}, {2});
test.AddOutput<float>("y", {2, 3, 4}, {1., 3., 6., 10., 5., 11., 18., 26., 9., 19., 30., 42., 13., 27., 42., 58., 17., 35., 54., 74., 21., 43., 66., 90.});
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider});
}
TEST(CumSumTest, _3DTestAxis0Exclusive) {
OpTester test("CumSum", 11, onnxruntime::kOnnxDomain);
test.AddAttribute<int64_t>("exclusive", 1);
test.AddInput<float>("x", {2, 3, 4}, {1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22., 23., 24.});
test.AddInput<int32_t>("axis", {1}, {0});
test.AddOutput<float>("y", {2, 3, 4}, {0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.});
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider});
}
TEST(CumSumTest, _3DTestAxis1Exclusive) {
OpTester test("CumSum", 11, onnxruntime::kOnnxDomain);
test.AddAttribute<int64_t>("exclusive", 1);
test.AddInput<float>("x", {2, 3, 4}, {1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22., 23., 24.});
test.AddInput<int32_t>("axis", {1}, {1});
test.AddOutput<float>("y", {2, 3, 4}, {0., 0., 0., 0., 1., 2., 3., 4., 6., 8., 10., 12., 0., 0., 0., 0., 13., 14., 15., 16., 30., 32., 34., 36.});
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider});
}
TEST(CumSumTest, _3DTestAxis2Exclusive) {
OpTester test("CumSum", 11, onnxruntime::kOnnxDomain);
test.AddAttribute<int64_t>("exclusive", 1);
test.AddInput<float>("x", {2, 3, 4}, {1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22., 23., 24.});
test.AddInput<int32_t>("axis", {1}, {2});
test.AddOutput<float>("y", {2, 3, 4}, {0., 1., 3., 6., 0., 5., 11., 18., 0., 9., 19., 30., 0., 13., 27., 42., 0., 17., 35., 54., 0., 21., 43., 66.});
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider});
}
TEST(CumSumTest, _1DTestReverse) {
OpTester test("CumSum", 11, onnxruntime::kOnnxDomain);
test.AddAttribute<int64_t>("reverse", 1);
test.AddInput<float>("x", {5}, {1., 2., 3., 4., 5.});
test.AddInput<int32_t>("axis", {1}, {0});
test.AddOutput<float>("y", {5}, {15., 14., 12., 9., 5.});
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider});
}
TEST(CumSumTest, _1DTestReverseExclusive) {
OpTester test("CumSum", 11, onnxruntime::kOnnxDomain);
test.AddAttribute<int64_t>("exclusive", 1);
test.AddAttribute<int64_t>("reverse", 1);
test.AddInput<float>("x", {5}, {1., 2., 3., 4., 5.});
test.AddInput<int32_t>("axis", {1}, {0});
test.AddOutput<float>("y", {5}, {14., 12., 9., 5., 0.});
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider});
}
TEST(CumSumTest, _3DTestAxis0Reverse) {
OpTester test("CumSum", 11, onnxruntime::kOnnxDomain);
test.AddAttribute<int64_t>("reverse", 1);
test.AddInput<float>("x", {2, 3, 4}, {1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22., 23., 24.});
test.AddInput<int32_t>("axis", {1}, {0});
test.AddOutput<float>("y", {2, 3, 4}, {14., 16., 18., 20., 22., 24., 26., 28., 30., 32., 34., 36., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22., 23., 24.});
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider});
}
TEST(CumSumTest, _3DTestAxis1Reverse) {
OpTester test("CumSum", 11, onnxruntime::kOnnxDomain);
test.AddAttribute<int64_t>("reverse", 1);
test.AddInput<float>("x", {2, 3, 4}, {1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22., 23., 24.});
test.AddInput<int32_t>("axis", {1}, {1});
test.AddOutput<float>("y", {2, 3, 4}, {15., 18., 21., 24., 14., 16., 18., 20., 9., 10., 11., 12., 51., 54., 57., 60., 38., 40., 42., 44., 21., 22., 23., 24.});
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider});
}
TEST(CumSumTest, _3DTestAxis2Reverse) {
OpTester test("CumSum", 11, onnxruntime::kOnnxDomain);
test.AddAttribute<int64_t>("reverse", 1);
test.AddInput<float>("x", {2, 3, 4}, {1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22., 23., 24.});
test.AddInput<int32_t>("axis", {1}, {2});
test.AddOutput<float>("y", {2, 3, 4}, {10., 9., 7., 4., 26., 21., 15., 8., 42., 33., 23., 12., 58., 45., 31., 16., 74., 57., 39., 20., 90., 69., 47., 24.});
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider});
}
TEST(CumSumTest, _3DTestAxis0ReverseExclusive) {
OpTester test("CumSum", 11, onnxruntime::kOnnxDomain);
test.AddAttribute<int64_t>("reverse", 1);
test.AddAttribute<int64_t>("exclusive", 1);
test.AddInput<float>("x", {2, 3, 4}, {1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22., 23., 24.});
test.AddInput<int32_t>("axis", {1}, {0});
test.AddOutput<float>("y", {2, 3, 4}, {13., 14., 15., 16., 17., 18., 19., 20., 21., 22., 23., 24., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.});
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider});
}
TEST(CumSumTest, _3DTestAxis1ReverseExclusive) {
OpTester test("CumSum", 11, onnxruntime::kOnnxDomain);
test.AddAttribute<int64_t>("reverse", 1);
test.AddAttribute<int64_t>("exclusive", 1);
test.AddInput<float>("x", {2, 3, 4}, {1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22., 23., 24.});
test.AddInput<int32_t>("axis", {1}, {1});
test.AddOutput<float>("y", {2, 3, 4}, {14., 16., 18., 20., 9., 10., 11., 12., 0., 0., 0., 0., 38., 40., 42., 44., 21., 22., 23., 24., 0., 0., 0., 0.});
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider});
}
TEST(CumSumTest, _3DTestAxis2ReverseExclusive) {
OpTester test("CumSum", 11, onnxruntime::kOnnxDomain);
test.AddAttribute<int64_t>("reverse", 1);
test.AddAttribute<int64_t>("exclusive", 1);
test.AddInput<float>("x", {2, 3, 4}, {1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22., 23., 24.});
test.AddInput<int32_t>("axis", {1}, {2});
test.AddOutput<float>("y", {2, 3, 4}, {9., 7., 4., 0., 21., 15., 8., 0., 33., 23., 12., 0., 45., 31., 16., 0., 57., 39., 20., 0., 69., 47., 24., 0.});
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider});
}
TEST(CumSumTest, _1DTestInt32) {
OpTester test("CumSum", 11, onnxruntime::kOnnxDomain);
test.AddInput<int32_t>("x", {5}, {1, 2, 3, 4, 5});
test.AddInput<int32_t>("axis", {1}, {0});
test.AddOutput<int32_t>("y", {5}, {1, 3, 6, 10, 15});
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider});
}
TEST(CumSumTest, _1DTestInt64) {
OpTester test("CumSum", 11, onnxruntime::kOnnxDomain);
test.AddInput<int64_t>("x", {5}, {1, 2, 3, 4, 5});
test.AddInput<int32_t>("axis", {1}, {0});
test.AddOutput<int64_t>("y", {5}, {1, 3, 6, 10, 15});
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider});
}
} // namespace test
} // namespace onnxruntime

View file

@ -0,0 +1,34 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "gtest/gtest.h"
#include "test/providers/provider_test_utils.h"
#include "core/framework/data_types.h"
#include "core/util/math.h"
namespace onnxruntime {
namespace test {
TEST(RoundTest, SimpleTestFloat) {
OpTester test("Round", 11, onnxruntime::kOnnxDomain);
test.AddInput<float>("x", {5}, {0.9f, 2.5f, 2.3f, 1.5f, -4.5f});
test.AddOutput<float>("y", {5}, {1.0f, 2.0f, 2.0f, 2.0f, -4.0f});
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider});
}
TEST(RoundTest, SimpleTestDouble) {
OpTester test("Round", 11, onnxruntime::kOnnxDomain);
test.AddInput<double>("x", {5}, {0.9, 2.5, 2.3, 1.5, -4.5});
test.AddOutput<double>("y", {5}, {1.0, 2.0, 2.0, 2.0, -4.0});
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider});
}
TEST(RoundTest, SimpleTestFloat16) {
OpTester test("Round", 11, onnxruntime::kOnnxDomain);
test.AddInput<MLFloat16>("x", {5}, {MLFloat16(math::floatToHalf(0.9f)), MLFloat16(math::floatToHalf(2.5f)), MLFloat16(math::floatToHalf(2.3f)), MLFloat16(math::floatToHalf(1.5f)), MLFloat16(math::floatToHalf(-4.5f))});
test.AddOutput<MLFloat16>("y", {5}, {MLFloat16(math::floatToHalf(1.0f)), MLFloat16(math::floatToHalf(2.0f)), MLFloat16(math::floatToHalf(2.0f)), MLFloat16(math::floatToHalf(2.0f)), MLFloat16(math::floatToHalf(-4.0f))});
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider});
}
} // namespace test
} // namespace onnxruntime

View file

@ -103,14 +103,6 @@ def create_backend_test(testname=None):
'^test_bitshift_left_uint32_cpu.*',
'^test_bitshift_left_uint64_cpu.*',
'^test_bitshift_left_uint8_cpu.*',
'^test_round_cpu.*',
'^test_cumsum_1d_cpu.*',
'^test_cumsum_1d_exclusive_cpu.*',
'^test_cumsum_1d_reverse_cpu.*',
'^test_cumsum_1d_reverse_exclusive_cpu.*',
'^test_cumsum_2d_axis_0_cpu.*',
'^test_cumsum_2d_axis_1_cpu.*',
'^test_cumsum_2d_negative_axis_cpu.*',
'^test_dynamicquantizelinear_expanded*',
'^test_dynamicquantizelinear_max_adjusted_expanded*',
'^test_dynamicquantizelinear_min_adjusted_expanded*',