From 7d79bfef719b4e1afa71eb1954137c814109427e Mon Sep 17 00:00:00 2001 From: Pranav Sharma Date: Mon, 10 Dec 2018 16:12:56 -0800 Subject: [PATCH] Move isnan out of contrib_ops and add float16 support for it as per the spec. (#141) * Move isnan out of contrib_ops and add float16 support for it as per the spec. * Remove isnan from list of broken tests --- onnxruntime/contrib_ops/contrib_ops.cc | 22 +------- onnxruntime/contrib_ops/cpu/isnan.cc | 37 ------------- .../providers/cpu/cpu_execution_provider.cc | 24 ++++---- .../core/providers/cpu/tensor/isnan.cc | 55 +++++++++++++++++++ .../cpu => core/providers/cpu/tensor}/isnan.h | 2 - onnxruntime/test/contrib_ops/isnan_test.cc | 20 ------- onnxruntime/test/onnx/main.cc | 3 +- .../test/providers/cpu/tensor/isnan_test.cc | 29 ++++++++++ 8 files changed, 101 insertions(+), 91 deletions(-) delete mode 100644 onnxruntime/contrib_ops/cpu/isnan.cc create mode 100644 onnxruntime/core/providers/cpu/tensor/isnan.cc rename onnxruntime/{contrib_ops/cpu => core/providers/cpu/tensor}/isnan.h (89%) delete mode 100644 onnxruntime/test/contrib_ops/isnan_test.cc create mode 100644 onnxruntime/test/providers/cpu/tensor/isnan_test.cc diff --git a/onnxruntime/contrib_ops/contrib_ops.cc b/onnxruntime/contrib_ops/contrib_ops.cc index 43f0c3f8d7..7c8f8df3c7 100644 --- a/onnxruntime/contrib_ops/contrib_ops.cc +++ b/onnxruntime/contrib_ops/contrib_ops.cc @@ -78,22 +78,6 @@ Sample echo operator.)DOC"); ONNX_CONTRIB_OPERATOR_SCHEMA_ELSEWHERE(AttnLSTM, RegisterAttnLSTMContribOpSchema); ONNX_CONTRIB_OPERATOR_SCHEMA_ELSEWHERE(Range, RegisterRangeOpSchema); - ONNX_CONTRIB_OPERATOR_SCHEMA(IsNaN) - .SetDomain(kMSDomain) - .SinceVersion(1) - .Input(0, "X", "input", "T1") - .Output(0, "Y", "output", "T2") - .TypeConstraint( - "T1", - ONNX_NAMESPACE::OpSchema::numeric_types_for_math_reduction(), - "Constrain to any numeric tensor type. If the dtype attribute is not provided this must be a valid output type.") - .TypeConstraint( - "T2", - {"tensor(bool)"}, - "Constrain outputs to boolean tensor") - .TypeAndShapeInferenceFunction(ONNX_NAMESPACE::propagateShapeAndTypeFromFirstInput) - .SetDoc(R"DOC(Returns which elements of the input are NaN.)DOC"); - ONNX_CONTRIB_OPERATOR_SCHEMA(Tokenizer) .SetDomain(kMSDomain) .SinceVersion(1) @@ -203,8 +187,8 @@ should be equal to the number of columns of input 'b'.)DOC") .SetDomain(kMSDomain) .SinceVersion(1) .SetDoc(R"DOC( -The convolution operator consumes a quantized input tensor, its scale and zero point, -a quantized filter, its scale and zero point, and output's scale and zero point, +The convolution operator consumes a quantized input tensor, its scale and zero point, +a quantized filter, its scale and zero point, and output's scale and zero point, and computes the quantized output. Each scale and zero point pair must have same shape. It means they must be either scalars (per tensor) or 1-D tensors (per channel).)DOC") .Input( @@ -522,7 +506,6 @@ The bounding box coordinates corresponding to the selected indices can then be o class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, float, SampleOp); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, float, ExpandDims); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, AttnLSTM); -class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, float, IsNaN); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, string, Tokenizer); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, uint8_t, DequantizeLinear); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kMSDomain, 1, int8_t, DequantizeLinear); @@ -538,7 +521,6 @@ void RegisterContribKernels(std::function fn) { fn(BuildKernel()); fn(BuildKernel()); - fn(BuildKernel()); fn(BuildKernel()); fn(BuildKernel()); fn(BuildKernel()); diff --git a/onnxruntime/contrib_ops/cpu/isnan.cc b/onnxruntime/contrib_ops/cpu/isnan.cc deleted file mode 100644 index 9599c40b91..0000000000 --- a/onnxruntime/contrib_ops/cpu/isnan.cc +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#include "isnan.h" -#include "onnx/defs/schema.h" -#include "core/util/math_cpuonly.h" -#include "core/common/common.h" -#include "core/framework/tensor.h" - -namespace onnxruntime { -namespace contrib { -ONNX_CPU_OPERATOR_TYPED_MS_KERNEL( - IsNaN, - 1, - float, - KernelDefBuilder() - .TypeConstraint("T1", DataTypeImpl::GetTensorType()) - .TypeConstraint("T2", DataTypeImpl::GetTensorType()), - contrib::IsNaN); - -template <> -Status IsNaN::Compute(OpKernelContext* context) const { - const Tensor* X_ptr = context->Input(0); - if (!X_ptr) { - return Status(common::ONNXRUNTIME, common::FAIL, "Null input ptr"); - } - auto& X = *X_ptr; - auto& dims = X.Shape(); - auto& Y = *context->Output(0, dims); - - EigenMap(Y) = EigenMap(X).array().isNaN(); - - return Status::OK(); -} - -} // namespace contrib -} // namespace onnxruntime diff --git a/onnxruntime/core/providers/cpu/cpu_execution_provider.cc b/onnxruntime/core/providers/cpu/cpu_execution_provider.cc index 6a5b94b6b2..f5303df02c 100644 --- a/onnxruntime/core/providers/cpu/cpu_execution_provider.cc +++ b/onnxruntime/core/providers/cpu/cpu_execution_provider.cc @@ -73,9 +73,7 @@ class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, And class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, Or); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, Xor); class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, 9, float, Less); -class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, int32_t, Less); class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, 9, float, Greater); -class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, int32_t, Greater); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, bool, Equal); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, int32_t, Equal); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, int64_t, Equal); @@ -155,7 +153,6 @@ class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, Dro class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, Identity); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, ImageScaler); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 8, MeanVarianceNormalization); -class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, MeanVarianceNormalization); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 2, Pad); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 4, Reshape_1); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 5, Reshape); @@ -174,7 +171,6 @@ class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 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_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, Compress); 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); @@ -189,10 +185,16 @@ class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 8, Sca class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, Scale); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, If); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, Loop); -class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, EyeLike); // Opset 9 +class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, Compress); +class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, MeanVarianceNormalization); +class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, int32_t, Greater); +class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, int32_t, Less); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, ConstantLike); +class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, EyeLike); +class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, float, IsNaN); +class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, MLFloat16, IsNaN); void RegisterOnnxOperatorKernels(std::function fn) { fn(BuildKernel()); @@ -258,9 +260,7 @@ void RegisterOnnxOperatorKernels(std::function fn) { fn(BuildKernel()); fn(BuildKernel()); fn(BuildKernel()); - fn(BuildKernel()); fn(BuildKernel()); - fn(BuildKernel()); fn(BuildKernel()); fn(BuildKernel()); fn(BuildKernel()); @@ -340,7 +340,6 @@ void RegisterOnnxOperatorKernels(std::function fn) { fn(BuildKernel()); fn(BuildKernel()); fn(BuildKernel()); - fn(BuildKernel()); fn(BuildKernel()); fn(BuildKernel()); fn(BuildKernel()); @@ -359,7 +358,6 @@ void RegisterOnnxOperatorKernels(std::function fn) { fn(BuildKernel()); fn(BuildKernel()); fn(BuildKernel()); - fn(BuildKernel()); fn(BuildKernel()); fn(BuildKernel()); fn(BuildKernel()); @@ -374,10 +372,16 @@ void RegisterOnnxOperatorKernels(std::function fn) { fn(BuildKernel()); fn(BuildKernel()); fn(BuildKernel()); - fn(BuildKernel()); // Opset 9 + fn(BuildKernel()); + fn(BuildKernel()); + fn(BuildKernel()); + fn(BuildKernel()); fn(BuildKernel()); + fn(BuildKernel()); + fn(BuildKernel()); + fn(BuildKernel()); } // Forward declarations of ml op kernels diff --git a/onnxruntime/core/providers/cpu/tensor/isnan.cc b/onnxruntime/core/providers/cpu/tensor/isnan.cc new file mode 100644 index 0000000000..ec4143743e --- /dev/null +++ b/onnxruntime/core/providers/cpu/tensor/isnan.cc @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "isnan.h" +#include "core/util/math_cpuonly.h" +#include "core/common/common.h" +#include "core/framework/tensor.h" +#include "Eigen/src/Core/arch/CUDA/Half.h" + +namespace onnxruntime { +// https://github.com/onnx/onnx/blob/master/docs/Operators.md#IsNaN +#define ADD_TYPED_ISNAN_OP(data_type) \ + ONNX_CPU_OPERATOR_TYPED_KERNEL( \ + IsNaN, \ + 9, \ + data_type, \ + KernelDefBuilder() \ + .TypeConstraint("T1", DataTypeImpl::GetTensorType()) \ + .TypeConstraint("T2", DataTypeImpl::GetTensorType()), \ + IsNaN); + +ADD_TYPED_ISNAN_OP(float); +ADD_TYPED_ISNAN_OP(MLFloat16); + +template <> +Status IsNaN::Compute(OpKernelContext* context) const { + const Tensor* X_ptr = context->Input(0); + if (!X_ptr) { + return Status(common::ONNXRUNTIME, common::FAIL, "Null input ptr"); + } + auto& X = *X_ptr; + auto& dims = X.Shape(); + auto& Y = *context->Output(0, dims); + + EigenMap(Y) = EigenMap(X).array().isNaN(); + + return Status::OK(); +} + +template <> +Status IsNaN::Compute(OpKernelContext* context) const { + const Tensor* X_ptr = context->Input(0); + if (!X_ptr) { + return Status(common::ONNXRUNTIME, common::FAIL, "Null input ptr"); + } + auto X_data = X_ptr->template Data(); + auto& dims = X_ptr->Shape(); + auto shape_size = dims.Size(); + auto& Y = *context->Output(0, dims); + + EigenMap(Y) = ConstEigenVectorMap(static_cast(static_cast(X_data)), shape_size).array().isNaN(); + + return Status::OK(); +} +} // namespace onnxruntime diff --git a/onnxruntime/contrib_ops/cpu/isnan.h b/onnxruntime/core/providers/cpu/tensor/isnan.h similarity index 89% rename from onnxruntime/contrib_ops/cpu/isnan.h rename to onnxruntime/core/providers/cpu/tensor/isnan.h index 6c670e4049..4850f72ea8 100644 --- a/onnxruntime/contrib_ops/cpu/isnan.h +++ b/onnxruntime/core/providers/cpu/tensor/isnan.h @@ -6,12 +6,10 @@ #include "core/framework/op_kernel.h" namespace onnxruntime { -namespace contrib { template class IsNaN : public OpKernel { public: explicit IsNaN(const OpKernelInfo& info) : OpKernel(info) {} Status Compute(OpKernelContext* context) const override; }; -} // namespace contrib } // namespace onnxruntime diff --git a/onnxruntime/test/contrib_ops/isnan_test.cc b/onnxruntime/test/contrib_ops/isnan_test.cc deleted file mode 100644 index 43a7e781ce..0000000000 --- a/onnxruntime/test/contrib_ops/isnan_test.cc +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#include "gtest/gtest.h" -#include "test/providers/provider_test_utils.h" -#include // NAN - -namespace onnxruntime { -namespace test { - -TEST(ContribOpTest, IsNaN) { - OpTester test("IsNaN", 1, onnxruntime::kMSDomain); - std::vector dims{2, 2}; - test.AddInput("X", dims, {1.0f, NAN, 2.0f, NAN}); - test.AddOutput("Y", dims, {false, true, false, true}); - test.Run(); -} - -} // namespace test -} // namespace onnxruntime diff --git a/onnxruntime/test/onnx/main.cc b/onnxruntime/test/onnx/main.cc index e966040d4f..4871e1102c 100644 --- a/onnxruntime/test/onnx/main.cc +++ b/onnxruntime/test/onnx/main.cc @@ -330,8 +330,7 @@ int real_main(int argc, char* argv[]) { {"sign", "opset 9 not supported yet"}, {"scatter_with_axis", "opset 9 not supported yet"}, {"scatter_without_axis", "opset 9 not supported yet"}, - {"scan_sum", "opset 9 not supported yet"}, - {"isnan", "opset 9 not supported yet"}}; + {"scan_sum", "opset 9 not supported yet"}}; #ifdef USE_CUDA broken_tests["maxpool_2d_default"] = "cudnn pooling only support input dimension >= 3"; diff --git a/onnxruntime/test/providers/cpu/tensor/isnan_test.cc b/onnxruntime/test/providers/cpu/tensor/isnan_test.cc new file mode 100644 index 0000000000..1817135179 --- /dev/null +++ b/onnxruntime/test/providers/cpu/tensor/isnan_test.cc @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "gtest/gtest.h" +#include "test/providers/provider_test_utils.h" +#include // NAN +#include "core/util/math.h" + +namespace onnxruntime { +namespace test { + +TEST(IsNaNOpTest, IsNaNFloat) { + OpTester test("IsNaN", 9, kOnnxDomain); + std::vector dims{2, 2}; + test.AddInput("X", dims, {1.0f, NAN, 2.0f, NAN}); + test.AddOutput("Y", dims, {false, true, false, true}); + test.Run(); +} + +TEST(IsNaNOpTest, IsNaNFloat16) { + OpTester test("IsNaN", 9, kOnnxDomain); + std::vector dims{2, 2}; + test.AddInput("X", dims, std::initializer_list({MLFloat16(math::floatToHalf(1.0f)), MLFloat16(math::floatToHalf(NAN)), MLFloat16(math::floatToHalf(2.0f)), MLFloat16(math::floatToHalf(NAN))})); + test.AddOutput("Y", dims, {false, true, false, true}); + test.Run(); +} + +} // namespace test +} // namespace onnxruntime