Support double for operators Where, LpNormalisation (#6034)

This commit is contained in:
Xavier Dupré 2020-12-28 12:53:44 +01:00 committed by GitHub
parent 2d09db67b4
commit 111ac299cc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 131 additions and 78 deletions

View file

@ -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<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 6,
InstanceNormalization)>,
BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, LpNormalization)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1,
float, LpNormalization)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1,
double, LpNormalization)>,
BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, 12, LRN)>,
BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, 9,
AveragePool)>,
@ -1033,6 +1038,8 @@ Status RegisterOnnxOperatorKernels(KernelRegistry& kernel_registry) {
Where)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, float,
Where)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, double,
Where)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, int32_t,
Where)>,
BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, int64_t,

View file

@ -6,26 +6,34 @@
#include "core/providers/common.h"
namespace onnxruntime {
ONNX_CPU_OPERATOR_KERNEL(
LpNormalization,
1,
KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType<float>()),
LpNorm<float>);
#define REGISTER_LPNORMALISATION_KERNEL(type, sinceVersion) \
ONNX_CPU_OPERATOR_TYPED_KERNEL( \
LpNormalization, sinceVersion, type, \
KernelDefBuilder().TypeConstraint("T", DataTypeImpl::GetTensorType<type>()), \
LpNorm<type>);
REGISTER_LPNORMALISATION_KERNEL(float, 1)
REGISTER_LPNORMALISATION_KERNEL(double, 1)
using InnerStride = Eigen::InnerStride<Eigen::Dynamic>;
using StridedVec = Eigen::Map<Eigen::Matrix<float, 1, Eigen::Dynamic>, 0, InnerStride>;
using ConstStridedVec = Eigen::Map<const Eigen::Matrix<float, 1, Eigen::Dynamic>, 0, InnerStride>;
template <typename T>
using StridedVec = Eigen::Map<Eigen::Matrix<T, 1, Eigen::Dynamic>, 0, InnerStride>;
template <typename T>
using ConstStridedVec = Eigen::Map<const Eigen::Matrix<T, 1, Eigen::Dynamic>, 0, InnerStride>;
template <typename T>
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<T> xVec(xData + base, 1, m, InnerStride(sf));
StridedVec<T> yVec(yData + base, 1, m, InnerStride(sf));
auto norm = xVec.template lpNorm<2>();
if (norm != 0) {
@ -37,16 +45,17 @@ void DoNormalizeP2(
}
};
template <typename T>
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<T> xVec(xData + base, 1, m, InnerStride(sf));
StridedVec<T> 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<float>::Compute(OpKernelContext* p_op_kernel_context) const {
template <typename T>
Status LpNorm<T>::Compute(OpKernelContext* p_op_kernel_context) const {
const auto* input = p_op_kernel_context->Input<Tensor>(0);
const TensorShape& input_shape = input->Shape();
Tensor* output = p_op_kernel_context->Output(0, input_shape);
@ -70,9 +79,9 @@ Status LpNorm<float>::Compute(OpKernelContext* p_op_kernel_context) const {
const int64_t sf = input_shape.SizeFromDimension(canonical_axis + 1);
if (p_ == 1) {
DoNormalizeP1(input->template Data<float>(), output->template MutableData<float>(), m, n, sf);
DoNormalizeP1(input->template Data<T>(), output->template MutableData<T>(), m, n, sf);
} else if (p_ == 2) {
DoNormalizeP2(input->template Data<float>(), output->template MutableData<float>(), m, n, sf);
DoNormalizeP2(input->template Data<T>(), output->template MutableData<T>(), m, n, sf);
}
return Status::OK();

View file

@ -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)

View file

@ -7,48 +7,55 @@ using namespace std;
namespace onnxruntime {
namespace test {
TEST(LpNormalizationTest, L1Normalization) {
template <typename T>
void L1Normalization() {
OpTester test("LpNormalization");
test.AddAttribute("axis", (int64_t)1);
test.AddAttribute("p", (int64_t)1);
vector<float> 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<T> 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<int64_t> input_dims = {2, 3, 4};
test.AddInput<float>("input", input_dims, input);
test.AddInput<T>("input", input_dims, input);
vector<float> 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<T> 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<float>("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<T>("Y", input_dims, expected_output);
test.Run();
}
TEST(LpNormalizationTest, L2Normalization) {
TEST(LpNormalizationTest, L1Normalization) {
L1Normalization<float>();
L1Normalization<double>();
}
template <typename T>
void L2Normalization() {
OpTester test("LpNormalization");
test.AddAttribute("axis", (int64_t)1);
test.AddAttribute("p", (int64_t)2);
vector<float> 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<T> 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<int64_t> input_dims = {2, 3, 4};
test.AddInput<float>("input", input_dims, input);
test.AddInput<T>("input", input_dims, input);
vector<float> expected_output = {
vector<T> 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<float>("Y", input_dims, expected_output);
test.AddOutput<T>("Y", input_dims, expected_output);
test.Run();
}
TEST(LpNormalizationTest, LpNormalizationDefaultAxisAndP) {
OpTester test("LpNormalization");
TEST(LpNormalizationTest, L2Normalization) {
L2Normalization<float>();
L2Normalization<double>();
}
vector<float> input = {
template <typename T>
void LpNormalizationDefaultAxisAndP() {
OpTester test("LpNormalization");
vector<T> 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<int64_t> input_dims = {16};
test.AddInput<float>("input", input_dims, input);
test.AddInput<T>("input", input_dims, input);
vector<float> expected_output = {
vector<T> 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<float>("Y", input_dims, expected_output);
test.AddOutput<T>("Y", input_dims, expected_output);
test.Run();
}
TEST(LpNormalizationTest, L1NormalizationWithValidNegativeAxis) {
TEST(LpNormalizationTest, LpNormalizationDefaultAxisAndP) {
LpNormalizationDefaultAxisAndP<float>();
LpNormalizationDefaultAxisAndP<double>();
}
template <typename T>
void L1NormalizationWithValidNegativeAxis() {
OpTester test("LpNormalization");
test.AddAttribute("axis", static_cast<int64_t>(-2));
test.AddAttribute("p", static_cast<int64_t>(1));
vector<float> 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<T> 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<int64_t> input_dims = {2, 3, 4};
test.AddInput<float>("input", input_dims, input);
test.AddInput<T>("input", input_dims, input);
vector<float> 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<T> 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<float>("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<T>("Y", input_dims, expected_output);
test.Run();
}
TEST(LpNormalizationTest, L1NormalizationWithZeroNorm) {
TEST(LpNormalizationTest, L1NormalizationWithValidNegativeAxis) {
L1NormalizationWithValidNegativeAxis<float>();
L1NormalizationWithValidNegativeAxis<double>();
}
template <typename T>
void L1NormalizationWithZeroNorm() {
OpTester test("LpNormalization");
test.AddAttribute("p", static_cast<int64_t>(1));
// With default axis (axis = -1), one of the norms will be evaluated to zero
// for the following input
vector<float> input = {2.f, 2.f, 0.f, 0.f};
vector<T> input = {2.f, 2.f, 0.f, 0.f};
vector<int64_t> input_dims = {2, 2};
test.AddInput<float>("input", input_dims, input);
test.AddInput<T>("input", input_dims, input);
vector<float> expected_output = {0.5f, 0.5f, 0.f, 0.f};
test.AddOutput<float>("Y", input_dims, expected_output);
vector<T> expected_output = {0.5f, 0.5f, 0.f, 0.f};
test.AddOutput<T>("Y", input_dims, expected_output);
test.Run();
}
TEST(LpNormalizationTest, L2NormalizationWithZeroNorm) {
TEST(LpNormalizationTest, L1NormalizationWithZeroNorm) {
L1NormalizationWithZeroNorm<float>();
L1NormalizationWithZeroNorm<double>();
}
template <typename T>
void L2NormalizationWithZeroNorm() {
OpTester test("LpNormalization");
// With default axis (axis = -1), one of the norms will be evaluated to zero
// for the following input
vector<float> input = {1.f, 0.f, 0.f, 0.f};
vector<T> input = {1.f, 0.f, 0.f, 0.f};
vector<int64_t> input_dims = {2, 2};
test.AddInput<float>("input", input_dims, input);
test.AddInput<T>("input", input_dims, input);
vector<float> expected_output = {1.f, 0.f, 0.f, 0.f};
test.AddOutput<float>("Y", input_dims, expected_output);
vector<T> expected_output = {1.f, 0.f, 0.f, 0.f};
test.AddOutput<T>("Y", input_dims, expected_output);
test.Run();
}
TEST(LpNormalizationTest, L2NormalizationWithZeroNorm) {
L2NormalizationWithZeroNorm<float>();
L2NormalizationWithZeroNorm<double>();
}
} // namespace test
} // namespace onnxruntime

View file

@ -88,6 +88,7 @@ void WhereBroadcastTest(const T& x_value, const T& y_value) {
TEST(WhereOpTest, BasicNumeric) {
WhereBasicNumericTest<float>();
WhereBasicNumericTest<double>();
}
TEST(WhereOpTest, BasicString) {
@ -106,6 +107,7 @@ TEST(WhereOpTest, BasicString) {
TEST(WhereOpTest, Broadcast) {
WhereBroadcastTest<float>(1.0f, 0.0f);
WhereBroadcastTest<double>(1.0f, 0.0f);
WhereBroadcastTest<std::string>("true", "false");
}