From 111ac299cc26d0b7dfca68e500855e927653c157 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xavier=20Dupr=C3=A9?= Date: Mon, 28 Dec 2020 12:53:44 +0100 Subject: [PATCH] Support double for operators Where, LpNormalisation (#6034) --- .../providers/cpu/cpu_execution_provider.cc | 11 +- onnxruntime/core/providers/cpu/nn/lp_norm.cc | 47 +++--- .../core/providers/cpu/tensor/where_op.cc | 2 +- .../test/providers/cpu/nn/lp_norm_op_test.cc | 147 +++++++++++------- .../providers/cpu/tensor/where_op_test.cc | 2 + 5 files changed, 131 insertions(+), 78 deletions(-) diff --git a/onnxruntime/core/providers/cpu/cpu_execution_provider.cc b/onnxruntime/core/providers/cpu/cpu_execution_provider.cc index deda7f8227..55f25b0a2d 100644 --- a/onnxruntime/core/providers/cpu/cpu_execution_provider.cc +++ b/onnxruntime/core/providers/cpu/cpu_execution_provider.cc @@ -134,7 +134,8 @@ class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDoma class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 10, ConvTranspose); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 8, Flatten); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 6, InstanceNormalization); -class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, LpNormalization); +class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, float, LpNormalization); +class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, double, LpNormalization); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 12, LRN); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, 9, AveragePool); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 7, MaxPool); @@ -266,6 +267,7 @@ class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOn class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, 12, uint8_t, NonZero); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, string, Where); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, float, Where); +class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, double, Where); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, int32_t, Where); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, int64_t, Where); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, uint8_t, Where); @@ -812,7 +814,10 @@ Status RegisterOnnxOperatorKernels(KernelRegistry& kernel_registry) { Flatten)>, BuildKernelCreateInfo, - BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, @@ -1033,6 +1038,8 @@ Status RegisterOnnxOperatorKernels(KernelRegistry& kernel_registry) { Where)>, BuildKernelCreateInfo, + BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo()), - LpNorm); +#define REGISTER_LPNORMALISATION_KERNEL(type, sinceVersion) \ + ONNX_CPU_OPERATOR_TYPED_KERNEL( \ + LpNormalization, sinceVersion, type, \ + KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType()), \ + LpNorm); + +REGISTER_LPNORMALISATION_KERNEL(float, 1) +REGISTER_LPNORMALISATION_KERNEL(double, 1) using InnerStride = Eigen::InnerStride; -using StridedVec = Eigen::Map, 0, InnerStride>; -using ConstStridedVec = Eigen::Map, 0, InnerStride>; +template +using StridedVec = Eigen::Map, 0, InnerStride>; + +template +using ConstStridedVec = Eigen::Map, 0, InnerStride>; + +template void DoNormalizeP2( - const float* xData, - float* yData, + const T* xData, + T* yData, const int64_t m, const int64_t n, const int64_t sf) { for (int i = 0; i < n; ++i) { auto base = (i / sf) * sf * m + (i % sf); - ConstStridedVec xVec(xData + base, 1, m, InnerStride(sf)); - StridedVec yVec(yData + base, 1, m, InnerStride(sf)); + ConstStridedVec xVec(xData + base, 1, m, InnerStride(sf)); + StridedVec yVec(yData + base, 1, m, InnerStride(sf)); auto norm = xVec.template lpNorm<2>(); if (norm != 0) { @@ -37,16 +45,17 @@ void DoNormalizeP2( } }; +template void DoNormalizeP1( - const float* xData, - float* yData, + const T* xData, + T* yData, const int64_t m, const int64_t n, const int64_t sf) { for (int i = 0; i < n; ++i) { auto base = (i / sf) * sf * m + (i % sf); - ConstStridedVec xVec(xData + base, 1, m, InnerStride(sf)); - StridedVec yVec(yData + base, 1, m, InnerStride(sf)); + ConstStridedVec xVec(xData + base, 1, m, InnerStride(sf)); + StridedVec yVec(yData + base, 1, m, InnerStride(sf)); auto norm = xVec.template lpNorm<1>(); if (norm != 0) { @@ -58,8 +67,8 @@ void DoNormalizeP1( } }; -template <> -Status LpNorm::Compute(OpKernelContext* p_op_kernel_context) const { +template +Status LpNorm::Compute(OpKernelContext* p_op_kernel_context) const { const auto* input = p_op_kernel_context->Input(0); const TensorShape& input_shape = input->Shape(); Tensor* output = p_op_kernel_context->Output(0, input_shape); @@ -70,9 +79,9 @@ Status LpNorm::Compute(OpKernelContext* p_op_kernel_context) const { const int64_t sf = input_shape.SizeFromDimension(canonical_axis + 1); if (p_ == 1) { - DoNormalizeP1(input->template Data(), output->template MutableData(), m, n, sf); + DoNormalizeP1(input->template Data(), output->template MutableData(), m, n, sf); } else if (p_ == 2) { - DoNormalizeP2(input->template Data(), output->template MutableData(), m, n, sf); + DoNormalizeP2(input->template Data(), output->template MutableData(), m, n, sf); } return Status::OK(); diff --git a/onnxruntime/core/providers/cpu/tensor/where_op.cc b/onnxruntime/core/providers/cpu/tensor/where_op.cc index 05be3d4ff4..f57b9ba086 100644 --- a/onnxruntime/core/providers/cpu/tensor/where_op.cc +++ b/onnxruntime/core/providers/cpu/tensor/where_op.cc @@ -33,7 +33,7 @@ WHERE_TYPED_KERNEL(int64_t) //WHERE_TYPED_KERNEL(MLFloat16) //WHERE_TYPED_KERNEL(BFloat16) WHERE_TYPED_KERNEL(float) -//WHERE_TYPED_KERNEL(double) +WHERE_TYPED_KERNEL(double) WHERE_TYPED_KERNEL_WITH_TYPE_NAME(std::string, string) //WHERE_TYPED_KERNEL(bool) diff --git a/onnxruntime/test/providers/cpu/nn/lp_norm_op_test.cc b/onnxruntime/test/providers/cpu/nn/lp_norm_op_test.cc index a2eaa5f798..e37206d6ae 100644 --- a/onnxruntime/test/providers/cpu/nn/lp_norm_op_test.cc +++ b/onnxruntime/test/providers/cpu/nn/lp_norm_op_test.cc @@ -7,48 +7,55 @@ using namespace std; namespace onnxruntime { namespace test { -TEST(LpNormalizationTest, L1Normalization) { +template +void L1Normalization() { OpTester test("LpNormalization"); test.AddAttribute("axis", (int64_t)1); test.AddAttribute("p", (int64_t)1); - vector input = {5.93932154F, 7.4367043F, 6.42487038F, 5.90394865F, - 4.81289319F, 6.81304702F, 4.9382849F, 9.02595701F, - 9.67296484F, 4.45097367F, 8.12552534F, 5.76005428F, + vector input = {5.93932154F, 7.4367043F, 6.42487038F, 5.90394865F, + 4.81289319F, 6.81304702F, 4.9382849F, 9.02595701F, + 9.67296484F, 4.45097367F, 8.12552534F, 5.76005428F, - 6.11240105F, 9.33036974F, 1.63932452F, 1.7841637F, - 1.18196558F, 8.49357861F, 8.00341076F, 8.83010933F, - 9.80756508F, 8.19242708F, 5.15331426F, 8.02476259F}; + 6.11240105F, 9.33036974F, 1.63932452F, 1.7841637F, + 1.18196558F, 8.49357861F, 8.00341076F, 8.83010933F, + 9.80756508F, 8.19242708F, 5.15331426F, 8.02476259F}; vector input_dims = {2, 3, 4}; - test.AddInput("input", input_dims, input); + test.AddInput("input", input_dims, input); - vector expected_output = {0.2907843F, 0.3976693F, 0.3296719F, 0.28535331F, - 0.23563529F, 0.36431994F, 0.25339247F, 0.43624816F, - 0.47358041F, 0.23801075F, 0.41693563F, 0.27839852F, + vector expected_output = {0.2907843F, 0.3976693F, 0.3296719F, 0.28535331F, + 0.23563529F, 0.36431994F, 0.25339247F, 0.43624816F, + 0.47358041F, 0.23801075F, 0.41693563F, 0.27839852F, - 0.35740998F, 0.3586345F, 0.11079474F, 0.09572189F, - 0.06911299F, 0.32647048F, 0.54091538F, 0.47374282F, - 0.57347703F, 0.31489502F, 0.34828988F, 0.43053529F}; - test.AddOutput("Y", input_dims, expected_output); + 0.35740998F, 0.3586345F, 0.11079474F, 0.09572189F, + 0.06911299F, 0.32647048F, 0.54091538F, 0.47374282F, + 0.57347703F, 0.31489502F, 0.34828988F, 0.43053529F}; + test.AddOutput("Y", input_dims, expected_output); test.Run(); } -TEST(LpNormalizationTest, L2Normalization) { +TEST(LpNormalizationTest, L1Normalization) { + L1Normalization(); + L1Normalization(); +} + +template +void L2Normalization() { OpTester test("LpNormalization"); test.AddAttribute("axis", (int64_t)1); test.AddAttribute("p", (int64_t)2); - vector input = {5.93932154F, 7.4367043F, 6.42487038F, 5.90394865F, - 4.81289319F, 6.81304702F, 4.9382849F, 9.02595701F, - 9.67296484F, 4.45097367F, 8.12552534F, 5.76005428F, + vector input = {5.93932154F, 7.4367043F, 6.42487038F, 5.90394865F, + 4.81289319F, 6.81304702F, 4.9382849F, 9.02595701F, + 9.67296484F, 4.45097367F, 8.12552534F, 5.76005428F, - 6.11240105F, 9.33036974F, 1.63932452F, 1.7841637F, - 1.18196558F, 8.49357861F, 8.00341076F, 8.83010933F, - 9.80756508F, 8.19242708F, 5.15331426F, 8.02476259F}; + 6.11240105F, 9.33036974F, 1.63932452F, 1.7841637F, + 1.18196558F, 8.49357861F, 8.00341076F, 8.83010933F, + 9.80756508F, 8.19242708F, 5.15331426F, 8.02476259F}; vector input_dims = {2, 3, 4}; - test.AddInput("input", input_dims, input); + test.AddInput("input", input_dims, input); - vector expected_output = { + vector expected_output = { 0.48173351F, 0.67457895F, 0.55987147F, 0.48285641F, 0.39036983F, 0.61800737F, 0.4303285F, 0.73819091F, 0.78456626F, 0.40374513F, 0.70806873F, 0.47108796F, @@ -56,85 +63,113 @@ TEST(LpNormalizationTest, L2Normalization) { 0.52617536F, 0.62021826F, 0.16971778F, 0.14788607F, 0.10174744F, 0.56459419F, 0.82858584F, 0.73191164F, 0.8442671F, 0.54457572F, 0.53351794F, 0.66515792F}; - test.AddOutput("Y", input_dims, expected_output); + test.AddOutput("Y", input_dims, expected_output); test.Run(); } -TEST(LpNormalizationTest, LpNormalizationDefaultAxisAndP) { - OpTester test("LpNormalization"); +TEST(LpNormalizationTest, L2Normalization) { + L2Normalization(); + L2Normalization(); +} - vector input = { +template +void LpNormalizationDefaultAxisAndP() { + OpTester test("LpNormalization"); + vector input = { 0.0f, 0.5f, 2.0f, 2.0f, 1.0f, 0.5f, 2.0f, 2.5f, 1.0f, 1.5f, 3.0f, 3.0f, 1.5f, 2.0f, 3.5f, 3.5f}; vector input_dims = {16}; - test.AddInput("input", input_dims, input); + test.AddInput("input", input_dims, input); - vector expected_output = { + vector expected_output = { 0.0f, 0.059028134f, 0.236112535f, 0.236112535f, 0.118056267f, 0.059028134f, 0.236112535f, 0.295140654f, 0.118056267f, 0.177084401f, 0.354168802f, 0.354168802f, 0.177084401f, 0.236112535f, 0.413196921f, 0.413196921f}; - test.AddOutput("Y", input_dims, expected_output); + test.AddOutput("Y", input_dims, expected_output); test.Run(); } -TEST(LpNormalizationTest, L1NormalizationWithValidNegativeAxis) { +TEST(LpNormalizationTest, LpNormalizationDefaultAxisAndP) { + LpNormalizationDefaultAxisAndP(); + LpNormalizationDefaultAxisAndP(); +} + +template +void L1NormalizationWithValidNegativeAxis() { OpTester test("LpNormalization"); test.AddAttribute("axis", static_cast(-2)); test.AddAttribute("p", static_cast(1)); - vector input = {5.93932154F, 7.4367043F, 6.42487038F, 5.90394865F, - 4.81289319F, 6.81304702F, 4.9382849F, 9.02595701F, - 9.67296484F, 4.45097367F, 8.12552534F, 5.76005428F, + vector input = {5.93932154F, 7.4367043F, 6.42487038F, 5.90394865F, + 4.81289319F, 6.81304702F, 4.9382849F, 9.02595701F, + 9.67296484F, 4.45097367F, 8.12552534F, 5.76005428F, - 6.11240105F, 9.33036974F, 1.63932452F, 1.7841637F, - 1.18196558F, 8.49357861F, 8.00341076F, 8.83010933F, - 9.80756508F, 8.19242708F, 5.15331426F, 8.02476259F}; + 6.11240105F, 9.33036974F, 1.63932452F, 1.7841637F, + 1.18196558F, 8.49357861F, 8.00341076F, 8.83010933F, + 9.80756508F, 8.19242708F, 5.15331426F, 8.02476259F}; vector input_dims = {2, 3, 4}; - test.AddInput("input", input_dims, input); + test.AddInput("input", input_dims, input); - vector expected_output = {0.2907843F, 0.3976693F, 0.3296719F, 0.28535331F, - 0.23563529F, 0.36431994F, 0.25339247F, 0.43624816F, - 0.47358041F, 0.23801075F, 0.41693563F, 0.27839852F, + vector expected_output = {0.2907843F, 0.3976693F, 0.3296719F, 0.28535331F, + 0.23563529F, 0.36431994F, 0.25339247F, 0.43624816F, + 0.47358041F, 0.23801075F, 0.41693563F, 0.27839852F, - 0.35740998F, 0.3586345F, 0.11079474F, 0.09572189F, - 0.06911299F, 0.32647048F, 0.54091538F, 0.47374282F, - 0.57347703F, 0.31489502F, 0.34828988F, 0.43053529F}; - test.AddOutput("Y", input_dims, expected_output); + 0.35740998F, 0.3586345F, 0.11079474F, 0.09572189F, + 0.06911299F, 0.32647048F, 0.54091538F, 0.47374282F, + 0.57347703F, 0.31489502F, 0.34828988F, 0.43053529F}; + test.AddOutput("Y", input_dims, expected_output); test.Run(); } -TEST(LpNormalizationTest, L1NormalizationWithZeroNorm) { +TEST(LpNormalizationTest, L1NormalizationWithValidNegativeAxis) { + L1NormalizationWithValidNegativeAxis(); + L1NormalizationWithValidNegativeAxis(); +} + +template +void L1NormalizationWithZeroNorm() { OpTester test("LpNormalization"); test.AddAttribute("p", static_cast(1)); // With default axis (axis = -1), one of the norms will be evaluated to zero // for the following input - vector input = {2.f, 2.f, 0.f, 0.f}; + vector input = {2.f, 2.f, 0.f, 0.f}; vector input_dims = {2, 2}; - test.AddInput("input", input_dims, input); + test.AddInput("input", input_dims, input); - vector expected_output = {0.5f, 0.5f, 0.f, 0.f}; - test.AddOutput("Y", input_dims, expected_output); + vector expected_output = {0.5f, 0.5f, 0.f, 0.f}; + test.AddOutput("Y", input_dims, expected_output); test.Run(); } -TEST(LpNormalizationTest, L2NormalizationWithZeroNorm) { +TEST(LpNormalizationTest, L1NormalizationWithZeroNorm) { + L1NormalizationWithZeroNorm(); + L1NormalizationWithZeroNorm(); +} + +template +void L2NormalizationWithZeroNorm() { OpTester test("LpNormalization"); // With default axis (axis = -1), one of the norms will be evaluated to zero // for the following input - vector input = {1.f, 0.f, 0.f, 0.f}; + vector input = {1.f, 0.f, 0.f, 0.f}; vector input_dims = {2, 2}; - test.AddInput("input", input_dims, input); + test.AddInput("input", input_dims, input); - vector expected_output = {1.f, 0.f, 0.f, 0.f}; - test.AddOutput("Y", input_dims, expected_output); + vector expected_output = {1.f, 0.f, 0.f, 0.f}; + test.AddOutput("Y", input_dims, expected_output); test.Run(); } +TEST(LpNormalizationTest, L2NormalizationWithZeroNorm) { + L2NormalizationWithZeroNorm(); + L2NormalizationWithZeroNorm(); +} + } // namespace test } // namespace onnxruntime diff --git a/onnxruntime/test/providers/cpu/tensor/where_op_test.cc b/onnxruntime/test/providers/cpu/tensor/where_op_test.cc index 4e08204564..b38b5ed0a1 100644 --- a/onnxruntime/test/providers/cpu/tensor/where_op_test.cc +++ b/onnxruntime/test/providers/cpu/tensor/where_op_test.cc @@ -88,6 +88,7 @@ void WhereBroadcastTest(const T& x_value, const T& y_value) { TEST(WhereOpTest, BasicNumeric) { WhereBasicNumericTest(); + WhereBasicNumericTest(); } TEST(WhereOpTest, BasicString) { @@ -106,6 +107,7 @@ TEST(WhereOpTest, BasicString) { TEST(WhereOpTest, Broadcast) { WhereBroadcastTest(1.0f, 0.0f); + WhereBroadcastTest(1.0f, 0.0f); WhereBroadcastTest("true", "false"); }