From 8e9b733534b5f2b59788e4856b66d599917411a7 Mon Sep 17 00:00:00 2001 From: Jozef Daniecki Date: Fri, 4 Sep 2020 15:02:14 +0200 Subject: [PATCH] HostTensor2Vector (#2027) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add host_tesnor_2_vector() implementation and unit tests. One reference OP refactored to use it. * Ngraph assertion message refactored. Co-authored-by: Tomasz Dołbniak * Fix style. Co-authored-by: Tomasz Dołbniak --- ngraph/core/include/ngraph/util.hpp | 81 +++++++++++++- ngraph/core/src/op/scatter_update.cpp | 16 +-- ngraph/test/util.cpp | 150 ++++++++++++++++++++++++++ 3 files changed, 233 insertions(+), 14 deletions(-) diff --git a/ngraph/core/include/ngraph/util.hpp b/ngraph/core/include/ngraph/util.hpp index cf0ec9cd97f..1b6b5a2fbef 100644 --- a/ngraph/core/include/ngraph/util.hpp +++ b/ngraph/core/include/ngraph/util.hpp @@ -34,6 +34,7 @@ #include "ngraph/axis_vector.hpp" #include "ngraph/graph_util.hpp" #include "ngraph/node.hpp" +#include "ngraph/runtime/host_tensor.hpp" #include "ngraph/runtime/tensor.hpp" #include "ngraph/shape.hpp" @@ -48,7 +49,7 @@ namespace ngraph class Backend; class Value; class Tensor; - } + } // namespace runtime template std::string join(const T& v, const std::string& sep = ", ") @@ -393,6 +394,84 @@ std::vector read_vector(std::shared_ptr tv) return rc; } +template +std::vector host_tensor_2_vector(ngraph::HostTensorPtr tensor) +{ + NGRAPH_CHECK(tensor != nullptr, + "Invalid Tensor received, can't read the data from a null pointer."); + + switch (tensor->get_element_type()) + { + case ngraph::element::Type_t::boolean: + { + auto p = tensor->get_data_ptr(); + return std::vector(p, p + tensor->get_element_count()); + } + case ngraph::element::Type_t::bf16: + { + auto p = tensor->get_data_ptr(); + return std::vector(p, p + tensor->get_element_count()); + } + case ngraph::element::Type_t::f16: + { + auto p = tensor->get_data_ptr(); + return std::vector(p, p + tensor->get_element_count()); + } + case ngraph::element::Type_t::f32: + { + auto p = tensor->get_data_ptr(); + return std::vector(p, p + tensor->get_element_count()); + } + case ngraph::element::Type_t::f64: + { + auto p = tensor->get_data_ptr(); + return std::vector(p, p + tensor->get_element_count()); + } + case ngraph::element::Type_t::i8: + { + auto p = tensor->get_data_ptr(); + return std::vector(p, p + tensor->get_element_count()); + } + case ngraph::element::Type_t::i16: + { + auto p = tensor->get_data_ptr(); + return std::vector(p, p + tensor->get_element_count()); + } + case ngraph::element::Type_t::i32: + { + auto p = tensor->get_data_ptr(); + return std::vector(p, p + tensor->get_element_count()); + } + case ngraph::element::Type_t::i64: + { + auto p = tensor->get_data_ptr(); + return std::vector(p, p + tensor->get_element_count()); + } + case ngraph::element::Type_t::u1: NGRAPH_CHECK(false, "u1 element type is unsupported"); break; + case ngraph::element::Type_t::u8: + { + auto p = tensor->get_data_ptr(); + return std::vector(p, p + tensor->get_element_count()); + } + case ngraph::element::Type_t::u16: + { + auto p = tensor->get_data_ptr(); + return std::vector(p, p + tensor->get_element_count()); + } + case ngraph::element::Type_t::u32: + { + auto p = tensor->get_data_ptr(); + return std::vector(p, p + tensor->get_element_count()); + } + case ngraph::element::Type_t::u64: + { + auto p = tensor->get_data_ptr(); + return std::vector(p, p + tensor->get_element_count()); + } + default: NGRAPH_UNREACHABLE("unsupported element type"); + } +} + std::vector NGRAPH_API read_float_vector(std::shared_ptr tv); std::vector NGRAPH_API read_index_vector(std::shared_ptr tv); diff --git a/ngraph/core/src/op/scatter_update.cpp b/ngraph/core/src/op/scatter_update.cpp index 1ebf07e5299..6aef517d32a 100644 --- a/ngraph/core/src/op/scatter_update.cpp +++ b/ngraph/core/src/op/scatter_update.cpp @@ -53,20 +53,10 @@ bool op::v3::ScatterUpdate::evaluate(const HostTensorVector& outputs, const auto elem_size = data->get_element_type().size(); out->set_shape(data->get_shape()); - int64_t axis_val = 0; - switch (axis->get_element_type()) - { - case element::Type_t::i8: axis_val = axis->get_data_ptr()[0]; break; - case element::Type_t::i16: axis_val = axis->get_data_ptr()[0]; break; - case element::Type_t::i32: axis_val = axis->get_data_ptr()[0]; break; - case element::Type_t::i64: axis_val = axis->get_data_ptr()[0]; break; - case element::Type_t::u8: axis_val = axis->get_data_ptr()[0]; break; - case element::Type_t::u16: axis_val = axis->get_data_ptr()[0]; break; - case element::Type_t::u32: axis_val = axis->get_data_ptr()[0]; break; - case element::Type_t::u64: axis_val = axis->get_data_ptr()[0]; break; - default: throw ngraph_error("axis element type is not integral data type"); - } + NGRAPH_CHECK(axis->get_element_type().is_integral_number(), + "axis element type is not integral data type"); + int64_t axis_val = host_tensor_2_vector(axis)[0]; if (axis_val < 0) { axis_val = diff --git a/ngraph/test/util.cpp b/ngraph/test/util.cpp index 5dea0071f5a..a85ab16921e 100644 --- a/ngraph/test/util.cpp +++ b/ngraph/test/util.cpp @@ -733,3 +733,153 @@ TEST(util, double_to_int) EXPECT_TRUE(double_to_int(x, floor_func) == 1); EXPECT_TRUE(double_to_int(x, round_func) == 2); } + +template +void host_tensor_2_vector_test(const vector& input, + const vector& output, + const element::Type& hosttensor_elem_t) +{ + auto tensor = make_shared(hosttensor_elem_t, Shape{2, 2}); + tensor->write(input.data(), input.size() * sizeof(hosttensor_t)); + auto result = host_tensor_2_vector(tensor); + + ASSERT_TRUE(test::all_close(result, output)); +} + +TEST(util_host_tensor_2_vector, tensor_nullptr) +{ + ASSERT_THROW(host_tensor_2_vector(nullptr), ngraph::CheckFailure); +} + +TEST(util_host_tensor_2_vector, ht_boolean_2_vec_bool) +{ + vector input{1, 0, 1, 0}; + vector output{true, false, true, false}; + host_tensor_2_vector_test( + input, output, element::boolean); +} + +TEST(util_host_tensor_2_vector, ht_boolean_2_vec_int64) +{ + vector input{1, 0, 1, 0}; + vector output{true, false, true, false}; + host_tensor_2_vector_test( + input, output, element::boolean); +} + +TEST(util_host_tensor_2_vector, ht_i8_2_vec_int64) +{ + vector input{ + 0, 1, std::numeric_limits::min(), std::numeric_limits::max()}; + vector output{ + 0, 1, std::numeric_limits::min(), std::numeric_limits::max()}; + host_tensor_2_vector_test( + input, output, element::i8); +} + +TEST(util_host_tensor_2_vector, ht_i16_2_vec_int64) +{ + vector input{ + 0, 1, std::numeric_limits::min(), std::numeric_limits::max()}; + vector output{ + 0, 1, std::numeric_limits::min(), std::numeric_limits::max()}; + host_tensor_2_vector_test( + input, output, element::i16); +} + +TEST(util_host_tensor_2_vector, ht_i32_2_vec_int64) +{ + vector input{ + 0, 1, std::numeric_limits::min(), std::numeric_limits::max()}; + vector output{ + 0, 1, std::numeric_limits::min(), std::numeric_limits::max()}; + host_tensor_2_vector_test( + input, output, element::i32); +} + +TEST(util_host_tensor_2_vector, ht_i64_2_vec_int64) +{ + vector input{ + 0, 1, std::numeric_limits::min(), std::numeric_limits::max()}; + vector output{input}; + host_tensor_2_vector_test( + input, output, element::i64); +} + +TEST(util_host_tensor_2_vector, ht_bf16_2_vec_double) +{ + vector input{ + 0, 1, std::numeric_limits::min(), std::numeric_limits::max()}; + vector output{ + 0, 1, std::numeric_limits::min(), std::numeric_limits::max()}; + host_tensor_2_vector_test( + input, output, element::bf16); +} + +TEST(util_host_tensor_2_vector, ht_f16_2_vec_double) +{ + vector input{ + 0, 1, std::numeric_limits::min(), std::numeric_limits::max()}; + vector output{ + 0, 1, std::numeric_limits::min(), std::numeric_limits::max()}; + host_tensor_2_vector_test( + input, output, element::f16); +} + +TEST(util_host_tensor_2_vector, ht_f32_2_vec_double) +{ + vector input{0, 1, std::numeric_limits::min(), std::numeric_limits::max()}; + vector output{ + 0, 1, std::numeric_limits::min(), std::numeric_limits::max()}; + host_tensor_2_vector_test( + input, output, element::f32); +} + +TEST(util_host_tensor_2_vector, ht_f64_2_vec_double) +{ + vector input{ + 0, 1, std::numeric_limits::min(), std::numeric_limits::max()}; + vector output{ + 0, 1, std::numeric_limits::min(), std::numeric_limits::max()}; + host_tensor_2_vector_test( + input, output, element::f64); +} + +TEST(util_host_tensor_2_vector, ht_u8_2_vec_uint64) +{ + vector input{ + 0, 1, std::numeric_limits::min(), std::numeric_limits::max()}; + vector output{ + 0, 1, std::numeric_limits::min(), std::numeric_limits::max()}; + host_tensor_2_vector_test( + input, output, element::u8); +} + +TEST(util_host_tensor_2_vector, ht_u16_2_vec_uint64) +{ + vector input{ + 0, 1, std::numeric_limits::min(), std::numeric_limits::max()}; + vector output{ + 0, 1, std::numeric_limits::min(), std::numeric_limits::max()}; + host_tensor_2_vector_test( + input, output, element::u16); +} + +TEST(util_host_tensor_2_vector, ht_u32_2_vec_uint64) +{ + vector input{ + 0, 1, std::numeric_limits::min(), std::numeric_limits::max()}; + vector output{ + 0, 1, std::numeric_limits::min(), std::numeric_limits::max()}; + host_tensor_2_vector_test( + input, output, element::u32); +} + +TEST(util_host_tensor_2_vector, ht_u64_2_vec_uint64) +{ + vector input{ + 0, 1, std::numeric_limits::min(), std::numeric_limits::max()}; + vector output{input}; + host_tensor_2_vector_test( + input, output, element::u64); +}