Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion onnxruntime/core/providers/cpu/cpu_execution_provider.cc
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain,
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);
class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, Sign);
class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, Erf);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, int64_t_int64_t_int64_t, OneHot);
class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, float_int64_t_int64_t, OneHot);
Expand Down Expand Up @@ -459,7 +460,7 @@ void RegisterOnnxOperatorKernels(KernelRegistry& kernel_registry) {
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 1, Unsqueeze)>());
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, 9, float, Upsample)>());
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, 9, int32_t, Upsample)>());
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, 9, uint8_t, Upsample)>());
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 7, 9, uint8_t, Upsample)>());
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 8, float, Expand)>());
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 8, double, Expand)>());
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 8, int8_t, Expand)>());
Expand All @@ -486,6 +487,7 @@ void RegisterOnnxOperatorKernels(KernelRegistry& kernel_registry) {
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, EyeLike)>());
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, float, IsNaN)>());
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, MLFloat16, IsNaN)>());
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, Sign)>());
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, Erf)>());
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, int64_t_int64_t_int64_t, OneHot)>());
kernel_registry.Register(BuildKernelCreateInfo<ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 9, float_int64_t_int64_t, OneHot)>());
Expand Down
112 changes: 112 additions & 0 deletions onnxruntime/core/providers/cpu/math/sign.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#include "core/common/common.h"
#include "core/framework/data_types.h"
#include "core/framework/op_kernel.h"
#include "core/util/math.h"
#include "core/util/math_cpuonly.h"

#include "gsl/span"
#include <type_traits>

