HostTensor2Vector (#2027)

* 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 <tomasz.dolbniak@intel.com>

* Fix style.

Co-authored-by: Tomasz Dołbniak <tomasz.dolbniak@intel.com>
This commit is contained in:
Jozef Daniecki 2020-09-04 15:02:14 +02:00 committed by GitHub
parent 696091adea
commit 8e9b733534
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 233 additions and 14 deletions

View File

@ -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 <typename T>
std::string join(const T& v, const std::string& sep = ", ")
@ -393,6 +394,84 @@ std::vector<T> read_vector(std::shared_ptr<ngraph::runtime::Tensor> tv)
return rc;
}
template <typename T>
std::vector<T> 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<ngraph::element::Type_t::boolean>();
return std::vector<T>(p, p + tensor->get_element_count());
}
case ngraph::element::Type_t::bf16:
{
auto p = tensor->get_data_ptr<ngraph::element::Type_t::bf16>();
return std::vector<T>(p, p + tensor->get_element_count());
}
case ngraph::element::Type_t::f16:
{
auto p = tensor->get_data_ptr<ngraph::element::Type_t::f16>();
return std::vector<T>(p, p + tensor->get_element_count());
}
case ngraph::element::Type_t::f32:
{
auto p = tensor->get_data_ptr<ngraph::element::Type_t::f32>();
return std::vector<T>(p, p + tensor->get_element_count());
}
case ngraph::element::Type_t::f64:
{
auto p = tensor->get_data_ptr<ngraph::element::Type_t::f64>();
return std::vector<T>(p, p + tensor->get_element_count());
}
case ngraph::element::Type_t::i8:
{
auto p = tensor->get_data_ptr<ngraph::element::Type_t::i8>();
return std::vector<T>(p, p + tensor->get_element_count());
}
case ngraph::element::Type_t::i16:
{
auto p = tensor->get_data_ptr<ngraph::element::Type_t::i16>();
return std::vector<T>(p, p + tensor->get_element_count());
}
case ngraph::element::Type_t::i32:
{
auto p = tensor->get_data_ptr<ngraph::element::Type_t::i32>();
return std::vector<T>(p, p + tensor->get_element_count());
}
case ngraph::element::Type_t::i64:
{
auto p = tensor->get_data_ptr<ngraph::element::Type_t::i64>();
return std::vector<T>(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<ngraph::element::Type_t::u8>();
return std::vector<T>(p, p + tensor->get_element_count());
}
case ngraph::element::Type_t::u16:
{
auto p = tensor->get_data_ptr<ngraph::element::Type_t::u16>();
return std::vector<T>(p, p + tensor->get_element_count());
}
case ngraph::element::Type_t::u32:
{
auto p = tensor->get_data_ptr<ngraph::element::Type_t::u32>();
return std::vector<T>(p, p + tensor->get_element_count());
}
case ngraph::element::Type_t::u64:
{
auto p = tensor->get_data_ptr<ngraph::element::Type_t::u64>();
return std::vector<T>(p, p + tensor->get_element_count());
}
default: NGRAPH_UNREACHABLE("unsupported element type");
}
}
std::vector<float> NGRAPH_API read_float_vector(std::shared_ptr<ngraph::runtime::Tensor> tv);
std::vector<int64_t> NGRAPH_API read_index_vector(std::shared_ptr<ngraph::runtime::Tensor> tv);

View File

