Unverified Commit bfedcd45 authored by Charlie Lin's avatar Charlie Lin Committed by GitHub
Browse files

isnan operator (#1100)

Implements the IsNaN operator, ref, gpu, and onnx parser.
parent 9852aaef
...@@ -114,6 +114,7 @@ register_migraphx_ops( ...@@ -114,6 +114,7 @@ register_migraphx_ops(
identity identity
if_op if_op
im2col im2col
isnan
leaky_relu leaky_relu
less less
load load
......
#ifndef MIGRAPHX_GUARD_OPERATORS_ISNAN_HPP
#define MIGRAPHX_GUARD_OPERATORS_ISNAN_HPP
#include <migraphx/op/unary.hpp>
#include <migraphx/config.hpp>
namespace migraphx {
inline namespace MIGRAPHX_INLINE_NS {
namespace op {
struct isnan : unary<isnan>
{
auto apply() const
{
return [](auto x) { return std::isnan(x); };
}
std::string name() const { return "isnan"; }
shape compute_shape(std::vector<shape> inputs) const
{
return unary<isnan>::compute_shape(std::move(inputs)).with_type(shape::bool_type);
}
};
} // namespace op
} // namespace MIGRAPHX_INLINE_NS
} // namespace migraphx
#endif
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include <migraphx/op/identity.hpp> #include <migraphx/op/identity.hpp>
#include <migraphx/op/if_op.hpp> #include <migraphx/op/if_op.hpp>
#include <migraphx/op/im2col.hpp> #include <migraphx/op/im2col.hpp>
#include <migraphx/op/isnan.hpp>
#include <migraphx/op/leaky_relu.hpp> #include <migraphx/op/leaky_relu.hpp>
#include <migraphx/op/less.hpp> #include <migraphx/op/less.hpp>
#include <migraphx/op/load.hpp> #include <migraphx/op/load.hpp>
......
...@@ -28,6 +28,7 @@ struct parse_generic_op : op_parser<parse_generic_op> ...@@ -28,6 +28,7 @@ struct parse_generic_op : op_parser<parse_generic_op>
{"Floor", "floor"}, {"Floor", "floor"},
{"Gather", "gather"}, {"Gather", "gather"},
{"Identity", "identity"}, {"Identity", "identity"},
{"IsNaN", "isnan"},
{"LeakyRelu", "leaky_relu"}, {"LeakyRelu", "leaky_relu"},
{"Log", "log"}, {"Log", "log"},
{"LRN", "lrn"}, {"LRN", "lrn"},
......
...@@ -59,6 +59,7 @@ MIGRAPHX_DEVICE_MATH(cosh, ::cosh) ...@@ -59,6 +59,7 @@ MIGRAPHX_DEVICE_MATH(cosh, ::cosh)
MIGRAPHX_DEVICE_MATH(erf, ::erf) MIGRAPHX_DEVICE_MATH(erf, ::erf)
MIGRAPHX_DEVICE_MATH(exp, ::exp) MIGRAPHX_DEVICE_MATH(exp, ::exp)
MIGRAPHX_DEVICE_MATH(floor, ::floor) MIGRAPHX_DEVICE_MATH(floor, ::floor)
MIGRAPHX_DEVICE_MATH(isnan, ::isnan)
MIGRAPHX_DEVICE_MATH(log, ::log) MIGRAPHX_DEVICE_MATH(log, ::log)
MIGRAPHX_DEVICE_MATH(pow, ::pow) MIGRAPHX_DEVICE_MATH(pow, ::pow)
MIGRAPHX_DEVICE_MATH(round, ::round) MIGRAPHX_DEVICE_MATH(round, ::round)
...@@ -103,6 +104,7 @@ MIGRAPHX_DEVICE_MATH_HALF(cos, ::cos) ...@@ -103,6 +104,7 @@ MIGRAPHX_DEVICE_MATH_HALF(cos, ::cos)
MIGRAPHX_DEVICE_MATH_HALF(cosh, ::cosh) MIGRAPHX_DEVICE_MATH_HALF(cosh, ::cosh)
MIGRAPHX_DEVICE_MATH_HALF(erf, ::erf) MIGRAPHX_DEVICE_MATH_HALF(erf, ::erf)
MIGRAPHX_DEVICE_MATH_HALF(floor, ::floor) MIGRAPHX_DEVICE_MATH_HALF(floor, ::floor)
MIGRAPHX_DEVICE_MATH_HALF(isnan, ::isnan)
MIGRAPHX_DEVICE_MATH_HALF(pow, ::pow) MIGRAPHX_DEVICE_MATH_HALF(pow, ::pow)
MIGRAPHX_DEVICE_MATH_HALF(round, ::round) MIGRAPHX_DEVICE_MATH_HALF(round, ::round)
MIGRAPHX_DEVICE_MATH_HALF(sin, ::sin) MIGRAPHX_DEVICE_MATH_HALF(sin, ::sin)
...@@ -129,6 +131,7 @@ MIGRAPHX_DEVICE_MATH_VEC(cosh) ...@@ -129,6 +131,7 @@ MIGRAPHX_DEVICE_MATH_VEC(cosh)
MIGRAPHX_DEVICE_MATH_VEC(erf) MIGRAPHX_DEVICE_MATH_VEC(erf)
MIGRAPHX_DEVICE_MATH_VEC(exp) MIGRAPHX_DEVICE_MATH_VEC(exp)
MIGRAPHX_DEVICE_MATH_VEC(floor) MIGRAPHX_DEVICE_MATH_VEC(floor)
MIGRAPHX_DEVICE_MATH_VEC(isnan)
MIGRAPHX_DEVICE_MATH_VEC(log) MIGRAPHX_DEVICE_MATH_VEC(log)
MIGRAPHX_DEVICE_MATH_VEC(pow) MIGRAPHX_DEVICE_MATH_VEC(pow)
MIGRAPHX_DEVICE_MATH_VEC(round) MIGRAPHX_DEVICE_MATH_VEC(round)
......
...@@ -2307,6 +2307,32 @@ def instance_norm_val_3d_test(): ...@@ -2307,6 +2307,32 @@ def instance_norm_val_3d_test():
return ([node], [], [y], [x_tensor, scale_tensor, bias_tensor]) return ([node], [], [y], [x_tensor, scale_tensor, bias_tensor])
@onnx_test
def isnan_float_test():
t1 = helper.make_tensor_value_info('t1', TensorProto.FLOAT, [2, 3])
t2 = helper.make_tensor_value_info('t2', TensorProto.FLOAT, [2, 3])
node = onnx.helper.make_node(
'IsNaN',
inputs=['t1'],
outputs=['t2'],
)
return ([node], [t1], [t2])
@onnx_test
def isnan_half_test():
t1 = helper.make_tensor_value_info('t1', TensorProto.FLOAT16, [2, 3])
t2 = helper.make_tensor_value_info('t2', TensorProto.FLOAT16, [2, 3])
node = onnx.helper.make_node(
'IsNaN',
inputs=['t1'],
outputs=['t2'],
)
return ([node], [t1], [t2])
@onnx_test @onnx_test
def layernorm_test(): def layernorm_test():
x = helper.make_tensor_value_info('0', TensorProto.FLOAT, [1, 1, 5]) x = helper.make_tensor_value_info('0', TensorProto.FLOAT, [1, 1, 5])
......
isnan_float_test:O

t1t2"IsNaNisnan_float_testZ
t1


b
t2


B
\ No newline at end of file
isnan_half_test:N

t1t2"IsNaNisnan_half_testZ
t1



b
t2



B
\ No newline at end of file
...@@ -1929,6 +1929,32 @@ TEST_CASE(if_tuple_test) ...@@ -1929,6 +1929,32 @@ TEST_CASE(if_tuple_test)
EXPECT(p == prog); EXPECT(p == prog);
} }
TEST_CASE(isnan_float_test)
{
migraphx::program p;
auto* mm = p.get_main_module();
migraphx::shape s{migraphx::shape::float_type, {2, 3}};
auto t1 = mm->add_parameter("t1", s);
auto ret = mm->add_instruction(migraphx::make_op("isnan"), t1);
mm->add_return({ret});
auto prog = migraphx::parse_onnx("isnan_float_test.onnx");
EXPECT(p == prog);
}
TEST_CASE(isnan_half_test)
{
migraphx::program p;
auto* mm = p.get_main_module();
migraphx::shape s{migraphx::shape::half_type, {2, 3}};
auto t1 = mm->add_parameter("t1", s);
auto ret = mm->add_instruction(migraphx::make_op("isnan"), t1);
mm->add_return({ret});
auto prog = migraphx::parse_onnx("isnan_half_test.onnx");
EXPECT(p == prog);
}
TEST_CASE(imagescaler_test) TEST_CASE(imagescaler_test)
{ {
migraphx::program p; migraphx::program p;
......
...@@ -122,6 +122,7 @@ def create_backend_test(testname=None, target_device=None): ...@@ -122,6 +122,7 @@ def create_backend_test(testname=None, target_device=None):
backend_test.include(r'.*test_hardswish.*') backend_test.include(r'.*test_hardswish.*')
backend_test.include(r'.*test_identity.*') backend_test.include(r'.*test_identity.*')
backend_test.include(r'.*test_if.*') backend_test.include(r'.*test_if.*')
backend_test.include(r'.*test_isnan.*')
backend_test.include(r'.*test_LeakyReLU*') backend_test.include(r'.*test_LeakyReLU*')
backend_test.include(r'.*test_leakyrelu.*') backend_test.include(r'.*test_leakyrelu.*')
backend_test.include(r'.*test_less.*') backend_test.include(r'.*test_less.*')
......
...@@ -47,6 +47,26 @@ TEST_CASE(argmin_test_nonstd_shape) ...@@ -47,6 +47,26 @@ TEST_CASE(argmin_test_nonstd_shape)
EXPECT(migraphx::verify_range(result_vec, res_gold_vec)); EXPECT(migraphx::verify_range(result_vec, res_gold_vec));
} }
TEST_CASE(isnan_broadcast_test)
{
migraphx::program p;
auto* mm = p.get_main_module();
migraphx::shape s0{migraphx::shape::float_type, {3}};
migraphx::shape s1{migraphx::shape::float_type, {3, 2}};
auto nan_val = std::numeric_limits<float>::quiet_NaN();
std::vector<float> data0 = {1.2, 5.2, nan_val};
auto l0 = mm->add_literal(migraphx::literal{s0, data0});
auto l1 = mm->add_instruction(
migraphx::make_op("broadcast", {{"axis", 0}, {"out_lens", s1.lens()}}), l0);
mm->add_instruction(migraphx::make_op("isnan"), l1);
p.compile(migraphx::ref::target{});
auto result = p.eval({}).back();
std::vector<float> results_vector;
result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); });
std::vector<float> correct = {0, 0, 0, 0, 1, 1};
EXPECT(migraphx::verify_range(results_vector, correct));
}
TEST_CASE(squeeze_transpose_test) TEST_CASE(squeeze_transpose_test)
{ {
migraphx::program p; migraphx::program p;
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include <vector> #include <vector>
#include <cmath> #include <cmath>
#include <random> #include <random>
#include <limits>
#include <migraphx/literal.hpp> #include <migraphx/literal.hpp>
#include <migraphx/op/pooling.hpp> #include <migraphx/op/pooling.hpp>
#include <migraphx/op/batch_norm_inference.hpp> #include <migraphx/op/batch_norm_inference.hpp>
...@@ -1946,6 +1947,45 @@ TEST_CASE(if_pl_test) ...@@ -1946,6 +1947,45 @@ TEST_CASE(if_pl_test)
} }
} }
TEST_CASE(isnan_test)
{
// float test
{
migraphx::program p;
auto* mm = p.get_main_module();
migraphx::shape s{migraphx::shape::float_type, {2, 3}};
auto nan_val = std::numeric_limits<float>::quiet_NaN();
std::vector<float> data0 = {1.2, 5.2, nan_val, nan_val, 0., 100.};
auto l1 = mm->add_literal(migraphx::literal{s, data0});
mm->add_instruction(migraphx::make_op("isnan"), l1);
p.compile(migraphx::ref::target{});
auto result = p.eval({}).back();
std::vector<float> results_vector;
result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); });
std::vector<float> correct = {0, 0, 1, 1, 0, 0};
EXPECT(migraphx::verify_range(results_vector, correct));
}
// half test
{
migraphx::program p;
auto* mm = p.get_main_module();
migraphx::shape s{migraphx::shape::half_type, {2, 3}};
auto nan_val = std::numeric_limits<migraphx::half>::quiet_NaN();
migraphx::half a{1.2};
migraphx::half b{5.2};
std::vector<migraphx::half> data0 = {a, b, nan_val, nan_val, b, a};
auto l1 = mm->add_literal(migraphx::literal{s, data0});
mm->add_instruction(migraphx::make_op("isnan"), l1);
p.compile(migraphx::ref::target{});
auto result = p.eval({}).back();
std::vector<float> results_vector;
result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); });
std::vector<float> correct = {0, 0, 1, 1, 0, 0};
EXPECT(migraphx::verify_range(results_vector, correct));
}
}
TEST_CASE(im2col_3x3_no_pad_identity_test) TEST_CASE(im2col_3x3_no_pad_identity_test)
{ {
std::size_t f[2] = {3, 3}; std::size_t f[2] = {3, 3};
......
#include <limits>
#include "verify_program.hpp"
#include <migraphx/program.hpp>
#include <migraphx/generate.hpp>
#include <migraphx/make_op.hpp>
struct test_isnan_broadcast : verify_program<test_isnan_broadcast>
{
migraphx::program create_program() const
{
migraphx::program p;
auto* mm = p.get_main_module();
auto x = mm->add_parameter("x", migraphx::shape{migraphx::shape::float_type, {2}});
auto s0 = migraphx::shape{migraphx::shape::float_type, {2, 2}};
x = mm->add_instruction(
migraphx::make_op("broadcast", {{"axis", 0}, {"out_lens", s0.lens()}}), x);
std::vector<float> data0{2, std::numeric_limits<float>::quiet_NaN()};
migraphx::shape s1{migraphx::shape::float_type, {1, 2}};
auto l0 = mm->add_literal(migraphx::literal{s1, data0});
x = mm->add_instruction(migraphx::make_op("concat", {{"axis", 0}}), x, l0);
mm->add_instruction(migraphx::make_op("isnan"), x);
return p;
}
};
#include <limits>
#include "verify_program.hpp"
#include <migraphx/program.hpp>
#include <migraphx/generate.hpp>
#include <migraphx/make_op.hpp>
struct test_isnan_float : verify_program<test_isnan_float>
{
migraphx::program create_program() const
{
migraphx::program p;
auto* mm = p.get_main_module();
auto x = mm->add_parameter("x", migraphx::shape{migraphx::shape::float_type, {2}});
auto l0 = mm->add_literal(std::numeric_limits<float>::quiet_NaN());
x = mm->add_instruction(migraphx::make_op("concat", {{"axis", 0}}), x, l0);
mm->add_instruction(migraphx::make_op("isnan"), x);
return p;
}
};
#include <limits>
#include "verify_program.hpp"
#include <migraphx/program.hpp>
#include <migraphx/generate.hpp>
#include <migraphx/make_op.hpp>
#include <migraphx/half.hpp>
struct test_isnan_half : verify_program<test_isnan_half>
{
migraphx::program create_program() const
{
migraphx::program p;
auto* mm = p.get_main_module();
auto x = mm->add_parameter("x", migraphx::shape{migraphx::shape::half_type, {2}});
auto l0 = mm->add_literal(std::numeric_limits<migraphx::half>::quiet_NaN());
x = mm->add_instruction(migraphx::make_op("concat", {{"axis", 0}}), x, l0);
mm->add_instruction(migraphx::make_op("isnan"), x);
return p;
}
};
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment