Skip to content

Commit

Permalink
Revision of Sqrt op and reference implementation (#5446)
Browse files Browse the repository at this point in the history
* Add NGRAPH_RTTI

* Instantiate unary ops type prop tests for Sqrt

* Add sqrt backend tests

* Add rounding for int types to Sqrt reference implementation
  • Loading branch information
mitruska authored Apr 30, 2021
1 parent c99257e commit a7353f4
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 39 deletions.
4 changes: 2 additions & 2 deletions ngraph/core/include/ngraph/op/sqrt.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ namespace ngraph
class NGRAPH_API Sqrt : public util::UnaryElementwiseArithmetic
{
public:
static constexpr NodeTypeInfo type_info{"Sqrt", 0};
const NodeTypeInfo& get_type_info() const override { return type_info; }
NGRAPH_RTTI_DECLARATION;

/// \brief Constructs a square operation.
///
/// \param arg Node that produces the input tensor.
Expand Down
13 changes: 12 additions & 1 deletion ngraph/core/reference/include/ngraph/runtime/reference/sqrt.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <cmath>
#include <cstddef>
#include <type_traits>

namespace ngraph
{
Expand All @@ -14,13 +15,23 @@ namespace ngraph
namespace reference
{
template <typename T>
void sqrt(const T* arg, T* out, size_t count)
typename std::enable_if<!std::is_integral<T>::value>::type
sqrt(const T* arg, T* out, size_t count)
{
for (size_t i = 0; i < count; i++)
{
out[i] = std::sqrt(arg[i]);
}
}
template <typename T>
typename std::enable_if<std::is_integral<T>::value>::type
sqrt(const T* arg, T* out, size_t count)
{
for (size_t i = 0; i < count; i++)
{
out[i] = static_cast<T>(std::round(std::sqrt(arg[i])));
}
}
} // namespace reference
} // namespace runtime
} // namespace ngraph
2 changes: 1 addition & 1 deletion ngraph/core/src/op/sqrt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
using namespace std;
using namespace ngraph;

constexpr NodeTypeInfo op::Sqrt::type_info;
NGRAPH_RTTI_DEFINITION(op::v0::Sqrt, "Sqrt", 0, util::UnaryElementwiseArithmetic);

op::Sqrt::Sqrt(const Output<Node>& arg)
: UnaryElementwiseArithmetic(arg)
Expand Down
104 changes: 70 additions & 34 deletions ngraph/test/backend/sqrt.in.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,56 +20,92 @@
// clang-format on

#include "gtest/gtest.h"
#include "runtime/backend.hpp"
#include "ngraph/runtime/tensor.hpp"
#include "ngraph/ngraph.hpp"
#include "util/all_close.hpp"
#include "util/all_close_f.hpp"
#include "util/ndarray.hpp"
#include "util/test_case.hpp"
#include "util/test_control.hpp"
#include "util/test_tools.hpp"
#include "util/engine/test_engines.hpp"

using namespace std;
using namespace ngraph;

static string s_manifest = "${MANIFEST}";
using TestEngine = test::ENGINE_CLASS_NAME(${BACKEND_NAME});

NGRAPH_TEST(${BACKEND_NAME}, sqrt)
NGRAPH_TEST(${BACKEND_NAME}, sqrt_basic)
{
Shape shape{2, 3};
auto A = make_shared<op::Parameter>(element::f32, shape);
auto f = make_shared<Function>(make_shared<op::Sqrt>(A), ParameterVector{A});
auto input_param = make_shared<op::Parameter>(element::f32, shape);
auto function =
make_shared<Function>(make_shared<op::Sqrt>(input_param), ParameterVector{input_param});

auto backend = runtime::Backend::create("${BACKEND_NAME}");
std::vector<float> input_data{16, 4, 81, 100, 10000, 0};
std::vector<float> expected_result{4, 2, 9, 10, 100, 0};

// Create some tensors for input/output
auto a = backend->create_tensor(element::f32, shape);
copy_data(a, vector<float>{16, 4, 81, 100, 10000, 0});
auto result = backend->create_tensor(element::f32, shape);

auto handle = backend->compile(f);
handle->call_with_validate({result}, {a});
EXPECT_TRUE(test::all_close_f(vector<float>{4, 2, 9, 10, 100, 0}, read_vector<float>(result)));
auto test_case = test::TestCase<TestEngine>(function);
test_case.add_input<float>(input_data);
test_case.add_expected_output<float>(shape, expected_result);
test_case.run();
}

NGRAPH_TEST(${BACKEND_NAME}, sqrt_negative_inputs)
{
Shape shape{4};
auto A = make_shared<op::Parameter>(element::f32, shape);
auto f = make_shared<Function>(make_shared<op::Sqrt>(A), ParameterVector{A});

auto backend = runtime::Backend::create("${BACKEND_NAME}");

// Create some tensors for input/output
auto a = backend->create_tensor(element::f32, shape);
copy_data(a, vector<float>{-1, 4, -81, 100});
auto result = backend->create_tensor(element::f32, shape);

auto handle = backend->compile(f);
handle->call_with_validate({result}, {a});
auto result_val = read_vector<float>(result);
EXPECT_TRUE(isnan(result_val[0]));
EXPECT_FLOAT_EQ(result_val[1], std::sqrt(4));
EXPECT_TRUE(isnan(result_val[2]));
EXPECT_FLOAT_EQ(result_val[3], std::sqrt(100));
auto input_param = make_shared<op::Parameter>(element::f32, shape);
auto function =
make_shared<Function>(make_shared<op::Sqrt>(input_param), ParameterVector{input_param});

std::vector<float> input_data{-1, 4, -81, 100};
std::vector<float> expected_result{NAN, 2, NAN, 10};

auto test_case = test::TestCase<TestEngine>(function);
test_case.add_input<float>(input_data);
test_case.add_expected_output<float>(shape, expected_result);
test_case.run();
}

NGRAPH_TEST(${BACKEND_NAME}, sqrt_integral_inputs)
{
Shape shape{2, 7};
auto input_param = make_shared<op::Parameter>(element::i32, shape);
auto function =
make_shared<Function>(make_shared<op::Sqrt>(input_param), ParameterVector{input_param});

std::vector<int> input_data{4, 7, 9, 10, 80, 55, 6, 1, 23, 233, 256, 474, 1024, 110889};
std::vector<int> expected_result{2, 3, 3, 3, 9, 7, 2, 1, 5, 15, 16, 22, 32, 333};

auto test_case = test::TestCase<TestEngine>(function);
test_case.add_input<int>(input_data);
test_case.add_expected_output<int>(shape, expected_result);
test_case.run();
}

NGRAPH_TEST(${BACKEND_NAME}, sqrt_floating_inputs)
{
Shape shape{2, 7};
auto input_param = make_shared<op::Parameter>(element::f32, shape);
auto function =
make_shared<Function>(make_shared<op::Sqrt>(input_param), ParameterVector{input_param});

std::vector<float> input_data{
4, 7, 9, 10, 80, 55, 6.25, 0.9, 23.33, 233, 256, 473.7891, 1024, 111108.88};
std::vector<float> expected_result{2.,
2.6457512,
3.,
3.1622777,
8.944272,
7.4161983,
2.5,
0.94868326,
4.830114,
15.264338,
16.,
21.766697,
32.,
333.33};

auto test_case = test::TestCase<TestEngine>(function);
test_case.add_input<float>(input_data);
test_case.add_expected_output<float>(shape, expected_result);
test_case.run();
}
2 changes: 1 addition & 1 deletion ngraph/test/type_prop/unary_ops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,6 @@ REGISTER_TYPED_TEST_CASE_P(UnaryOperator,
dynamic_rank_input_shape_3D,
dynamic_rank_input_shape_full);

using Types = ::testing::Types<op::Acos, op::Asin, op::Abs, op::Sin, op::Exp>;
using Types = ::testing::Types<op::Acos, op::Asin, op::Abs, op::Sqrt, op::Sin, op::Exp>;

INSTANTIATE_TYPED_TEST_CASE_P(type_prop, UnaryOperator, Types);

0 comments on commit a7353f4

Please sign in to comment.