using namespace ::onnxruntime::common;
using namespace ONNX_NAMESPACE;
namespace onnxruntime {

class Sign final : public OpKernel {
public:
explicit Sign(const OpKernelInfo& info) : OpKernel(info) {}

Status Compute(OpKernelContext* ctx) const override;
};

ONNX_CPU_OPERATOR_KERNEL(
Sign,
9,
KernelDefBuilder().TypeConstraint("T", {DataTypeImpl::GetTensorType<float>(),
DataTypeImpl::GetTensorType<double>(),
DataTypeImpl::GetTensorType<int64_t>(),
DataTypeImpl::GetTensorType<uint64_t>(),
DataTypeImpl::GetTensorType<int32_t>(),
DataTypeImpl::GetTensorType<uint32_t>(),
DataTypeImpl::GetTensorType<int16_t>(),
DataTypeImpl::GetTensorType<uint16_t>(),
DataTypeImpl::GetTensorType<int8_t>(),
DataTypeImpl::GetTensorType<uint8_t>(),
DataTypeImpl::GetTensorType<MLFloat16>(),
DataTypeImpl::GetTensorType<BFloat16>()}),
Sign);

namespace sign_internal {
// The spec does not specify how NaN is
// treated but we have to treat it somehow. We choose
// to return 0 for NaN as TF does.
template <class T>
inline T FloatingImpl(T val) {
if (std::isnan(val) || val == T(0)) {
return T(0);
} else if (val > T(0)) {
return T(1);
} else {
return T(-1);
}
}

void SignMLFloat16(const Tensor* input, Tensor* output) {
auto span = gsl::make_span(input->Data<MLFloat16>(), input->Shape().Size());
auto output_data = output->template MutableData<MLFloat16>();
std::transform(span.cbegin(), span.cend(), output_data, [](const MLFloat16& val) {
float fl = math::halfToFloat(val.val);
return MLFloat16(math::floatToHalf(FloatingImpl(fl)));
});
}

void SignBFloat16(const Tensor* input, Tensor* output) {
auto span = gsl::make_span(input->Data<BFloat16>(), input->Shape().Size());
auto output_data = output->template MutableData<BFloat16>();
std::transform(span.cbegin(), span.cend(), output_data, [](const BFloat16& val) {
float fl = val.ToFloat();
return BFloat16(FloatingImpl(fl));
});
}
} // namespace sign_internal

Status Sign::Compute(OpKernelContext* ctx) const {

@askhade askhade Feb 8, 2019

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yuslepukhin yuslepukhin Feb 8, 2019

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! #Closed

using namespace sign_internal;

auto input = ctx->Input<Tensor>(0);
auto output = ctx->Output(0, input->Shape());

auto dtype = input->DataType();
if (dtype == DataTypeImpl::GetType<float>()) {
EigenMap<float>(*output) = EigenMap<float>(*input).array().cwiseSign();
} else if (dtype == DataTypeImpl::GetType<double>()) {
EigenMap<double>(*output) = EigenMap<double>(*input).array().cwiseSign();
} else if (dtype == DataTypeImpl::GetType<int8_t>()) {
EigenMap<int8_t>(*output) = EigenMap<int8_t>(*input).array().cwiseSign();
} else if (dtype == DataTypeImpl::GetType<int16_t>()) {
EigenMap<int16_t>(*output) = EigenMap<int16_t>(*input).array().cwiseSign();
} else if (dtype == DataTypeImpl::GetType<int32_t>()) {
EigenMap<int32_t>(*output) = EigenMap<int32_t>(*input).array().cwiseSign();
} else if (dtype == DataTypeImpl::GetType<int64_t>()) {
EigenMap<int64_t>(*output) = EigenMap<int64_t>(*input).array().cwiseSign();
} else if (dtype == DataTypeImpl::GetType<uint8_t>()) {
EigenMap<uint8_t>(*output) = EigenMap<uint8_t>(*input).array().cwiseSign();
} else if (dtype == DataTypeImpl::GetType<uint16_t>()) {
EigenMap<uint16_t>(*output) = EigenMap<uint16_t>(*input).array().cwiseSign();
} else if (dtype == DataTypeImpl::GetType<uint32_t>()) {
EigenMap<uint32_t>(*output) = EigenMap<uint32_t>(*input).array().cwiseSign();
} else if (dtype == DataTypeImpl::GetType<uint64_t>()) {
EigenMap<uint64_t>(*output) = EigenMap<uint64_t>(*input).array().cwiseSign();
} else if (dtype == DataTypeImpl::GetType<MLFloat16>()) {
SignMLFloat16(input, output);
} else if (dtype == DataTypeImpl::GetType<BFloat16>()) {
SignBFloat16(input, output);
} else {
return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Unsupported input datatype");
}
return Status::OK();
}

} // namespace onnxruntime
1 change: 0 additions & 1 deletion onnxruntime/test/onnx/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,6 @@ int real_main(int argc, char* argv[]) {
{"acosh_example", "opset 9 not supported yet"},
{"atanh_example", "opset 9 not supported yet"},
{"sign_model", "opset 9 not supported yet"},
{"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"},
Expand Down
182 changes: 182 additions & 0 deletions onnxruntime/test/providers/cpu/math/sing_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#include "gtest/gtest.h"
#include "test/providers/provider_test_utils.h"
#include "core/util/math.h"

namespace onnxruntime {
namespace test {

namespace test_sign_internal {

template <class T, class A>
struct make_type {
static T make(A v) {
return T(v);
}
};

template <class A>
struct make_type<MLFloat16, A> {
static MLFloat16 make(A v) {
return MLFloat16(math::floatToHalf(float(v)));
}
};

template <class A>
struct make_type<BFloat16, A> {
static BFloat16 make(A v) {
return BFloat16(float(v));
}
};

template <class T, class OutputIter>
typename std::enable_if<!std::numeric_limits<T>::is_signed>::type
GenerateSequence(OutputIter out) {
for (int i = 0; i < 7; ++i) {
*out = make_type<T, int>::make(i);
++out;
}
}

template <class T, class OutputIter>
typename std::enable_if<std::numeric_limits<T>::is_signed>::type
GenerateSequence(OutputIter out) {
for (int i = -5; i < 2; ++i) {
*out = make_type<T, int>::make(i);
++out;
}
}

template <class T>
inline auto to_testable_type(T v) {
return v;
}

template <>
inline auto to_testable_type(MLFloat16 v) {
return math::halfToFloat(v.val);
}

template <>
inline auto to_testable_type(BFloat16 v) {
return v.ToFloat();
}

template <class T, class ForwardIter, class OutputIter>
typename std::enable_if<!std::numeric_limits<T>::is_signed &&
!std::is_same<T, MLFloat16>::value &&
!std::is_same<T, BFloat16>::value>::type
TestImpl(ForwardIter first, ForwardIter last, OutputIter out) {
std::transform(first, last, out, [](T v) {
auto t = to_testable_type<T>(v);
if (t == 0) {
t = 0;
} else {
t = 1;
}
return make_type<T, decltype(t)>::make(t);
});
}

template <class T, class ForwardIter, class OutputIter>
typename std::enable_if<std::numeric_limits<T>::is_signed ||
std::is_same<T, MLFloat16>::value ||
std::is_same<T, BFloat16>::value>::type
TestImpl(ForwardIter first, ForwardIter last, OutputIter out) {
std::transform(first, last, out, [](T v) {
auto t = to_testable_type<T>(v);
if (t == 0) {
t = 0;
} else if (t > 0) {
t = 1;
} else {
t = -1;
}
return make_type<T, decltype(t)>::make(t);
});
}
} // namespace test_sign_internal

TEST(MathOpTest, Sign_uint64) {
using namespace test_sign_internal;
OpTester test("Sign", 9);

std::vector<int64_t> input_dims{7};
std::vector<uint64_t> input;
GenerateSequence<uint64_t>(std::back_inserter(input));
ASSERT_EQ(input.size(), 7U);
test.AddInput<uint64_t>("input", input_dims, input);

std::vector<uint64_t> output;
TestImpl<uint64_t>(input.cbegin(), input.cend(), std::back_inserter(output));
test.AddOutput<uint64_t>("output", input_dims, output);
test.Run(OpTester::ExpectResult::kExpectSuccess);
}

TEST(MathOpTest, Sign_int64) {
using namespace test_sign_internal;
OpTester test("Sign", 9);

std::vector<int64_t> input_dims{7};
std::vector<int64_t> input;
GenerateSequence<int64_t>(std::back_inserter(input));
ASSERT_EQ(input.size(), 7U);
test.AddInput<int64_t>("input", input_dims, input);

std::vector<int64_t> output;
TestImpl<int64_t>(input.cbegin(), input.cend(), std::back_inserter(output));
test.AddOutput<int64_t>("output", input_dims, output);
test.Run(OpTester::ExpectResult::kExpectSuccess);
}

TEST(MathOpTest, Sign_float) {
using namespace test_sign_internal;
OpTester test("Sign", 9);

std::vector<int64_t> input_dims{7};
std::vector<float> input;
GenerateSequence<float>(std::back_inserter(input));
ASSERT_EQ(input.size(), 7U);
test.AddInput<float>("input", input_dims, input);

std::vector<float> output;
TestImpl<float>(input.cbegin(), input.cend(), std::back_inserter(output));
test.AddOutput<float>("output", input_dims, output);
test.Run(OpTester::ExpectResult::kExpectSuccess);
}

TEST(MathOpTest, Sign_double) {
using namespace test_sign_internal;
OpTester test("Sign", 9);

std::vector<int64_t> input_dims{7};
std::vector<double> input;
GenerateSequence<double>(std::back_inserter(input));
ASSERT_EQ(input.size(), 7U);
test.AddInput<double>("input", input_dims, input);

std::vector<double> output;
TestImpl<double>(input.cbegin(), input.cend(), std::back_inserter(output));
test.AddOutput<double>("output", input_dims, output);
test.Run(OpTester::ExpectResult::kExpectSuccess);
}
TEST(MathOpTest, Sign_MLFloat16) {
using namespace test_sign_internal;
OpTester test("Sign", 9);

std::vector<int64_t> input_dims{7};
std::vector<MLFloat16> input;
GenerateSequence<MLFloat16>(std::back_inserter(input));
ASSERT_EQ(input.size(), 7U);
test.AddInput<MLFloat16>("input", input_dims, input);

std::vector<MLFloat16> output;
TestImpl<MLFloat16>(input.cbegin(), input.cend(), std::back_inserter(output));
test.AddOutput<MLFloat16>("output", input_dims, output);
test.Run(OpTester::ExpectResult::kExpectSuccess);
}

} // namespace test
} // namespace onnxruntime
1 change: 0 additions & 1 deletion onnxruntime/test/python/onnx_backend_test_series.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
'|^test_scatter_without_axis_cpu.*'
'|^test_shrink_hard_cpu.*'
'|^test_shrink_soft_cpu.*'
'|^test_sign_cpu.*'
'|^test_where_example_cpu.*'
'|^test_AvgPool1d_cpu.*'
'|^test_AvgPool1d_stride_cpu.*'
Expand Down