mirror of
https://github.com/saymrwulf/onnxruntime.git
synced 2026-07-22 19:23:30 +00:00
Implement opset v10 changes for Slice operator (#772)
This commit is contained in:
parent
53038b33ed
commit
56749a84ee
10 changed files with 813 additions and 236 deletions
|
|
@ -160,19 +160,19 @@ class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDoma
|
|||
class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 5, Reshape);
|
||||
class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, Shape);
|
||||
class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, Size);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, bool, Slice);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, float, Slice);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, double, Slice);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, MLFloat16, Slice);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, uint8_t, Slice);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, uint16_t, Slice);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, uint32_t, Slice);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, uint64_t, Slice);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, int8_t, Slice);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, int16_t, Slice);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, int32_t, Slice);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, int64_t, Slice);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, string, Slice);
|
||||
class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, bool, Slice);
|
||||
class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, float, Slice);
|
||||
class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, double, Slice);
|
||||
class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, MLFloat16, Slice);
|
||||
class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, uint8_t, Slice);
|
||||
class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, uint16_t, Slice);
|
||||
class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, uint32_t, Slice);
|
||||
class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, uint64_t, Slice);
|
||||
class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, int8_t, Slice);
|
||||
class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, int16_t, Slice);
|
||||
class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, int32_t, Slice);
|
||||
class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, int64_t, Slice);
|
||||
class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, string, Slice);
|
||||
class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, SpaceToDepth);
|
||||
class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 4, DepthToSpace);
|
||||
class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 2, Split);
|
||||
|
|
@ -247,6 +247,19 @@ class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, QL
|
|||
class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, MatMulInteger);
|
||||
class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, ConvInteger);
|
||||
class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, QLinearConv);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, bool, Slice);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, float, Slice);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, double, Slice);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, MLFloat16, Slice);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, uint8_t, Slice);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, uint16_t, Slice);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, uint32_t, Slice);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, uint64_t, Slice);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, int8_t, Slice);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, int16_t, Slice);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, int32_t, Slice);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, int64_t, Slice);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, string, Slice);
|
||||
|
||||
void RegisterOnnxOperatorKernels(KernelRegistry& kernel_registry) {
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 6, Clip)>());
|
||||
|
|
@ -395,21 +408,19 @@ void RegisterOnnxOperatorKernels(KernelRegistry& kernel_registry) {
|
|||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 5, Reshape)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, Shape)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, Size)>());
|
||||
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, bool, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, float, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, double, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, MLFloat16, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, uint8_t, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, uint16_t, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, uint32_t, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, uint64_t, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, int8_t, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, int16_t, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, int32_t, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, int64_t, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, string, Slice)>());
|
||||
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, bool, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, float, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, double, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, MLFloat16, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, uint8_t, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, uint16_t, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, uint32_t, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, uint64_t, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, int8_t, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, int16_t, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, int32_t, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, int64_t, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 9, string, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, SpaceToDepth)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 4, DepthToSpace)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 2, Split)>());
|
||||
|
|
@ -484,6 +495,19 @@ void RegisterOnnxOperatorKernels(KernelRegistry& kernel_registry) {
|
|||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, MatMulInteger)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, ConvInteger)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, QLinearConv)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, bool, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, float, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, double, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, MLFloat16, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, uint8_t, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, uint16_t, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, uint32_t, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, uint64_t, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, int8_t, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, int16_t, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, int32_t, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, int64_t, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, string, Slice)>());
|
||||
}
|
||||
|
||||
// Forward declarations of ml op kernels
|
||||
|
|
|
|||
|
|
@ -171,12 +171,12 @@ Status MaxUnpool::Compute(OpKernelContext* context) const {
|
|||
size_t inner_axis = dimension_count - 1;
|
||||
|
||||
TensorAxisCounters input_counters(*p_tensor);
|
||||
SliceIterator<float> input(*p_tensor, input_starts, input_extents);
|
||||
SliceIterator<float> input(*p_tensor, input_starts, input_extents, {});
|
||||
|
||||
while (input_counters) {
|
||||
Y_data += alignSkip;
|
||||
{
|
||||
Y_data = input.CopyInnermostAxis(Y_data);
|
||||
Y_data = input.CopyInnermostAxisSolitaryInnerStep(Y_data);
|
||||
int64_t prePad = inferredPads[inner_axis];
|
||||
int64_t postPad = inferredPads[inner_axis + dimension_count];
|
||||
Y_data += postPad;
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ Status Pad<float>::Compute(OpKernelContext* ctx) const {
|
|||
TensorShape output_shape(output_dims);
|
||||
|
||||
TensorShape input_shape(reshaped_input_dims);
|
||||
SliceIterator<float> input(input_tensor, input_shape, input_starts, input_extents);
|
||||
SliceIterator<float> input(input_tensor, input_shape, input_starts, input_extents, {});
|
||||
|
||||
// output_shape need to keep original.
|
||||
auto& output_tensor = *ctx->Output(0, output_shape);
|
||||
|
|
@ -155,7 +155,7 @@ Status Pad<float>::Compute(OpKernelContext* ctx) const {
|
|||
output += alignSkip;
|
||||
{
|
||||
float* axisStart = output;
|
||||
output = input.CopyInnermostAxis(output);
|
||||
output = input.CopyInnermostAxisSolitaryInnerStep(output);
|
||||
|
||||
int64_t prePad = reshaped_pad[inner_axis];
|
||||
int64_t postPad = reshaped_pad[inner_axis + new_dims_count];
|
||||
|
|
@ -186,7 +186,7 @@ Status Pad<float>::Compute(OpKernelContext* ctx) const {
|
|||
output += alignSkip;
|
||||
{
|
||||
float* axisStart = output;
|
||||
output = input.CopyInnermostAxis(output);
|
||||
output = input.CopyInnermostAxisSolitaryInnerStep(output);
|
||||
|
||||
int64_t prePad = reshaped_pad[inner_axis];
|
||||
int64_t postPad = reshaped_pad[inner_axis + new_dims_count];
|
||||
|
|
@ -217,7 +217,7 @@ Status Pad<float>::Compute(OpKernelContext* ctx) const {
|
|||
output += alignSkip;
|
||||
{
|
||||
float* axisStart = output;
|
||||
output = input.CopyInnermostAxis(output);
|
||||
output = input.CopyInnermostAxisSolitaryInnerStep(output);
|
||||
|
||||
int64_t prePad = reshaped_pad[inner_axis];
|
||||
int64_t postPad = reshaped_pad[inner_axis + new_dims_count];
|
||||
|
|
|
|||
|
|
@ -3,31 +3,34 @@
|
|||
|
||||
#include "core/providers/cpu/tensor/slice.h"
|
||||
#include "core/providers/cpu/tensor/utils.h"
|
||||
#include <unordered_map>
|
||||
#include <limits>
|
||||
|
||||
using namespace ::onnxruntime::common;
|
||||
using namespace std;
|
||||
|
||||
namespace onnxruntime {
|
||||
#define ADD_TYPED_SLICE_OP(data_type) \
|
||||
ONNX_CPU_OPERATOR_TYPED_KERNEL( \
|
||||
#define ADD_TYPED_SLICE_V9_OP(data_type) \
|
||||
ONNX_CPU_OPERATOR_VERSIONED_TYPED_KERNEL( \
|
||||
Slice, \
|
||||
1, \
|
||||
1, 9, \
|
||||
data_type, \
|
||||
KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType<data_type>()), \
|
||||
Slice<data_type, false>);
|
||||
|
||||
ADD_TYPED_SLICE_OP(uint8_t);
|
||||
ADD_TYPED_SLICE_OP(uint16_t);
|
||||
ADD_TYPED_SLICE_OP(uint32_t);
|
||||
ADD_TYPED_SLICE_OP(uint64_t);
|
||||
ADD_TYPED_SLICE_OP(int8_t);
|
||||
ADD_TYPED_SLICE_OP(int16_t);
|
||||
ADD_TYPED_SLICE_OP(int32_t);
|
||||
ADD_TYPED_SLICE_OP(int64_t);
|
||||
ADD_TYPED_SLICE_OP(float);
|
||||
ADD_TYPED_SLICE_OP(double);
|
||||
ADD_TYPED_SLICE_OP(MLFloat16);
|
||||
ADD_TYPED_SLICE_OP(bool);
|
||||
ADD_TYPED_SLICE_OP(string);
|
||||
ADD_TYPED_SLICE_V9_OP(uint8_t);
|
||||
ADD_TYPED_SLICE_V9_OP(uint16_t);
|
||||
ADD_TYPED_SLICE_V9_OP(uint32_t);
|
||||
ADD_TYPED_SLICE_V9_OP(uint64_t);
|
||||
ADD_TYPED_SLICE_V9_OP(int8_t);
|
||||
ADD_TYPED_SLICE_V9_OP(int16_t);
|
||||
ADD_TYPED_SLICE_V9_OP(int32_t);
|
||||
ADD_TYPED_SLICE_V9_OP(int64_t);
|
||||
ADD_TYPED_SLICE_V9_OP(float);
|
||||
ADD_TYPED_SLICE_V9_OP(double);
|
||||
ADD_TYPED_SLICE_V9_OP(MLFloat16);
|
||||
ADD_TYPED_SLICE_V9_OP(bool);
|
||||
ADD_TYPED_SLICE_V9_OP(string);
|
||||
|
||||
#ifndef DISABLE_CONTRIB_OPS
|
||||
namespace contrib {
|
||||
|
|
@ -57,6 +60,31 @@ ADD_TYPED_DYNAMIC_SLICE_OP(string);
|
|||
|
||||
} // namespace contrib
|
||||
#endif
|
||||
|
||||
#define ADD_TYPED_SLICE_V10_OP(data_type) \
|
||||
ONNX_CPU_OPERATOR_TYPED_KERNEL( \
|
||||
Slice, \
|
||||
10, \
|
||||
data_type, \
|
||||
KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType<data_type>()) \
|
||||
.TypeConstraint("Tind", {DataTypeImpl::GetTensorType<int32_t>(), \
|
||||
DataTypeImpl::GetTensorType<int64_t>()}), \
|
||||
Slice<data_type, true>);
|
||||
|
||||
ADD_TYPED_SLICE_V10_OP(uint8_t);
|
||||
ADD_TYPED_SLICE_V10_OP(uint16_t);
|
||||
ADD_TYPED_SLICE_V10_OP(uint32_t);
|
||||
ADD_TYPED_SLICE_V10_OP(uint64_t);
|
||||
ADD_TYPED_SLICE_V10_OP(int8_t);
|
||||
ADD_TYPED_SLICE_V10_OP(int16_t);
|
||||
ADD_TYPED_SLICE_V10_OP(int32_t);
|
||||
ADD_TYPED_SLICE_V10_OP(int64_t);
|
||||
ADD_TYPED_SLICE_V10_OP(float);
|
||||
ADD_TYPED_SLICE_V10_OP(double);
|
||||
ADD_TYPED_SLICE_V10_OP(MLFloat16);
|
||||
ADD_TYPED_SLICE_V10_OP(bool);
|
||||
ADD_TYPED_SLICE_V10_OP(string);
|
||||
|
||||
namespace {
|
||||
// std::clamp doesn't exist until C++17 so create a local version
|
||||
template <typename T>
|
||||
|
|
@ -67,6 +95,7 @@ const T& clamp(const T& v, const T& lo, const T& hi) {
|
|||
}
|
||||
} // namespace
|
||||
|
||||
// Slice V1-9 & DynamicSlice
|
||||
Status SliceBase::PrepareForCompute(const std::vector<int64_t>& raw_starts,
|
||||
const std::vector<int64_t>& raw_ends,
|
||||
const std::vector<int64_t>& raw_axes,
|
||||
|
|
@ -75,46 +104,138 @@ Status SliceBase::PrepareForCompute(const std::vector<int64_t>& raw_starts,
|
|||
std::vector<int64_t>& output_dims) const {
|
||||
// Initialize axes to the provided axes attribute or to the default sequence
|
||||
std::vector<int64_t> axes(raw_axes);
|
||||
if (axes.size() == 0) {
|
||||
if (axes.empty()) {
|
||||
//axes are omitted, they are set to[0, ..., ndim - 1]
|
||||
axes.resize(starts.size());
|
||||
std::iota(axes.begin(), axes.end(), 0);
|
||||
}
|
||||
|
||||
// Iterate through the provided axes and override the start/end ranges
|
||||
std::unordered_set<int64_t> unique_axes;
|
||||
const auto& dimension_count = input_dimensions.size();
|
||||
for (size_t axesIndex = 0; axesIndex < axes.size(); axesIndex++) {
|
||||
auto axis = axes[axesIndex] < 0 ? axes[axesIndex] + static_cast<int64_t>(dimension_count) : axes[axesIndex];
|
||||
for (size_t axis_index = 0, axes_count = axes.size(); axis_index < axes_count; ++axis_index) {
|
||||
auto axis = axes[axis_index] < 0 ? axes[axis_index] + static_cast<int64_t>(dimension_count) : axes[axis_index];
|
||||
if (axis >= static_cast<int64_t>(dimension_count) || axis < 0)
|
||||
return Status(ONNXRUNTIME, INVALID_ARGUMENT, "'axes' has an axis outside of the tensor dimension count");
|
||||
auto start = raw_starts[axesIndex];
|
||||
if (unique_axes.find(axis) != unique_axes.end())
|
||||
return Status(ONNXRUNTIME, INVALID_ARGUMENT, "'axes' has duplicates");
|
||||
unique_axes.insert(axis);
|
||||
|
||||
// process start
|
||||
auto start = raw_starts[axis_index];
|
||||
if (start < 0)
|
||||
start += input_dimensions[axis];
|
||||
starts[axis] = clamp(start, int64_t{0}, input_dimensions[axis]);
|
||||
|
||||
auto end = raw_ends[axesIndex];
|
||||
// process end
|
||||
auto end = raw_ends[axis_index];
|
||||
if (end < 0)
|
||||
end += input_dimensions[axis];
|
||||
output_dims[axis] = clamp(end, int64_t{0}, input_dimensions[axis]) - starts[axis];
|
||||
if (output_dims[axis] < 0)
|
||||
return Status(ONNXRUNTIME, INVALID_ARGUMENT, "'starts' and 'ends' values resulted in a negative dimension");
|
||||
|
||||
// find output dim value for this axis
|
||||
auto temp = clamp(end, int64_t{0}, input_dimensions[axis]) - starts[axis];
|
||||
if (temp < 0)
|
||||
output_dims[axis] = 0;
|
||||
else
|
||||
output_dims[axis] = temp;
|
||||
}
|
||||
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
// DynamicSlice & Slice V10
|
||||
Status SliceBase::PrepareForCompute(const std::vector<int64_t>& raw_starts,
|
||||
const std::vector<int64_t>& raw_ends,
|
||||
const std::vector<int64_t>& raw_axes,
|
||||
const std::vector<int64_t>& raw_steps,
|
||||
const std::vector<int64_t>& input_dimensions,
|
||||
std::vector<int64_t>& starts,
|
||||
std::vector<int64_t>& steps,
|
||||
std::vector<int64_t>& output_dims) const {
|
||||
// Initialize axes to the provided axes attribute or to the default sequence
|
||||
std::vector<int64_t> axes(raw_axes);
|
||||
if (axes.empty()) {
|
||||
// axes are omitted, they are set to[0, ..., ndim - 1]
|
||||
axes.resize(starts.size());
|
||||
std::iota(axes.begin(), axes.end(), 0);
|
||||
}
|
||||
|
||||
// Iterate through the provided axes and override the start/end/steps ranges
|
||||
std::unordered_set<int64_t> unique_axes;
|
||||
const auto& dimension_count = input_dimensions.size();
|
||||
for (size_t axis_index = 0, axes_count = axes.size(); axis_index < axes_count; ++axis_index) {
|
||||
auto axis = axes[axis_index] < 0 ? axes[axis_index] + static_cast<int64_t>(dimension_count) : axes[axis_index];
|
||||
if (axis >= static_cast<int64_t>(dimension_count) || axis < 0)
|
||||
return Status(ONNXRUNTIME, INVALID_ARGUMENT, "'axes' has an axis outside of the tensor dimension count");
|
||||
if (unique_axes.find(axis) != unique_axes.end())
|
||||
return Status(ONNXRUNTIME, INVALID_ARGUMENT, "'axes' has duplicates");
|
||||
unique_axes.insert(axis);
|
||||
|
||||
// process step
|
||||
auto step = axis_index < raw_steps.size() ? raw_steps[axis_index] : 1;
|
||||
if (step == 0)
|
||||
return Status(ONNXRUNTIME, INVALID_ARGUMENT, "'step' value cannot be 0");
|
||||
steps[axis] = step;
|
||||
|
||||
// process start
|
||||
auto start = raw_starts[axis_index];
|
||||
if (start < 0)
|
||||
start += input_dimensions[axis];
|
||||
if (step < 0)
|
||||
starts[axis] = clamp(start, int64_t{0}, input_dimensions[axis] - 1);
|
||||
else
|
||||
starts[axis] = clamp(start, int64_t{0}, input_dimensions[axis]);
|
||||
|
||||
// process end
|
||||
auto end = raw_ends[axis_index];
|
||||
// INT_MAX has a special meaning for end according to spec
|
||||
// equivalent to 'None' in numpy
|
||||
// it represent slicing to the end of the dimension
|
||||
if (end == std::numeric_limits<int32_t>::max() ||
|
||||
end == std::numeric_limits<int64_t>::max()) {
|
||||
end = step < 0 ? -1 : input_dimensions[axis];
|
||||
}
|
||||
|
||||
else {
|
||||
if (end < 0)
|
||||
end += input_dimensions[axis];
|
||||
if (step < 0)
|
||||
end = clamp(end, int64_t{-1}, input_dimensions[axis]);
|
||||
else
|
||||
end = clamp(end, int64_t{0}, input_dimensions[axis]);
|
||||
}
|
||||
|
||||
// find output dim value for this axis
|
||||
auto temp = static_cast<int64_t>(ceil(1.0 * (end - starts[axis]) / step));
|
||||
if (temp < 0)
|
||||
output_dims[axis] = 0;
|
||||
else
|
||||
output_dims[axis] = temp;
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
// Slice V10 & DynamicSlice
|
||||
void SliceBase::FillVectorsFromInput(const OpKernelContext* context,
|
||||
std::vector<int64_t>& input_starts,
|
||||
std::vector<int64_t>& input_ends,
|
||||
std::vector<int64_t>& input_axes) const {
|
||||
std::vector<int64_t>& input_axes,
|
||||
std::vector<int64_t>& input_steps) const {
|
||||
auto start_tensor = context->Input<Tensor>(1);
|
||||
auto ends_tensor = context->Input<Tensor>(2);
|
||||
auto axes_tensor = context->Input<Tensor>(3);
|
||||
const Tensor* axes_tensor = nullptr;
|
||||
if (context->InputCount() >= 4)
|
||||
axes_tensor = context->Input<Tensor>(3);
|
||||
// Slice V10 (optional input)
|
||||
const Tensor* steps_tensor = nullptr;
|
||||
if (context->InputCount() == 5)
|
||||
steps_tensor = context->Input<Tensor>(4);
|
||||
|
||||
ORT_ENFORCE(nullptr != start_tensor && start_tensor->Shape().NumDimensions() == 1, "Starts must be a 1-D array");
|
||||
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");
|
||||
|
||||
const auto& dtype = start_tensor->DataType();
|
||||
const auto& size = start_tensor->Shape().Size();
|
||||
|
|
@ -122,12 +243,18 @@ void SliceBase::FillVectorsFromInput(const OpKernelContext* context,
|
|||
input_ends.resize(size);
|
||||
if (nullptr != axes_tensor)
|
||||
input_axes.resize(size);
|
||||
// Slice V10
|
||||
if (nullptr != steps_tensor)
|
||||
input_steps.resize(size);
|
||||
|
||||
if (dtype == DataTypeImpl::GetType<int32_t>()) {
|
||||
std::copy(start_tensor->Data<int32_t>(), start_tensor->Data<int32_t>() + size, input_starts.begin());
|
||||
std::copy(ends_tensor->Data<int32_t>(), ends_tensor->Data<int32_t>() + size, input_ends.begin());
|
||||
if (nullptr != axes_tensor)
|
||||
std::copy(axes_tensor->Data<int32_t>(), axes_tensor->Data<int32_t>() + size, input_axes.begin());
|
||||
// Slice V10
|
||||
if (nullptr != steps_tensor)
|
||||
std::copy(steps_tensor->Data<int32_t>(), steps_tensor->Data<int32_t>() + size, input_steps.begin());
|
||||
}
|
||||
|
||||
else if (dtype == DataTypeImpl::GetType<int64_t>()) {
|
||||
|
|
@ -135,6 +262,9 @@ void SliceBase::FillVectorsFromInput(const OpKernelContext* context,
|
|||
std::copy(ends_tensor->Data<int64_t>(), ends_tensor->Data<int64_t>() + size, input_ends.begin());
|
||||
if (nullptr != axes_tensor)
|
||||
std::copy(axes_tensor->Data<int64_t>(), axes_tensor->Data<int64_t>() + size, input_axes.begin());
|
||||
// Slice V10
|
||||
if (nullptr != steps_tensor)
|
||||
std::copy(steps_tensor->Data<int64_t>(), steps_tensor->Data<int64_t>() + size, input_steps.begin());
|
||||
}
|
||||
|
||||
// should not reach this as no kernel is registered for this condition to be triggered - just an additional safety check
|
||||
|
|
@ -145,15 +275,21 @@ void SliceBase::FillVectorsFromInput(const OpKernelContext* context,
|
|||
|
||||
template <typename T>
|
||||
Status SliceImpl(OpKernelContext* ctx,
|
||||
const Tensor& input_tensor,
|
||||
const Tensor& input_tensor,
|
||||
std::vector<int64_t>& output_dims,
|
||||
const std::vector<int64_t>& starts) {
|
||||
const std::vector<int64_t>& starts,
|
||||
const std::vector<int64_t>& steps) {
|
||||
TensorShape output_shape(output_dims);
|
||||
auto& output_tensor = *ctx->Output(0, output_shape);
|
||||
|
||||
// output tensor's size is 0, nothing to fill - return
|
||||
if (output_shape.Size() == 0)
|
||||
return Status::OK();
|
||||
|
||||
auto* output = output_tensor.template MutableData<T>();
|
||||
const auto* output_end = output + output_tensor.Shape().Size();
|
||||
|
||||
SliceIterator<T> input_iterator(input_tensor, starts, output_tensor.Shape().GetDims());
|
||||
SliceIterator<T> input_iterator(input_tensor, starts, output_dims, steps);
|
||||
while (output != output_end)
|
||||
*output++ = *input_iterator++;
|
||||
|
||||
|
|
@ -166,21 +302,27 @@ Status Slice<T, dynamic>::Compute(OpKernelContext* ctx) const {
|
|||
ORT_ENFORCE(input_tensor_ptr != nullptr, "Missing input tensor to be processed");
|
||||
const auto& input_tensor = *input_tensor_ptr;
|
||||
const auto& input_dimensions = input_tensor.Shape().GetDims();
|
||||
if (input_dimensions.size() < 1)
|
||||
return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Cannot slice scalars");
|
||||
|
||||
// Initialize the starts & ends to the actual tensor shape
|
||||
std::vector<int64_t> starts(input_dimensions.size(), 0);
|
||||
std::vector<int64_t> steps(input_dimensions.size(), 1);
|
||||
std::vector<int64_t> output_dims(input_dimensions);
|
||||
|
||||
// Slice V10 & DynamicSlice
|
||||
if (dynamic) {
|
||||
std::vector<int64_t> input_starts, input_ends, input_axes;
|
||||
FillVectorsFromInput(ctx, input_starts, input_ends, input_axes);
|
||||
ORT_RETURN_IF_ERROR(PrepareForCompute(input_starts, input_ends, input_axes,
|
||||
input_dimensions, starts, output_dims));
|
||||
} else {
|
||||
std::vector<int64_t> input_starts, input_ends, input_axes, input_steps;
|
||||
FillVectorsFromInput(ctx, input_starts, input_ends, input_axes, input_steps);
|
||||
ORT_RETURN_IF_ERROR(PrepareForCompute(input_starts, input_ends, input_axes, input_steps,
|
||||
input_dimensions, starts, steps, output_dims));
|
||||
}
|
||||
// Slice V1-9
|
||||
else {
|
||||
ORT_RETURN_IF_ERROR(PrepareForCompute(attr_starts_, attr_ends_, attr_axes_,
|
||||
input_dimensions, starts, output_dims));
|
||||
}
|
||||
|
||||
return SliceImpl<T>(ctx, input_tensor, output_dims, starts);
|
||||
return SliceImpl<T>(ctx, input_tensor, output_dims, starts, steps);
|
||||
}
|
||||
} // namespace onnxruntime
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ class SliceBase {
|
|||
}
|
||||
}
|
||||
|
||||
// compute output_dims without steps (Slice V1-9 & DynamicSlice)
|
||||
Status PrepareForCompute(const std::vector<int64_t>& raw_starts,
|
||||
const std::vector<int64_t>& raw_ends,
|
||||
const std::vector<int64_t>& raw_axes,
|
||||
|
|
@ -28,10 +29,22 @@ class SliceBase {
|
|||
std::vector<int64_t>& starts,
|
||||
std::vector<int64_t>& output_dims) const;
|
||||
|
||||
// compute output_dims with steps (Slice V10)
|
||||
Status PrepareForCompute(const std::vector<int64_t>& raw_starts,
|
||||
const std::vector<int64_t>& raw_ends,
|
||||
const std::vector<int64_t>& raw_axes,
|
||||
const std::vector<int64_t>& raw_steps,
|
||||
const std::vector<int64_t>& input_dimensions,
|
||||
std::vector<int64_t>& starts,
|
||||
std::vector<int64_t>& steps,
|
||||
std::vector<int64_t>& output_dims) const;
|
||||
|
||||
// Slice V10 & DynamicSlice
|
||||
void FillVectorsFromInput(const OpKernelContext* context,
|
||||
std::vector<int64_t>& raw_starts,
|
||||
std::vector<int64_t>& raw_ends,
|
||||
std::vector<int64_t>& raw_axes) const;
|
||||
std::vector<int64_t>& input_starts,
|
||||
std::vector<int64_t>& input_ends,
|
||||
std::vector<int64_t>& input_axes,
|
||||
std::vector<int64_t>& input_steps) const;
|
||||
|
||||
std::vector<int64_t> attr_starts_, attr_ends_, attr_axes_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -119,47 +119,70 @@ struct ExtentAxisCounters {
|
|||
gsl::span<const int64_t> extents_; // The extents of each axis
|
||||
};
|
||||
|
||||
// A std::vector that holds the number of entries to skip to go to the next axis start given an extent in each axis
|
||||
// A std::vector that holds the number of entries to skip to go to the next axis start given an extent
|
||||
// and optionally steps along each axis:
|
||||
// This is used by the SliceIterator to iterate over a slice of a tensor
|
||||
struct SliceSkips : std::vector<int64_t> {
|
||||
SliceSkips(const TensorShape& input_shape, gsl::span<const int64_t> extents)
|
||||
: std::vector<int64_t>(input_shape.NumDimensions(), 0) {
|
||||
SliceSkips(const TensorShape& input_shape, gsl::span<const int64_t> extents, gsl::span<const int64_t> steps)
|
||||
: std::vector<int64_t>(input_shape.NumDimensions(), 0) {
|
||||
auto& dims = input_shape.GetDims();
|
||||
ORT_ENFORCE(static_cast<ptrdiff_t>(dims.size()) == extents.size());
|
||||
size_t pitch = dims.back();
|
||||
back() = pitch - extents[size() - 1];
|
||||
for (size_t i = size() - 1; i-- > 0;) {
|
||||
ORT_ENFORCE(static_cast<ptrdiff_t>(dims.size()) == extents.size() &&
|
||||
static_cast<ptrdiff_t>(dims.size()) >= steps.size());
|
||||
|
||||
int64_t inner_most_dim = dims.size() - 1;
|
||||
// assume step == 1 if not present
|
||||
ptrdiff_t steps_size = steps.size();
|
||||
int64_t steps_i = 1;
|
||||
if (inner_most_dim >= 0 && static_cast<ptrdiff_t>(inner_most_dim) < steps_size)
|
||||
steps_i = steps[inner_most_dim];
|
||||
|
||||
size_t pitch = 1;
|
||||
for (size_t i = size(); i-- > 0;) {
|
||||
auto prevPitch = pitch;
|
||||
pitch *= dims[i];
|
||||
operator[](i) = pitch - prevPitch * extents[i];
|
||||
|
||||
// assume step == 1 if not present
|
||||
int64_t steps_i_minus_1 = 1;
|
||||
if (i > 0 && static_cast<ptrdiff_t>(i) - 1 < steps_size)
|
||||
steps_i_minus_1 = steps[i - 1];
|
||||
|
||||
// first "revert" back to the old starting position (term with -ve sign)
|
||||
// and then "step" over the pitch accordingly (term with +ve sign)
|
||||
operator[](i) = steps_i_minus_1 * pitch - steps_i * extents[i] * prevPitch;
|
||||
|
||||
steps_i = steps_i_minus_1;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// This provides easy sequential iteration over a subset of a tensor given a span of starts & extents
|
||||
// This provides easy sequential iteration over a subset of a tensor given a span of starts, extents & optionally steps
|
||||
template <typename T>
|
||||
struct SliceIterator {
|
||||
SliceIterator(const Tensor& tensor, gsl::span<const int64_t> starts, gsl::span<const int64_t> extents)
|
||||
: tensor_(tensor), extents_(extents), skips_(tensor_.Shape(), extents), indices_(extents.size(), 0) {
|
||||
SliceIterator(const Tensor& tensor, gsl::span<const int64_t> starts,
|
||||
gsl::span<const int64_t> extents, gsl::span<const int64_t> steps)
|
||||
: tensor_(tensor), extents_(extents), skips_(tensor_.Shape(), extents, steps), indices_(extents.size(), 0) {
|
||||
auto& dims = tensor_.Shape().GetDims();
|
||||
|
||||
Init(dims, starts);
|
||||
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).
|
||||
SliceIterator(const Tensor& tensor, const TensorShape& tensor_shape, gsl::span<const int64_t> starts, gsl::span<const int64_t> extents)
|
||||
: tensor_(tensor), extents_(extents), skips_(tensor_shape, extents), indices_(extents.size(), 0) {
|
||||
// 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
|
||||
SliceIterator(const 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), extents_(extents), skips_(tensor_shape, extents, steps), indices_(extents.size(), 0) {
|
||||
auto& dims = tensor_shape.GetDims();
|
||||
|
||||
Init(dims, starts);
|
||||
Init(dims, starts, steps);
|
||||
}
|
||||
|
||||
// Initialize initial skip and inner_extent.
|
||||
void Init(const std::vector<int64_t>& dims, gsl::span<const int64_t> starts) {
|
||||
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() && static_cast<ptrdiff_t>(dims.size()) == extents_.size());
|
||||
ORT_ENFORCE(static_cast<ptrdiff_t>(dims.size()) == starts.size() &&
|
||||
static_cast<ptrdiff_t>(dims.size()) == extents_.size() &&
|
||||
static_cast<ptrdiff_t>(dims.size()) >= steps.size());
|
||||
|
||||
size_t pitch = 1;
|
||||
// Initial skip, so that input_ points to the first element to copy
|
||||
|
|
@ -169,6 +192,8 @@ struct SliceIterator {
|
|||
}
|
||||
|
||||
inner_extent_ = extents_[dims.size() - 1];
|
||||
inner_step_ = static_cast<ptrdiff_t>(dims.size()) == steps.size()
|
||||
? steps[dims.size() - 1] : 1;
|
||||
}
|
||||
|
||||
void AdvanceOverInnerExtent() {
|
||||
|
|
@ -181,7 +206,8 @@ struct SliceIterator {
|
|||
}
|
||||
|
||||
const T* operator++(int) {
|
||||
const T* input = input_++;
|
||||
const T* input = input_;
|
||||
input_ += inner_step_;
|
||||
if (++inner_counter_ == inner_extent_) {
|
||||
inner_counter_ = 0;
|
||||
AdvanceOverInnerExtent();
|
||||
|
|
@ -189,7 +215,13 @@ struct SliceIterator {
|
|||
return input;
|
||||
}
|
||||
|
||||
T* CopyInnermostAxis(T* output) {
|
||||
// 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_;
|
||||
|
|
@ -197,11 +229,20 @@ struct SliceIterator {
|
|||
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:
|
||||
const Tensor& tensor_;
|
||||
const T* input_{tensor_.template Data<T>()};
|
||||
gsl::span<const int64_t> extents_;
|
||||
size_t inner_counter_{}, inner_extent_;
|
||||
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
|
||||
};
|
||||
|
|
@ -221,4 +262,4 @@ inline void CopyCpuTensor(const Tensor* src, Tensor* tgt) {
|
|||
}
|
||||
}
|
||||
|
||||
} // namespace onnxruntime
|
||||
} // namespace onnxruntime
|
||||
|
|
@ -492,8 +492,8 @@ class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain,
|
|||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 7, float, LSTM);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 7, double, LSTM);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 7, MLFloat16, LSTM);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 1, int32_t, Slice);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 1, int64_t, Slice);
|
||||
class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 1, 9, int32_t, Slice);
|
||||
class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 1, 9, int64_t, Slice);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 1, int32_t, DynamicSlice);
|
||||
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 1, int64_t, DynamicSlice);
|
||||
class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 9, Compress);
|
||||
|
|
@ -756,8 +756,8 @@ static void RegisterCudaKernels(KernelRegistry& kernel_registry) {
|
|||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 7, float, LSTM)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 7, double, LSTM)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 7, MLFloat16, LSTM)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 1, int32_t, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 1, int64_t, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 1, 9, int32_t, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 1, 9, int64_t, Slice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 1, int32_t, DynamicSlice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 1, int64_t, DynamicSlice)>());
|
||||
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 9, Compress)>());
|
||||
|
|
|
|||
|
|
@ -7,10 +7,26 @@
|
|||
|
||||
namespace onnxruntime {
|
||||
namespace cuda {
|
||||
#define REGISTER_VERSIONED_TYPED_SLICE(TIND) \
|
||||
ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_EX( \
|
||||
Slice, \
|
||||
kOnnxDomain, \
|
||||
1, 9, \
|
||||
TIND, \
|
||||
kCudaExecutionProvider, \
|
||||
KernelDefBuilder().InputMemoryType<OrtMemTypeCPUInput>(1). \
|
||||
InputMemoryType<OrtMemTypeCPUInput>(2). \
|
||||
InputMemoryType<OrtMemTypeCPUInput>(3). \
|
||||
TypeConstraint("T", DataTypeImpl::AllFixedSizeTensorTypes()). \
|
||||
TypeConstraint("Tind", DataTypeImpl::GetTensorType<TIND>()), \
|
||||
Slice<TIND,false>);
|
||||
|
||||
#define REGISTER_TYPED_SLICE(NAME, TIND, DYNAMIC) \
|
||||
REGISTER_VERSIONED_TYPED_SLICE(int32_t)
|
||||
REGISTER_VERSIONED_TYPED_SLICE(int64_t)
|
||||
|
||||
#define REGISTER_TYPED_DYNAMICSLICE(TIND) \
|
||||
ONNX_OPERATOR_TYPED_KERNEL_EX( \
|
||||
NAME, \
|
||||
DynamicSlice, \
|
||||
kOnnxDomain, \
|
||||
1, \
|
||||
TIND, \
|
||||
|
|
@ -20,12 +36,10 @@ namespace cuda {
|
|||
InputMemoryType<OrtMemTypeCPUInput>(3). \
|
||||
TypeConstraint("T", DataTypeImpl::AllFixedSizeTensorTypes()). \
|
||||
TypeConstraint("Tind", DataTypeImpl::GetTensorType<TIND>()), \
|
||||
Slice<TIND,DYNAMIC>);
|
||||
Slice<TIND,true>);
|
||||
|
||||
REGISTER_TYPED_SLICE(Slice, int32_t, false)
|
||||
REGISTER_TYPED_SLICE(Slice, int64_t, false)
|
||||
REGISTER_TYPED_SLICE(DynamicSlice, int32_t, true )
|
||||
REGISTER_TYPED_SLICE(DynamicSlice, int64_t, true )
|
||||
REGISTER_TYPED_DYNAMICSLICE(int32_t)
|
||||
REGISTER_TYPED_DYNAMICSLICE(int64_t)
|
||||
|
||||
template<typename Tind, bool dynamic>
|
||||
Status Slice<Tind, dynamic>::ComputeInternal(OpKernelContext* ctx) const {
|
||||
|
|
@ -36,13 +50,14 @@ Status Slice<Tind, dynamic>::ComputeInternal(OpKernelContext* ctx) const {
|
|||
// Initialize the starts & ends to the actual tensor shape
|
||||
const size_t dimension_count = input_dimensions.size();
|
||||
std::vector<int64_t> starts(dimension_count, 0);
|
||||
std::vector<int64_t> steps(input_dimensions.size(), 1);
|
||||
std::vector<int64_t> output_dims(input_dimensions);
|
||||
|
||||
if (dynamic) {
|
||||
std::vector<int64_t> input_starts, input_ends, input_axes;
|
||||
FillVectorsFromInput(ctx, input_starts, input_ends, input_axes);
|
||||
std::vector<int64_t> input_starts, input_ends, input_axes, input_steps;
|
||||
FillVectorsFromInput(ctx, input_starts, input_ends, input_axes, input_steps);
|
||||
ORT_RETURN_IF_ERROR(PrepareForCompute(input_starts, input_ends, input_axes,
|
||||
input_dimensions, starts, output_dims));
|
||||
input_steps, input_dimensions, starts, steps, output_dims));
|
||||
|
||||
} else {
|
||||
ORT_RETURN_IF_ERROR(PrepareForCompute(attr_starts_, attr_ends_, attr_axes_,
|
||||
|
|
|
|||
|
|
@ -7,156 +7,505 @@
|
|||
namespace onnxruntime {
|
||||
namespace test {
|
||||
|
||||
TEST(SliceTest, Slice1D) {
|
||||
OpTester test("Slice");
|
||||
template <typename T>
|
||||
void RunSliceTest(const std::vector<int64_t>& input_dims,
|
||||
const std::vector<T>& input_vals,
|
||||
const std::vector<int64_t>& starts,
|
||||
const std::vector<int64_t>& ends,
|
||||
const std::vector<int64_t>& axes,
|
||||
const std::vector<int64_t>& steps,
|
||||
const std::vector<int64_t>& output_dims,
|
||||
const std::vector<T>& output_vals,
|
||||
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<T>("data", input_dims, input_vals);
|
||||
testv9.AddOutput<T>("output", output_dims, output_vals);
|
||||
testv9.Run();
|
||||
}
|
||||
|
||||
test.AddAttribute("axes", std::vector<int64_t>{0});
|
||||
test.AddAttribute("starts", std::vector<int64_t>{2});
|
||||
test.AddAttribute("ends", std::vector<int64_t>{4});
|
||||
// V10
|
||||
OpTester testv10("Slice", 10);
|
||||
testv10.AddInput<T>("data", input_dims, input_vals);
|
||||
testv10.AddInput<int64_t>("starts", {static_cast<int64_t>(starts.size())}, starts);
|
||||
testv10.AddInput<int64_t>("ends", {static_cast<int64_t>(ends.size())}, ends);
|
||||
if (axes.size() != 0)
|
||||
testv10.AddInput<int64_t>("axes", {static_cast<int64_t>(axes.size())}, axes);
|
||||
if (steps.size() != 0)
|
||||
testv10.AddInput<int64_t>("steps", {static_cast<int64_t>(steps.size())}, steps);
|
||||
testv10.AddOutput<T>("output", output_dims, output_vals);
|
||||
testv10.Run();
|
||||
}
|
||||
|
||||
test.AddInput<float>("data", {6}, {0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f});
|
||||
test.AddOutput<float>("output", {2}, {2.0f, 3.0f});
|
||||
test.Run();
|
||||
// Slice V1-9 & Slice V10 can both run the following tests
|
||||
TEST(SliceTest, Slice1D_InvalidStartEndRange) {
|
||||
RunSliceTest<float>({6},
|
||||
{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f},
|
||||
{3},
|
||||
{2},
|
||||
{0},
|
||||
{},
|
||||
{0},
|
||||
{});
|
||||
}
|
||||
|
||||
TEST(SliceTest, Slice1D_ValidStartEndRange_NoOutput) {
|
||||
RunSliceTest<float>({6},
|
||||
{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f},
|
||||
{2},
|
||||
{2},
|
||||
{0},
|
||||
{},
|
||||
{0},
|
||||
{});
|
||||
}
|
||||
|
||||
TEST(SliceTest, Slice1D_Regular) {
|
||||
RunSliceTest<float>
|
||||
({6},
|
||||
{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f},
|
||||
{2},
|
||||
{4},
|
||||
{0},
|
||||
{},
|
||||
{2},
|
||||
{2.0f, 3.0f});
|
||||
}
|
||||
|
||||
TEST(SliceTest, Slice1D_Perf) {
|
||||
OpTester test("Slice");
|
||||
|
||||
test.AddAttribute("axes", std::vector<int64_t>{0});
|
||||
test.AddAttribute("starts", std::vector<int64_t>{2});
|
||||
test.AddAttribute("ends", std::vector<int64_t>{502});
|
||||
|
||||
std::vector<float> input(1000, 2.0f);
|
||||
std::vector<float> output(500, 2.0f);
|
||||
test.AddInput<float>("data", {1000}, input);
|
||||
test.AddOutput<float>("output", {500}, output);
|
||||
test.Run();
|
||||
RunSliceTest<float>({1000},
|
||||
input,
|
||||
{2},
|
||||
{502},
|
||||
{0},
|
||||
{},
|
||||
{500},
|
||||
output);
|
||||
}
|
||||
|
||||
TEST(SliceTest, Slice2D_OutOfBounds) {
|
||||
OpTester test("Slice");
|
||||
TEST(SliceTest, Slice1D_EndOutOfBounds) {
|
||||
RunSliceTest<float>({6},
|
||||
{1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f},
|
||||
{0},
|
||||
{10},
|
||||
{},
|
||||
{},
|
||||
{6},
|
||||
{1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f});
|
||||
}
|
||||
|
||||
test.AddAttribute("axes", std::vector<int64_t>{0, 1});
|
||||
test.AddAttribute("starts", std::vector<int64_t>{0, 1000});
|
||||
test.AddAttribute("ends", std::vector<int64_t>{10, 1000});
|
||||
TEST(SliceTest, Slice1D_StartAndEndOutOfBounds) {
|
||||
RunSliceTest<float>({6},
|
||||
{1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f},
|
||||
{1000},
|
||||
{1001},
|
||||
{},
|
||||
{},
|
||||
{0},
|
||||
{});
|
||||
}
|
||||
|
||||
test.AddInput<float>("data", {2, 3}, {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f});
|
||||
test.AddOutput<float>("output", {2, 0}, {});
|
||||
test.Run();
|
||||
TEST(SliceTest, Slice2D_StartAndEndOutOfBounds) {
|
||||
RunSliceTest<float>({2, 3},
|
||||
{1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f},
|
||||
{0, 1000},
|
||||
{10, 1000},
|
||||
{0, 1},
|
||||
{},
|
||||
{2, 0},
|
||||
{});
|
||||
}
|
||||
|
||||
TEST(SliceTest, Slice2D_OneAxis) {
|
||||
OpTester test("Slice");
|
||||
|
||||
test.AddAttribute("axes", std::vector<int64_t>{0});
|
||||
test.AddAttribute("starts", std::vector<int64_t>{1});
|
||||
test.AddAttribute("ends", std::vector<int64_t>{3});
|
||||
|
||||
test.AddInput<float>("data", {6, 4},
|
||||
{00.0f, 01.0f, 02.0f, 03.0f,
|
||||
10.0f, 11.0f, 12.0f, 13.0f,
|
||||
20.0f, 21.0f, 22.0f, 23.0f,
|
||||
30.0f, 31.0f, 32.0f, 33.0f,
|
||||
40.0f, 41.0f, 42.0f, 43.0f,
|
||||
50.0f, 51.0f, 52.0f, 53.0f});
|
||||
test.AddOutput<float>("output", {2, 4},
|
||||
{10.0f, 11.0f, 12.0f, 13.0f,
|
||||
20.0f, 21.0f, 22.0f, 23.0f});
|
||||
test.Run();
|
||||
RunSliceTest<float>({6, 4},
|
||||
{00.0f, 01.0f, 02.0f, 03.0f,
|
||||
10.0f, 11.0f, 12.0f, 13.0f,
|
||||
20.0f, 21.0f, 22.0f, 23.0f,
|
||||
30.0f, 31.0f, 32.0f, 33.0f,
|
||||
40.0f, 41.0f, 42.0f, 43.0f,
|
||||
50.0f, 51.0f, 52.0f, 53.0f},
|
||||
{1},
|
||||
{3},
|
||||
{0},
|
||||
{},
|
||||
{2, 4},
|
||||
{10.0f, 11.0f, 12.0f, 13.0f,
|
||||
20.0f, 21.0f, 22.0f, 23.0f});
|
||||
}
|
||||
|
||||
TEST(SliceTest, Slice2D_TwoAxes) {
|
||||
OpTester test("Slice");
|
||||
|
||||
test.AddAttribute("axes", std::vector<int64_t>{1, 0});
|
||||
test.AddAttribute("starts", std::vector<int64_t>{2, 3});
|
||||
test.AddAttribute("ends", std::vector<int64_t>{1000, -1});
|
||||
|
||||
test.AddInput<float>("data", {6, 4},
|
||||
{00.0f, 01.0f, 02.0f, 03.0f,
|
||||
10.0f, 11.0f, 12.0f, 13.0f,
|
||||
20.0f, 21.0f, 22.0f, 23.0f,
|
||||
30.0f, 31.0f, 32.0f, 33.0f,
|
||||
40.0f, 41.0f, 42.0f, 43.0f,
|
||||
50.0f, 51.0f, 52.0f, 53.0f});
|
||||
test.AddOutput<float>("output", {2, 2},
|
||||
{32.0f, 33.0f,
|
||||
42.0f, 43.0f});
|
||||
test.Run();
|
||||
RunSliceTest<float>({6, 4},
|
||||
{00.0f, 01.0f, 02.0f, 03.0f,
|
||||
10.0f, 11.0f, 12.0f, 13.0f,
|
||||
20.0f, 21.0f, 22.0f, 23.0f,
|
||||
30.0f, 31.0f, 32.0f, 33.0f,
|
||||
40.0f, 41.0f, 42.0f, 43.0f,
|
||||
50.0f, 51.0f, 52.0f, 53.0f},
|
||||
{2, 3},
|
||||
{1000 ,-1},
|
||||
{1, 0},
|
||||
{},
|
||||
{2, 2},
|
||||
{32.0f, 33.0f,
|
||||
42.0f, 43.0f});
|
||||
}
|
||||
|
||||
TEST(SliceTest, Slice2D_TwoAxesEque) {
|
||||
OpTester test("Slice");
|
||||
|
||||
test.AddAttribute("axes", std::vector<int64_t>{1, 0});
|
||||
test.AddAttribute("starts", std::vector<int64_t>{2, 3});
|
||||
test.AddAttribute("ends", std::vector<int64_t>{1000, 3});
|
||||
|
||||
test.AddInput<float>("data", {6, 4},
|
||||
{00.0f, 01.0f, 02.0f, 03.0f,
|
||||
10.0f, 11.0f, 12.0f, 13.0f,
|
||||
20.0f, 21.0f, 22.0f, 23.0f,
|
||||
30.0f, 31.0f, 32.0f, 33.0f,
|
||||
40.0f, 41.0f, 42.0f, 43.0f,
|
||||
50.0f, 51.0f, 52.0f, 53.0f});
|
||||
test.AddOutput<float>("output", {0, 2},
|
||||
{});
|
||||
test.Run();
|
||||
RunSliceTest<float>({6, 4},
|
||||
{00.0f, 01.0f, 02.0f, 03.0f,
|
||||
10.0f, 11.0f, 12.0f, 13.0f,
|
||||
20.0f, 21.0f, 22.0f, 23.0f,
|
||||
30.0f, 31.0f, 32.0f, 33.0f,
|
||||
40.0f, 41.0f, 42.0f, 43.0f,
|
||||
50.0f, 51.0f, 52.0f, 53.0f},
|
||||
{2, 3},
|
||||
{1000, 3},
|
||||
{1, 0},
|
||||
{},
|
||||
{0, 2},
|
||||
{});
|
||||
}
|
||||
|
||||
TEST(SliceTest, Slice3D) {
|
||||
OpTester test("Slice");
|
||||
RunSliceTest<float>({3, 3, 3},
|
||||
{111.0f, 112.0f, 113.0f,
|
||||
121.0f, 122.0f, 123.0f,
|
||||
131.0f, 132.0f, 133.0f,
|
||||
|
||||
test.AddAttribute("starts", std::vector<int64_t>{0, 1, 1});
|
||||
test.AddAttribute("ends", std::vector<int64_t>{1000, 1000, 1000});
|
||||
211.0f, 212.0f, 213.0f,
|
||||
221.0f, 222.0f, 223.0f,
|
||||
231.0f, 232.0f, 233.0f,
|
||||
|
||||
test.AddInput<float>("data", {3, 3, 3},
|
||||
{111.0f, 112.0f, 113.0f,
|
||||
121.0f, 122.0f, 123.0f,
|
||||
131.0f, 132.0f, 133.0f,
|
||||
311.0f, 312.0f, 313.0f,
|
||||
321.0f, 322.0f, 323.0f,
|
||||
331.0f, 332.0f, 333.0f},
|
||||
{0, 1, 1},
|
||||
{1000, 1000, 1000},
|
||||
{},
|
||||
{},
|
||||
{3, 2, 2},
|
||||
{122.0f, 123.0f,
|
||||
132.0f, 133.0f,
|
||||
|
||||
211.0f, 212.0f, 213.0f,
|
||||
221.0f, 222.0f, 223.0f,
|
||||
231.0f, 232.0f, 233.0f,
|
||||
222.0f, 223.0f,
|
||||
232.0f, 233.0f,
|
||||
|
||||
311.0f, 312.0f, 313.0f,
|
||||
321.0f, 322.0f, 323.0f,
|
||||
331.0f, 332.0f, 333.0f});
|
||||
test.AddOutput<float>("output", {3, 2, 2},
|
||||
{122.0f, 123.0f,
|
||||
132.0f, 133.0f,
|
||||
|
||||
222.0f, 223.0f,
|
||||
232.0f, 233.0f,
|
||||
|
||||
322.0f, 323.0f,
|
||||
332.0f, 333.0f});
|
||||
test.Run();
|
||||
322.0f, 323.0f,
|
||||
332.0f, 333.0f});
|
||||
}
|
||||
|
||||
TEST(SliceTest, Slice1D_Int) {
|
||||
OpTester test("Slice");
|
||||
|
||||
test.AddAttribute("axes", std::vector<int64_t>{0});
|
||||
test.AddAttribute("starts", std::vector<int64_t>{2});
|
||||
test.AddAttribute("ends", std::vector<int64_t>{4});
|
||||
|
||||
test.AddInput<int32_t>("data", {6}, {0L, 1L, 2L, 3L, 4L, 5L});
|
||||
test.AddOutput<int32_t>("output", {2}, {2L, 3L});
|
||||
test.Run();
|
||||
RunSliceTest<int32_t>({6},
|
||||
{0L, 1L, 2L, 3L, 4L, 5L},
|
||||
{2},
|
||||
{4},
|
||||
{0},
|
||||
{},
|
||||
{2},
|
||||
{2L, 3L});
|
||||
}
|
||||
|
||||
TEST(SliceTest, Slice1D_String) {
|
||||
OpTester test("Slice");
|
||||
|
||||
test.AddAttribute("axes", std::vector<int64_t>{0});
|
||||
test.AddAttribute("starts", std::vector<int64_t>{2});
|
||||
test.AddAttribute("ends", std::vector<int64_t>{4});
|
||||
|
||||
test.AddInput<std::string>("data", {6}, {"0", "1", "2", "3", "4", "5"});
|
||||
test.AddOutput<std::string>("output", {2}, {"2", "3"});
|
||||
test.Run();
|
||||
RunSliceTest<std::string>({6},
|
||||
{"0", "1", "2", "3", "4", "5"},
|
||||
{2},
|
||||
{4},
|
||||
{0},
|
||||
{},
|
||||
{2},
|
||||
{"2", "3"});
|
||||
}
|
||||
|
||||
} // namespace Test
|
||||
// Only Slice V10 can run the following tests
|
||||
TEST(SliceTest, Slice1D_WithPositiveSteps) {
|
||||
RunSliceTest<float>({6},
|
||||
{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f},
|
||||
{0},
|
||||
{6},
|
||||
{0},
|
||||
{2},
|
||||
{3},
|
||||
{0.0f, 2.0f, 4.0f},
|
||||
true);
|
||||
}
|
||||
|
||||
// In numpy:
|
||||
// x = np.array([1, 2, 3, 4])
|
||||
// y = x[-1:-4:-1]
|
||||
TEST(SliceTest, Slice1D_WithNegativeSteps_Regular) {
|
||||
RunSliceTest<float>({4},
|
||||
{1.0f, 2.0f, 3.0f, 4.0f},
|
||||
{-1},
|
||||
{-4},
|
||||
{0},
|
||||
{-1},
|
||||
{3},
|
||||
{4.0f, 3.0f, 2.0f},
|
||||
true);
|
||||
}
|
||||
|
||||
TEST(SliceTest, Slice1D_WithNegativeSteps_EndOutOfBounds_1) {
|
||||
RunSliceTest<float>({6},
|
||||
{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f},
|
||||
{0},
|
||||
{6},
|
||||
{0},
|
||||
{-1},
|
||||
{0},
|
||||
{},
|
||||
true);
|
||||
}
|
||||
|
||||
TEST(SliceTest, Slice1D_WithNegativeSteps_EndOutOfBounds_2) {
|
||||
RunSliceTest<float>({6},
|
||||
{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f},
|
||||
{0},
|
||||
{-10},
|
||||
{0},
|
||||
{-1},
|
||||
{1},
|
||||
{0.0f},
|
||||
true);
|
||||
}
|
||||
|
||||
TEST(SliceTest, Slice1D_WithNegativeSteps_ValidStartEndRange) {
|
||||
RunSliceTest<float>({6},
|
||||
{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f},
|
||||
{5},
|
||||
{0},
|
||||
{0},
|
||||
{-1},
|
||||
{5},
|
||||
{5.0f, 4.0f, 3.0f, 2.0f, 1.0f},
|
||||
true);
|
||||
}
|
||||
|
||||
|
||||
TEST(SliceTest, Slice1D_WithNegativeSteps_StartOutOfBounds) {
|
||||
RunSliceTest<float>({6},
|
||||
{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f},
|
||||
{7},
|
||||
{0},
|
||||
{0},
|
||||
{-3},
|
||||
{2},
|
||||
{5.0f, 2.0f},
|
||||
true);
|
||||
}
|
||||
|
||||
TEST(SliceTest, Slice2D_WithPositiveSteps_1) {
|
||||
RunSliceTest<float>({2, 4},
|
||||
{1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f},
|
||||
{1, 0},
|
||||
{2, 3},
|
||||
{0, 1},
|
||||
{1, 2},
|
||||
{1, 2},
|
||||
{5.0f, 7.0f},
|
||||
true);
|
||||
}
|
||||
|
||||
TEST(SliceTest, Slice2D_WithPositiveSteps_2) {
|
||||
RunSliceTest<float>({2, 4},
|
||||
{1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f},
|
||||
{0, 1},
|
||||
{-1, 1000},
|
||||
{}, // default axes
|
||||
{}, // default steps
|
||||
{1, 3},
|
||||
{2.0f, 3.0f, 4.0f},
|
||||
true);
|
||||
}
|
||||
|
||||
TEST(SliceTest, Slice2D_WithNegativeSteps_1) {
|
||||
RunSliceTest<float>({2, 4},
|
||||
{1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f},
|
||||
{1, 0},
|
||||
{2, 3},
|
||||
{0, 1},
|
||||
{-1, -2},
|
||||
{0, 0},
|
||||
{},
|
||||
true);
|
||||
}
|
||||
|
||||
TEST(SliceTest, Slice2D_WithNegativeSteps_2) {
|
||||
RunSliceTest<float>({2, 4},
|
||||
{1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f},
|
||||
{1, 3},
|
||||
{0, 1},
|
||||
{0, 1},
|
||||
{-1, -2},
|
||||
{1, 1},
|
||||
{8.0f},
|
||||
true);
|
||||
}
|
||||
|
||||
TEST(SliceTest, Slice3D_WithPositiveSteps_AllAxes) {
|
||||
RunSliceTest<int32_t>({3, 3, 3},
|
||||
{27, 20, 2,
|
||||
4, 26, 11,
|
||||
26, 5, 17,
|
||||
|
||||
0, 21, 6,
|
||||
22, 13, 29,
|
||||
19, 17, 27,
|
||||
|
||||
4, 20, 12,
|
||||
3, 9, 24,
|
||||
17, 6, 24},
|
||||
{0, 1, 1},
|
||||
{1000, 1000, 1000},
|
||||
{0, 1, 2},
|
||||
{2, 2, 2},
|
||||
{2, 1, 1},
|
||||
{26, 9},
|
||||
true);
|
||||
}
|
||||
|
||||
TEST(SliceTest, Slice3D_WithPositiveAndNegativeSteps_SubsetOfAxes_1) {
|
||||
RunSliceTest<int32_t>({3, 3, 3},
|
||||
{27, 20, 2,
|
||||
4, 26, 11,
|
||||
26, 5, 17,
|
||||
|
||||
0, 21, 6,
|
||||
22, 13, 29,
|
||||
19, 17, 27,
|
||||
|
||||
4, 20, 12,
|
||||
3, 9, 24,
|
||||
17, 6, 24},
|
||||
{1, 4},
|
||||
{1000, 1},
|
||||
{1, 2},
|
||||
{3, -2},
|
||||
{3, 1, 1},
|
||||
{11, 29, 24},
|
||||
true);
|
||||
}
|
||||
|
||||
TEST(SliceTest, Slice3D_WithPositiveAndNegativeSteps_SubsetOfAxes_2) {
|
||||
RunSliceTest<int32_t>({3, 3, 3},
|
||||
{27, 20, 2,
|
||||
4, 26, 11,
|
||||
26, 5, 17,
|
||||
|
||||
0, 21, 6,
|
||||
22, 13, 29,
|
||||
19, 17, 27,
|
||||
|
||||
4, 20, 12,
|
||||
3, 9, 24,
|
||||
17, 6, 24},
|
||||
{1, 4},
|
||||
{1000, 2},
|
||||
{1, 2},
|
||||
{3, -2},
|
||||
{3, 1, 0},
|
||||
{},
|
||||
true);
|
||||
}
|
||||
|
||||
// Slice for Reversing
|
||||
// With numeric_limit_max, it means slice to the end of a dimension
|
||||
// (whichever direction we are stepping)
|
||||
TEST(SliceTest, Slice1D_ReverseAllAxes_1) {
|
||||
RunSliceTest<float>({4},
|
||||
{1.0f, 2.0f, 3.0f, 4.0f},
|
||||
{-1},
|
||||
{std::numeric_limits<int32_t>::max()},
|
||||
{0},
|
||||
{-1},
|
||||
{4},
|
||||
{4.0f, 3.0f, 2.0f, 1.0f},
|
||||
true);
|
||||
}
|
||||
|
||||
// With numeric_limit_min, the end value should be clamped to -1
|
||||
TEST(SliceTest, Slice1D_ReverseAllAxes_2) {
|
||||
RunSliceTest<float>({4},
|
||||
{1.0f, 2.0f, 3.0f, 4.0f},
|
||||
{-1},
|
||||
{std::numeric_limits<int32_t>::min()},
|
||||
{0},
|
||||
{-1},
|
||||
{4},
|
||||
{4.0f, 3.0f, 2.0f, 1.0f},
|
||||
true);
|
||||
}
|
||||
|
||||
// giving an end value < -{dim_value} should also clamp it to -1
|
||||
TEST(SliceTest, Slice1D_ReverseAllAxes_3) {
|
||||
RunSliceTest<float>({4},
|
||||
{1.0f, 2.0f, 3.0f, 4.0f},
|
||||
{-1},
|
||||
{-5},
|
||||
{0},
|
||||
{-1},
|
||||
{4},
|
||||
{4.0f, 3.0f, 2.0f, 1.0f},
|
||||
true);
|
||||
}
|
||||
|
||||
TEST(SliceTest, Slice2D_ReverseAllAxes) {
|
||||
RunSliceTest<float>({2, 2},
|
||||
{1.0f, 2.0f, 3.0f, 4.0f},
|
||||
{-1, -1},
|
||||
{std::numeric_limits<int64_t>::max(), std::numeric_limits<int64_t>::max()},
|
||||
{0, 1},
|
||||
{-1, -1},
|
||||
{2, 2},
|
||||
{4.0f, 3.0f, 2.0f, 1.0f},
|
||||
true);
|
||||
}
|
||||
|
||||
|
||||
TEST(SliceTest, Slice2D_ReverseSubsetOfAxes_1) {
|
||||
RunSliceTest<float>({2, 2},
|
||||
{1.0f, 2.0f, 3.0f, 4.0f},
|
||||
{-1},
|
||||
{std::numeric_limits<int64_t>::max()},
|
||||
{1}, // axis = 1 only
|
||||
{-1},
|
||||
{2, 2},
|
||||
{2.0f, 1.0f, 4.0f, 3.0f},
|
||||
true);
|
||||
}
|
||||
|
||||
|
||||
TEST(SliceTest, Slice2D_ReverseSubsetOfAxes_2) {
|
||||
RunSliceTest<float>({2, 2},
|
||||
{1.0f, 2.0f, 3.0f, 4.0f},
|
||||
{-1},
|
||||
{std::numeric_limits<int64_t>::max()}, // end of dimension
|
||||
{0}, // axis = 0 only
|
||||
{-1},
|
||||
{2, 2},
|
||||
{3.0f, 4.0f, 1.0f, 2.0f},
|
||||
true);
|
||||
}
|
||||
|
||||
// Slice for implicit copy
|
||||
TEST(SliceTest, Slice2D_ImplicitCopyBySlicingADimensionFully) {
|
||||
RunSliceTest<float>({2, 2},
|
||||
{1.0f, 2.0f, 3.0f, 4.0f},
|
||||
{0},
|
||||
{std::numeric_limits<int64_t>::max()}, // end of dimension
|
||||
{1}, // axis = 1 only
|
||||
{1},
|
||||
{2, 2},
|
||||
{1.0f, 2.0, 3.0f, 4.0f},
|
||||
true);
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace onnxruntime
|
||||
|
|
|
|||
|
|
@ -83,13 +83,6 @@ backend_test.exclude(r'('
|
|||
'|^test_vgg19_cpu.*'
|
||||
'|^test_zfnet512_cpu.*'
|
||||
'|^test_gru_seq_length_cpu.*'
|
||||
'|^test_slice_cpu.*'
|
||||
'|^test_slice_default_axes_cpu.*'
|
||||
'|^test_slice_default_steps_cpu.*'
|
||||
'|^test_slice_end_out_of_bounds_cpu.*'
|
||||
'|^test_slice_neg_cpu.*'
|
||||
'|^test_slice_neg_steps_cpu.*'
|
||||
'|^test_slice_start_out_of_bounds_cpu.*'
|
||||
'|^test_averagepool_2d_ceil_cpu.*'
|
||||
'|^test_maxpool_2d_ceil_cpu.*'
|
||||
'|^test_maxpool_2d_dilations_cpu.*'
|
||||
|
|
|
|||
Loading…
Reference in a new issue