@ -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<element::Type_t::i8>()[0]; break;
case element::Type_t::i16: axis_val = axis->get_data_ptr<element::Type_t::i16>()[0]; break;
case element::Type_t::i32: axis_val = axis->get_data_ptr<element::Type_t::i32>()[0]; break;
case element::Type_t::i64: axis_val = axis->get_data_ptr<element::Type_t::i64>()[0]; break;
case element::Type_t::u8: axis_val = axis->get_data_ptr<element::Type_t::u8>()[0]; break;
case element::Type_t::u16: axis_val = axis->get_data_ptr<element::Type_t::u16>()[0]; break;
case element::Type_t::u32: axis_val = axis->get_data_ptr<element::Type_t::u32>()[0]; break;
case element::Type_t::u64: axis_val = axis->get_data_ptr<element::Type_t::u64>()[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<int64_t>(axis)[0];
if (axis_val < 0)
{
axis_val =

View File

@ -733,3 +733,153 @@ TEST(util, double_to_int)
EXPECT_TRUE(double_to_int<int32_t>(x, floor_func) == 1);
EXPECT_TRUE(double_to_int<int32_t>(x, round_func) == 2);
}
template <typename hosttensor_t, typename vector_t>
void host_tensor_2_vector_test(const vector<hosttensor_t>& input,
const vector<vector_t>& output,
const element::Type& hosttensor_elem_t)
{
auto tensor = make_shared<HostTensor>(hosttensor_elem_t, Shape{2, 2});
tensor->write(input.data(), input.size() * sizeof(hosttensor_t));
auto result = host_tensor_2_vector<vector_t>(tensor);
ASSERT_TRUE(test::all_close(result, output));
}
TEST(util_host_tensor_2_vector, tensor_nullptr)
{
ASSERT_THROW(host_tensor_2_vector<int64_t>(nullptr), ngraph::CheckFailure);
}
TEST(util_host_tensor_2_vector, ht_boolean_2_vec_bool)
{
vector<char> input{1, 0, 1, 0};
vector<bool> output{true, false, true, false};
host_tensor_2_vector_test<decltype(input)::value_type, decltype(output)::value_type>(
input, output, element::boolean);
}
TEST(util_host_tensor_2_vector, ht_boolean_2_vec_int64)
{
vector<char> input{1, 0, 1, 0};
vector<int64_t> output{true, false, true, false};
host_tensor_2_vector_test<decltype(input)::value_type, decltype(output)::value_type>(
input, output, element::boolean);
}
TEST(util_host_tensor_2_vector, ht_i8_2_vec_int64)
{
vector<int8_t> input{
0, 1, std::numeric_limits<int8_t>::min(), std::numeric_limits<int8_t>::max()};
vector<int64_t> output{
0, 1, std::numeric_limits<int8_t>::min(), std::numeric_limits<int8_t>::max()};
host_tensor_2_vector_test<decltype(input)::value_type, decltype(output)::value_type>(
input, output, element::i8);
}
TEST(util_host_tensor_2_vector, ht_i16_2_vec_int64)
{
vector<int16_t> input{
0, 1, std::numeric_limits<int16_t>::min(), std::numeric_limits<int16_t>::max()};
vector<int64_t> output{
0, 1, std::numeric_limits<int16_t>::min(), std::numeric_limits<int16_t>::max()};
host_tensor_2_vector_test<decltype(input)::value_type, decltype(output)::value_type>(
input, output, element::i16);
}
TEST(util_host_tensor_2_vector, ht_i32_2_vec_int64)
{
vector<int32_t> input{
0, 1, std::numeric_limits<int32_t>::min(), std::numeric_limits<int32_t>::max()};
vector<int64_t> output{
0, 1, std::numeric_limits<int32_t>::min(), std::numeric_limits<int32_t>::max()};
host_tensor_2_vector_test<decltype(input)::value_type, decltype(output)::value_type>(
input, output, element::i32);
}
TEST(util_host_tensor_2_vector, ht_i64_2_vec_int64)
{
vector<int64_t> input{
0, 1, std::numeric_limits<int64_t>::min(), std::numeric_limits<int64_t>::max()};
vector<int64_t> output{input};
host_tensor_2_vector_test<decltype(input)::value_type, decltype(output)::value_type>(
input, output, element::i64);
}
TEST(util_host_tensor_2_vector, ht_bf16_2_vec_double)
{
vector<bfloat16> input{
0, 1, std::numeric_limits<bfloat16>::min(), std::numeric_limits<bfloat16>::max()};
vector<double> output{
0, 1, std::numeric_limits<bfloat16>::min(), std::numeric_limits<bfloat16>::max()};
host_tensor_2_vector_test<decltype(input)::value_type, decltype(output)::value_type>(
input, output, element::bf16);
}
TEST(util_host_tensor_2_vector, ht_f16_2_vec_double)
{
vector<float16> input{
0, 1, std::numeric_limits<float16>::min(), std::numeric_limits<float16>::max()};
vector<double> output{
0, 1, std::numeric_limits<float16>::min(), std::numeric_limits<float16>::max()};
host_tensor_2_vector_test<decltype(input)::value_type, decltype(output)::value_type>(
input, output, element::f16);
}
TEST(util_host_tensor_2_vector, ht_f32_2_vec_double)
{
vector<float> input{0, 1, std::numeric_limits<float>::min(), std::numeric_limits<float>::max()};
vector<double> output{
0, 1, std::numeric_limits<float>::min(), std::numeric_limits<float>::max()};
host_tensor_2_vector_test<decltype(input)::value_type, decltype(output)::value_type>(
input, output, element::f32);
}
TEST(util_host_tensor_2_vector, ht_f64_2_vec_double)
{
vector<double> input{
0, 1, std::numeric_limits<double>::min(), std::numeric_limits<double>::max()};
vector<double> output{
0, 1, std::numeric_limits<double>::min(), std::numeric_limits<double>::max()};
host_tensor_2_vector_test<decltype(input)::value_type, decltype(output)::value_type>(
input, output, element::f64);
}
TEST(util_host_tensor_2_vector, ht_u8_2_vec_uint64)
{
vector<uint8_t> input{
0, 1, std::numeric_limits<uint8_t>::min(), std::numeric_limits<uint8_t>::max()};
vector<uint64_t> output{
0, 1, std::numeric_limits<uint8_t>::min(), std::numeric_limits<uint8_t>::max()};
host_tensor_2_vector_test<decltype(input)::value_type, decltype(output)::value_type>(
input, output, element::u8);
}
TEST(util_host_tensor_2_vector, ht_u16_2_vec_uint64)
{
vector<uint16_t> input{
0, 1, std::numeric_limits<uint16_t>::min(), std::numeric_limits<uint16_t>::max()};
vector<uint64_t> output{
0, 1, std::numeric_limits<uint16_t>::min(), std::numeric_limits<uint16_t>::max()};
host_tensor_2_vector_test<decltype(input)::value_type, decltype(output)::value_type>(
input, output, element::u16);
}
TEST(util_host_tensor_2_vector, ht_u32_2_vec_uint64)
{
vector<uint32_t> input{
0, 1, std::numeric_limits<uint32_t>::min(), std::numeric_limits<uint32_t>::max()};
vector<uint64_t> output{
0, 1, std::numeric_limits<uint32_t>::min(), std::numeric_limits<uint32_t>::max()};
host_tensor_2_vector_test<decltype(input)::value_type, decltype(output)::value_type>(
input, output, element::u32);
}
TEST(util_host_tensor_2_vector, ht_u64_2_vec_uint64)
{
vector<uint64_t> input{
0, 1, std::numeric_limits<uint64_t>::min(), std::numeric_limits<uint64_t>::max()};
vector<uint64_t> output{input};
host_tensor_2_vector_test<decltype(input)::value_type, decltype(output)::value_type>(
input, output, element::u64);
}