diff --git a/onnxruntime/core/providers/cpu/cpu_execution_provider.cc b/onnxruntime/core/providers/cpu/cpu_execution_provider.cc index 6508bfdf86..6bc23ef14a 100644 --- a/onnxruntime/core/providers/cpu/cpu_execution_provider.cc +++ b/onnxruntime/core/providers/cpu/cpu_execution_provider.cc @@ -18,7 +18,7 @@ namespace onnxruntime { // Forward declarations of op kernels -class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 6, Clip); +class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 6, 10, Clip); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 6, Elu); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 6, HardSigmoid); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 6, LeakyRelu); @@ -298,9 +298,12 @@ class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, double, RoiAlign); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 10, ReverseSequence); +// opset 11 +class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, Clip); + void RegisterOnnxOperatorKernels(KernelRegistry& kernel_registry) { static const BuildKernelCreateInfoFn function_table[] = { - BuildKernelCreateInfo, + BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, @@ -579,6 +582,9 @@ void RegisterOnnxOperatorKernels(KernelRegistry& kernel_registry) { BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, + + //opset 11 + BuildKernelCreateInfo, }; for (auto& function_table_entry : function_table) { diff --git a/onnxruntime/core/providers/cpu/math/clip.cc b/onnxruntime/core/providers/cpu/math/clip.cc index 160d587df7..dc99582ddc 100644 --- a/onnxruntime/core/providers/cpu/math/clip.cc +++ b/onnxruntime/core/providers/cpu/math/clip.cc @@ -5,9 +5,16 @@ namespace onnxruntime { -ONNX_CPU_OPERATOR_KERNEL( +ONNX_CPU_OPERATOR_VERSIONED_KERNEL( Clip, 6, + 10, + KernelDefBuilder().MayInplace(0, 0).TypeConstraint("T", DataTypeImpl::GetTensorType()), + Clip_6); + +ONNX_CPU_OPERATOR_KERNEL( + Clip, + 11, KernelDefBuilder().MayInplace(0, 0).TypeConstraint("T", DataTypeImpl::GetTensorType()), Clip); diff --git a/onnxruntime/core/providers/cpu/math/clip.h b/onnxruntime/core/providers/cpu/math/clip.h index 653967547b..b4ef64398d 100644 --- a/onnxruntime/core/providers/cpu/math/clip.h +++ b/onnxruntime/core/providers/cpu/math/clip.h @@ -10,9 +10,9 @@ namespace onnxruntime { template -class Clip final : public OpKernel { +class Clip_6 final : public OpKernel { public: - Clip(const OpKernelInfo& info) : OpKernel(info) { + Clip_6(const OpKernelInfo& info) : OpKernel(info) { ORT_ENFORCE(info.GetAttr("max", &max_).IsOK()); ORT_ENFORCE(info.GetAttr("min", &min_).IsOK()); } @@ -32,4 +32,36 @@ class Clip final : public OpKernel { T min_; }; +template +class Clip final : public OpKernel { + public: + Clip(const OpKernelInfo& info) : OpKernel(info) { + } + + Status Compute(OpKernelContext* ctx) const override { + const auto* X = ctx->Input(0); + const auto* min = ctx->Input(1); + const auto* max = ctx->Input(2); + Tensor* Y = ctx->Output(0, X->Shape()); + + auto min_val = -std::numeric_limits::infinity(); + auto max_val = std::numeric_limits::infinity(); + if (min) { + ORT_ENFORCE(min->Shape().NumDimensions() == 0, "min should be a scalar."); + min_val = *(min->template Data()); + } + if (max) { + ORT_ENFORCE(max->Shape().NumDimensions() == 0, "max should be a scalar."); + max_val = *(max->template Data()); + } + + EigenVectorMap(Y->template MutableData(), Y->Shape().Size()) = + ConstEigenVectorMap(X->template Data(), X->Shape().Size()) + .cwiseMax(min_val) + .cwiseMin(max_val); + + return Status::OK(); + } +}; + } // namespace onnxruntime diff --git a/onnxruntime/test/onnx/main.cc b/onnxruntime/test/onnx/main.cc index 110aacfbc7..db35cef4e9 100644 --- a/onnxruntime/test/onnx/main.cc +++ b/onnxruntime/test/onnx/main.cc @@ -404,19 +404,19 @@ int real_main(int argc, char* argv[], Ort::Env& env) { {"cumsum_1d_reverse_exclusive", "not implemented yet"}, {"cumsum_1d_reverse", "not implemented yet"}, {"cumsum_1d_exclusive", "not implemented yet"}, - {"cumsum_1d", "not implemented yet"}, - {"clip_splitbounds", "not implemented yet for opset 11"}, - {"clip_outbounds", "not implemented yet for opset 11"}, - {"clip_example", "not implemented yet for opset 11"}, - {"clip_default_min", "not implemented yet for opset 11"}, - {"clip_default_max", "not implemented yet for opset 11"}, - {"clip", "not implemented yet for opset 11"}, + {"cumsum_1d", "not implemented yet"}, }; #ifdef USE_NGRAPH broken_tests.insert({"dequantizelinear", "ambiguity in scalar dimensions [] vs [1]", {"onnx150"}}); broken_tests.insert({"qlinearconv", "ambiguity in scalar dimensions [] vs [1]"}); broken_tests.insert({"quantizelinear", "ambiguity in scalar dimensions [] vs [1]", {"onnx150"}}); + broken_tests.insert({"clip_splitbounds", "not implemented yet for opset 11"}); + broken_tests.insert({"clip_outbounds", "not implemented yet for opset 11"}); + broken_tests.insert({"clip_example", "not implemented yet for opset 11"}); + broken_tests.insert({"clip_default_min", "not implemented yet for opset 11"}); + broken_tests.insert({"clip_default_max", "not implemented yet for opset 11"}); + broken_tests.insert({"clip", "not implemented yet for opset 11"}); #endif #ifdef USE_MKLDNN diff --git a/onnxruntime/test/providers/cpu/math/clip_test.cc b/onnxruntime/test/providers/cpu/math/clip_test.cc index 7a80f6a983..f68f89d7ef 100644 --- a/onnxruntime/test/providers/cpu/math/clip_test.cc +++ b/onnxruntime/test/providers/cpu/math/clip_test.cc @@ -7,8 +7,8 @@ namespace onnxruntime { namespace test { -TEST(MathOpTest, Clip) { - OpTester test("Clip"); +TEST(MathOpTest, Clip_6) { + OpTester test("Clip", 6); test.AddAttribute("min", -10.0f); test.AddAttribute("max", 10.0f); @@ -25,5 +25,41 @@ TEST(MathOpTest, Clip) { test.Run(); } +TEST(MathOpTest, Clip_Default) { + OpTester test("Clip", 11); + + std::vector dims{3, 3}; + test.AddInput("X", dims, + {11.0f, 4.4f, 432.3f, + -1.3f, 3.5f, 64.0f, + -5.4f, 9.3f, 82.4f}); + test.AddOutput("Y", dims, + {11.0f, 4.4f, 432.3f, + -1.3f, 3.5f, 64.0f, + -5.4f, 9.3f, 82.4f}); + + // nGraph does not support Clip opset 11 yet. + test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kNGraphExecutionProvider}); +} + +TEST(MathOpTest, Clip) { + OpTester test("Clip", 11); + + std::vector dims{3, 3}; + test.AddInput("X", dims, + {-1.0f, 0.0f, 1.0f, + -6.0f, 0.0f, 6.0f, + -5.4f, 2.0f, 6.0f}); + test.AddInput("min", {}, {-5}); + test.AddInput("max", {}, {5}); + test.AddOutput("Y", dims, + {-1.0f, 0.0f, 1.0f, + -5.0f, 0.0f, 5.0f, + -5.0f, 2.0f, 5.0f}); + + // nGraph does not support Clip opset 11 yet. + test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kNGraphExecutionProvider}); +} + } // namespace test } // namespace onnxruntime diff --git a/onnxruntime/test/python/onnx_backend_test_series.py b/onnxruntime/test/python/onnx_backend_test_series.py index 47d1855db0..a2f6011cce 100644 --- a/onnxruntime/test/python/onnx_backend_test_series.py +++ b/onnxruntime/test/python/onnx_backend_test_series.py @@ -116,7 +116,6 @@ def create_backend_test(testname=None): '^test_dynamicquantizelinear_max_adjusted_expanded*', '^test_dynamicquantizelinear_min_adjusted*', '^test_dynamicquantizelinear_min_adjusted_expanded*', - '^test_clip*', '^test_depthtospace*', '^test_gather_elements*', '^test_scatter_elements*', @@ -127,6 +126,8 @@ def create_backend_test(testname=None): # Example of how to disable tests for a specific provider. # if c2.supports_device('NGRAPH'): # current_failing_tests = current_failing_tests + ('|^test_operator_repeat_dim_overflow_cpu.*',) + if c2.supports_device('NGRAPH'): + current_failing_tests = current_failing_tests + ('|^test_clip*',) filters = current_failing_tests + \ tests_with_pre_opset7_dependencies_filters() + \