// Copyright (C) 2018-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // #include #include #include #include #include "gtest/gtest.h" #include "ngraph/file_util.hpp" #include "ngraph/function.hpp" #include "ngraph/graph_util.hpp" #include "ngraph/ngraph.hpp" #include "ngraph/op/util/op_annotations.hpp" #include "ngraph/opsets/opset3.hpp" #include "ngraph/opsets/opset6.hpp" #include "ngraph/opsets/opset8.hpp" #include "ngraph/pass/manager.hpp" #include "ngraph/pass/visualize_tree.hpp" #include "util/all_close.hpp" #include "util/ndarray.hpp" NGRAPH_SUPPRESS_DEPRECATED_START using namespace std; using namespace ngraph; TEST(util, split) { { string s1 = "this,is,a,test"; auto r1 = split(s1, ','); ASSERT_EQ(4, r1.size()); EXPECT_STRCASEEQ("this", r1[0].c_str()); EXPECT_STRCASEEQ("is", r1[1].c_str()); EXPECT_STRCASEEQ("a", r1[2].c_str()); EXPECT_STRCASEEQ("test", r1[3].c_str()); } { string s1 = "this,is,a,test,"; auto r1 = split(s1, ','); ASSERT_EQ(5, r1.size()); EXPECT_STRCASEEQ("this", r1[0].c_str()); EXPECT_STRCASEEQ("is", r1[1].c_str()); EXPECT_STRCASEEQ("a", r1[2].c_str()); EXPECT_STRCASEEQ("test", r1[3].c_str()); EXPECT_STRCASEEQ("", r1[4].c_str()); } { string s1 = ",this,is,a,test"; auto r1 = split(s1, ','); ASSERT_EQ(5, r1.size()); EXPECT_STRCASEEQ("", r1[0].c_str()); EXPECT_STRCASEEQ("this", r1[1].c_str()); EXPECT_STRCASEEQ("is", r1[2].c_str()); EXPECT_STRCASEEQ("a", r1[3].c_str()); EXPECT_STRCASEEQ("test", r1[4].c_str()); } { string s1 = "this,,is,a,test"; auto r1 = split(s1, ','); ASSERT_EQ(5, r1.size()); EXPECT_STRCASEEQ("this", r1[0].c_str()); EXPECT_STRCASEEQ("", r1[1].c_str()); EXPECT_STRCASEEQ("is", r1[2].c_str()); EXPECT_STRCASEEQ("a", r1[3].c_str()); EXPECT_STRCASEEQ("test", r1[4].c_str()); } { string s1 = "this"; auto r1 = split(s1, ','); ASSERT_EQ(1, r1.size()); EXPECT_STRCASEEQ("this", r1[0].c_str()); } { string s1 = ""; auto r1 = split(s1, ','); ASSERT_EQ(1, r1.size()); EXPECT_STRCASEEQ("", r1[0].c_str()); } } TEST(DISABLED_util, dump) { string text = "this is a text string used to test the dump function."; dump(cout, text.data(), text.size()); } #ifdef _WIN32 # ifndef NOMINMAX # define NOMINMAX # endif # include "windows.h" # define usleep(a) Sleep(a / 1000) #endif TEST(util, stopwatch) { stopwatch t1; t1.start(); usleep(1000); t1.stop(); t1.start(); usleep(1000); t1.stop(); t1.start(); usleep(1000); t1.stop(); EXPECT_EQ(3, t1.get_call_count()); EXPECT_GT(t1.get_total_microseconds(), t1.get_microseconds()); } TEST(util, trim) { EXPECT_STREQ("test", trim("test").c_str()); EXPECT_STREQ("test", trim(" test").c_str()); EXPECT_STREQ("test", trim("test ").c_str()); EXPECT_STREQ("test", trim(" test ").c_str()); EXPECT_STREQ("test", trim(" test ").c_str()); EXPECT_STREQ("test", trim("\ttest").c_str()); EXPECT_STREQ("test", trim("test\t").c_str()); EXPECT_STREQ("test", trim("\ttest\t").c_str()); EXPECT_STREQ("test", trim(" \t test \t ").c_str()); } TEST(util, all_close) { auto backend = runtime::Backend::create("INTERPRETER"); // Create some tensors for input/output auto a = backend->create_tensor(element::f32, Shape{2, 3}); auto b = backend->create_tensor(element::f32, Shape{2, 3}); copy_data(a, test::NDArray({{1, 2, 3}, {3, 4, 5}}).get_vector()); copy_data(b, test::NDArray({{1, 2, 3}, {3, 4, 5}}).get_vector()); EXPECT_TRUE(ngraph::test::all_close(a, b)); auto c = backend->create_tensor(element::f32, Shape{2, 3}); copy_data(c, test::NDArray({{1.1f, 2, 3}, {3, 4, 5}}).get_vector()); EXPECT_FALSE(ngraph::test::all_close(c, a, 0, .05f)); EXPECT_TRUE(ngraph::test::all_close(c, a, 0, .11f)); EXPECT_FALSE(ngraph::test::all_close(c, a, .05f, 0)); EXPECT_TRUE(ngraph::test::all_close(c, a, .11f, 0)); } class CloneTest : public ::testing::Test { public: // (A + B) * C Shape shape = Shape{2, 2}; std::shared_ptr A = make_shared(element::f32, shape); std::shared_ptr B = make_shared(element::f32, shape); std::shared_ptr C = make_shared(element::f32, shape); std::shared_ptr AplusB = make_shared(A, B); std::shared_ptr AplusBtimesC = make_shared(AplusB, C); NodeMap node_map; std::vector> nodes; std::shared_ptr func = make_shared(AplusBtimesC, ParameterVector{A, B, C}, "f"); void SetUp() override { nodes.push_back(AplusBtimesC); nodes.push_back(AplusB); nodes.push_back(A); nodes.push_back(B); nodes.push_back(C); } bool CompareNodeVector(const std::vector>& orig, const std::vector>& clone, const NodeMap& nm) { if (orig.size() != clone.size()) { return false; } auto origit = orig.begin(); auto cloneit = clone.begin(); while (origit != orig.end() && cloneit != clone.end()) { if (*cloneit != nm.at((*origit).get())) { return false; } ++origit; ++cloneit; } return true; } }; TEST_F(CloneTest, clone_nodes_full) { auto cloned_nodes = clone_nodes(nodes, node_map); ASSERT_TRUE(CompareNodeVector(nodes, cloned_nodes, node_map)); ASSERT_NE(nullptr, ov::as_type_ptr(node_map.at(A.get()))); ASSERT_NE(nullptr, ov::as_type_ptr(node_map.at(B.get()))); ASSERT_NE(nullptr, ov::as_type_ptr(node_map.at(C.get()))); ASSERT_NE(nullptr, ov::as_type_ptr(node_map.at(AplusB.get()))); ASSERT_NE(nullptr, ov::as_type_ptr(node_map.at(AplusBtimesC.get()))); auto sorted_nodes = topological_sort(nodes); auto sorted_cloned_nodes = topological_sort(cloned_nodes); ASSERT_TRUE(CompareNodeVector(sorted_nodes, sorted_cloned_nodes, node_map)); } TEST_F(CloneTest, clone_nodes_partial) { // map A -> A' prior to clone auto Aprime = make_shared(element::f32, shape); node_map[A.get()] = Aprime; auto cloned_nodes = clone_nodes(nodes, node_map); ASSERT_TRUE(CompareNodeVector(nodes, cloned_nodes, node_map)); // ensure A -> A' after clone ASSERT_EQ(Aprime, node_map.at(A.get())); } TEST_F(CloneTest, clone_function_full) { auto cloned_func = clone_function(*func, node_map); ASSERT_TRUE(CompareNodeVector(func->get_ops(), cloned_func->get_ops(), node_map)); } TEST(graph_util, clone_multiple_results) { Shape shape{2, 2}; auto A = make_shared(element::f32, shape); auto B = make_shared(element::f32, shape); auto C = make_shared(element::f32, shape); auto A_add_B = make_shared(A, B); auto A_add_B_mul_C = make_shared(A_add_B, C); auto f = make_shared(NodeVector{A_add_B, A_add_B_mul_C}, ParameterVector{A, B, C}); auto copy = clone_function(*f); } TEST(graph_util, clone_function_variables_dynamic) { auto c_fp16 = make_shared(element::f16, Shape{3}, std::vector{0}); auto variable = make_shared(VariableInfo{PartialShape::dynamic(), element::dynamic, "var_1"}); auto read_value = make_shared(c_fp16, variable); auto assign = make_shared(read_value, variable); auto f = make_shared(OutputVector{assign}, ParameterVector{}, VariableVector{variable}); auto copy = clone_function(*f); auto c_fp32 = make_shared(element::f32, Shape{3}, std::vector{0}); for (const auto& op : copy->get_ops()) { if (auto constant = std::dynamic_pointer_cast(op)) { ngraph::replace_node(constant, c_fp32); } } copy->validate_nodes_and_infer_types(); copy = clone_function(*f); } TEST(graph_util, clone_function_variables_validate_partially) { auto c_fp16 = make_shared(element::f16, Shape{3}, std::vector{0}); auto read_value = make_shared(c_fp16, "var_1"); auto assign = make_shared(read_value, "var_1"); auto res = make_shared(read_value); auto f = make_shared(ResultVector{res}, SinkVector{assign}, ParameterVector{}); f->validate_nodes_and_infer_types(); NodeMap nm; auto copy = clone_function(*f, nm); nm[assign.get()]->validate_and_infer_types(); } TEST(graph_util, clone_rt_info) { const std::string testAffinity = "CPU"; std::shared_ptr original_f; { ngraph::PartialShape shape({1, 84}); ngraph::element::Type type(ngraph::element::Type_t::f32); auto param = std::make_shared(type, shape); auto matMulWeights = ngraph::opset6::Constant::create(ngraph::element::Type_t::f32, {10, 84}, {1}); auto shapeOf = std::make_shared(matMulWeights); auto gConst1 = ngraph::opset6::Constant::create(ngraph::element::Type_t::i32, {1}, {1}); auto gConst2 = ngraph::opset6::Constant::create(ngraph::element::Type_t::i64, {}, {0}); auto gather = std::make_shared(shapeOf, gConst1, gConst2); auto concatConst = ngraph::opset6::Constant::create(ngraph::element::Type_t::i64, {1}, {1}); auto concat = std::make_shared(ngraph::NodeVector{concatConst, gather}, 0); auto relu = std::make_shared(param); auto reshape = std::make_shared(relu, concat, false); auto matMul = std::make_shared(reshape, matMulWeights, false, true); auto matMulBias = ngraph::opset6::Constant::create(ngraph::element::Type_t::f32, {1, 10}, {1}); auto addBias = std::make_shared(matMul, matMulBias); auto result = std::make_shared(addBias); ngraph::ParameterVector params = {param}; ngraph::ResultVector results = {result}; original_f = std::make_shared(results, params); } std::unordered_map affinity; for (auto&& node : original_f->get_ordered_ops()) { auto& nodeInfo = node->get_rt_info(); nodeInfo["affinity"] = std::make_shared>(testAffinity); affinity[node->get_friendly_name()] = testAffinity; for (auto&& output : node->outputs()) { auto& outputInfo = output.get_rt_info(); outputInfo["affinity"] = std::make_shared>(testAffinity); } } auto clonedFunction = ngraph::clone_function(*original_f); for (auto&& node : clonedFunction->get_ordered_ops()) { auto& nodeInfo = node->get_rt_info(); auto itInfo = nodeInfo.find("affinity"); ASSERT_TRUE(itInfo != nodeInfo.end()); auto value = ngraph::as_type_ptr>(itInfo->second)->get(); ASSERT_TRUE(affinity.find(node->get_friendly_name()) != affinity.end()); ASSERT_TRUE(affinity[node->get_friendly_name()] == value); for (auto&& output : node->outputs()) { auto& outputInfo = output.get_rt_info(); ASSERT_TRUE(outputInfo.count("affinity")); } } } TEST(util, round_up) { EXPECT_EQ(0, round_up(0, 4)); EXPECT_EQ(4, round_up(1, 4)); EXPECT_EQ(4, round_up(2, 4)); EXPECT_EQ(4, round_up(3, 4)); EXPECT_EQ(4, round_up(4, 4)); EXPECT_EQ(8, round_up(5, 4)); } TEST(util, parse_string) { EXPECT_FLOAT_EQ(2, parse_string("2")); EXPECT_FLOAT_EQ(2.125, parse_string("2.125")); EXPECT_FLOAT_EQ(numeric_limits::infinity(), parse_string("INFINITY")); EXPECT_FLOAT_EQ(numeric_limits::infinity(), parse_string("infinity")); EXPECT_FLOAT_EQ(-numeric_limits::infinity(), parse_string("-INFINITY")); EXPECT_TRUE(isnan(parse_string("NaN"))); EXPECT_FLOAT_EQ(2, parse_string("2")); EXPECT_FLOAT_EQ(2.125, parse_string("2.125")); EXPECT_FLOAT_EQ(numeric_limits::infinity(), parse_string("INFINITY")); EXPECT_FLOAT_EQ(numeric_limits::infinity(), parse_string("infinity")); EXPECT_FLOAT_EQ(-numeric_limits::infinity(), parse_string("-INFINITY")); EXPECT_TRUE(std::isnan(parse_string("NaN"))); } TEST(graph_util, get_subgraph_outputs_trivial_tests) { auto outputs = ngraph::get_subgraph_outputs(NodeVector{}, NodeVector{}); ASSERT_EQ(outputs.size(), 0); Shape shape{}; auto A = make_shared(element::f32, shape); auto absn = make_shared(A); auto neg_absn = make_shared(absn); outputs = ngraph::get_subgraph_outputs(NodeVector{A}, NodeVector{}); ASSERT_EQ(outputs, (NodeVector{A})); outputs = ngraph::get_subgraph_outputs(NodeVector{A}, NodeVector{A}); ASSERT_EQ(outputs, (NodeVector{})); outputs = ngraph::get_subgraph_outputs(NodeVector{A, absn}, NodeVector{}); ASSERT_EQ(outputs, (NodeVector{absn})); auto B = make_shared(element::f32, shape); auto abs_b = make_shared(B); auto neg_b = make_shared(B); auto abs_b_neg = make_shared(abs_b); outputs = ngraph::get_subgraph_outputs(NodeVector{B, abs_b}, NodeVector{}); ASSERT_EQ(outputs, (NodeVector{B, abs_b})); outputs = ngraph::get_subgraph_outputs(NodeVector{B, abs_b}, NodeVector{B}); ASSERT_EQ(outputs, (NodeVector{abs_b})); outputs = ngraph::get_subgraph_outputs(NodeVector{B, abs_b, abs_b_neg}, NodeVector{}); ASSERT_EQ(outputs, (NodeVector{B})); auto add_b = make_shared(neg_b, abs_b_neg); outputs = ngraph::get_subgraph_outputs(NodeVector{B, abs_b, neg_b, abs_b_neg, add_b}, NodeVector{}); ASSERT_EQ(outputs, (NodeVector{})); // now add_b uses abs_b_neg outputs = ngraph::get_subgraph_outputs(NodeVector{B, abs_b, abs_b_neg}, NodeVector{}); ASSERT_EQ(outputs, (NodeVector{B, abs_b_neg})); } TEST(graph_util, test_subgraph_topological_sort) { Shape shape{2, 2}; auto A = make_shared(element::f32, shape); auto B = make_shared(element::f32, shape); auto C = make_shared(element::f32, shape); auto add = make_shared(A, B); auto mul = make_shared(C, add); auto result = make_shared(mul); auto sorted = ngraph::subgraph_topological_sort(NodeVector{mul, add, A}); std::vector> expected{A, add, mul}; ASSERT_EQ(expected, sorted); } TEST(graph_util, test_subgraph_topological_sort_control_dependencies) { Shape shape{2, 2}; auto A = make_shared(element::f32, shape); auto B = make_shared(element::f32, shape); auto C = make_shared(element::f32, shape); auto D = make_shared(A); auto E = make_shared(B); auto add = make_shared(A, B); add->add_control_dependency(D); add->add_control_dependency(E); auto mul = make_shared(C, add); auto result = make_shared(mul); auto sorted = ngraph::subgraph_topological_sort(NodeVector{mul, add, A, D}); std::vector> expected{A, D, add, mul}; ASSERT_EQ(expected, sorted); } TEST(util, enum_mask_construction) { enum class Type : uint32_t { a = 0x1, b = 1 << 1, c = 1 << 2, d = 1 << 3 }; { EnumMask m; EXPECT_EQ(0, m.value()); } { EnumMask m(Type::c); EXPECT_EQ(static_cast(Type::c), m.value()); } { EnumMask a(Type::c); EnumMask b{a}; EXPECT_EQ(a.value(), b.value()); } { EnumMask a{Type::a, Type::c, Type::d}; EXPECT_EQ((static_cast(Type::a) | static_cast(Type::c) | static_cast(Type::d)), a.value()); } } TEST(util, enum_mask_set_clear) { enum class Type : uint32_t { a = 0x1, b = 1 << 1, c = 1 << 2, d = 1 << 3 }; EnumMask m; m.set(Type::b); EXPECT_EQ(static_cast(Type::b), m.value()); m.set(Type::c); EXPECT_EQ(static_cast(Type::b) | static_cast(Type::c), m.value()); m.clear(Type::b); EXPECT_EQ(static_cast(Type::c), m.value()); m.clear_all(); EXPECT_EQ(0, m.value()); m.set(Type::d); m.set(Type::b); EXPECT_TRUE(m.is_set(Type::d)); EXPECT_FALSE(m.is_set(Type::a)); EXPECT_TRUE(m.is_set(Type::b)); EXPECT_FALSE(m.is_set(Type::c)); EXPECT_FALSE(m.is_set({Type::a, Type::b})); EXPECT_FALSE(m.is_set({Type::c, Type::d})); EXPECT_FALSE(m.is_set({Type::a, Type::c})); EXPECT_TRUE(m.is_set({Type::b, Type::d})); EXPECT_FALSE(m.is_clear(Type::d)); EXPECT_TRUE(m.is_clear(Type::a)); EXPECT_FALSE(m.is_clear(Type::b)); EXPECT_TRUE(m.is_clear(Type::c)); EXPECT_FALSE(m.is_clear({Type::c, Type::d})); EXPECT_FALSE(m.is_clear({Type::a, Type::b})); EXPECT_TRUE(m.is_clear({Type::a, Type::c})); EXPECT_FALSE(m.is_clear({Type::b, Type::d})); EXPECT_TRUE(m.is_any_set({Type::a, Type::b})); EXPECT_TRUE(m.is_any_set({Type::a, Type::d})); EXPECT_TRUE(m.is_any_set({Type::b, Type::c})); EXPECT_TRUE(m.is_any_set({Type::c, Type::d})); EXPECT_FALSE(m.is_any_set({Type::a, Type::c})); EXPECT_TRUE(m.is_any_clear({Type::c, Type::d})); EXPECT_TRUE(m.is_any_clear({Type::a, Type::b})); EXPECT_TRUE(m.is_any_clear({Type::a, Type::c})); EXPECT_TRUE(m.is_any_clear({Type::b, Type::c})); EXPECT_FALSE(m.is_any_clear({Type::b, Type::d})); m.set(Type::a); EXPECT_FALSE(m.is_clear(Type::a)); EXPECT_FALSE(m.is_clear(Type::b)); EXPECT_TRUE(m.is_clear(Type::c)); EXPECT_FALSE(m.is_clear(Type::d)); } TEST(util, enum_mask_operators) { enum class Type : uint32_t { a = 0x1, b = 1 << 1, c = 1 << 2, d = 1 << 3 }; EnumMask m; m = Type::b; EXPECT_EQ(static_cast(Type::b), m.value()); EXPECT_TRUE(m[Type::b]); EXPECT_FALSE(m[Type::a]); EXPECT_FALSE(m[Type::c]); m |= Type::c; EXPECT_EQ(static_cast(Type::b) | static_cast(Type::c), m.value()); m &= Type::d; EXPECT_EQ(0, m.value()); m |= Type::a; m |= Type::c; EXPECT_TRUE(m.is_set(Type::a)); EXPECT_FALSE(m.is_set(Type::b)); EXPECT_TRUE(m.is_set(Type::c)); EXPECT_FALSE(m.is_set(Type::d)); EXPECT_TRUE(m.is_any_set(Type::a)); EXPECT_FALSE(m.is_any_set(Type::b)); EXPECT_TRUE(m.is_any_set(Type::c)); EXPECT_FALSE(m.is_any_set(Type::d)); EXPECT_TRUE(m.is_any_set({Type::a, Type::c})); EXPECT_FALSE(m.is_any_set({Type::b, Type::d})); EnumMask n; n = m | n; EXPECT_EQ(m, n); n = m & n; EXPECT_EQ(m, n); bool r = (n == m); EXPECT_TRUE(r); r = (n != m); EXPECT_FALSE(r); n.clear_all(); n = {Type::a, Type::b}; r = (n == m); EXPECT_FALSE(r); r = (n != m); EXPECT_TRUE(r); n = m & n; EXPECT_EQ(static_cast(Type::a), n.value()); n = m | Type::b; EXPECT_TRUE(n.is_set(Type::a)); EXPECT_TRUE(n.is_set(Type::b)); EXPECT_TRUE(n.is_set(Type::c)); EXPECT_FALSE(n.is_set(Type::d)); EXPECT_FALSE(n[Type::d]); EXPECT_TRUE(n[Type::b]); } TEST(graph, huge) { std::vector> weak_nodes; { auto param = make_shared(element::f32, Shape{3, 3}); std::shared_ptr n = param; weak_nodes.push_back(n); for (size_t i = 0; i < 1000000; i++) { n = make_shared(n); weak_nodes.push_back(n); } auto f = make_shared(NodeVector{n}, ParameterVector{param}); } for (auto& weak_node : weak_nodes) { EXPECT_TRUE(weak_node.expired()); } } TEST(util, apply_permutation) { ASSERT_EQ(apply_permutation(Shape{0, 1, 2, 3}, AxisVector{2, 1, 0, 3}), (Shape{2, 1, 0, 3})); } TEST(util, apply_permutation_too_short_fails) { ASSERT_THROW(apply_permutation(Shape{0, 1, 2, 3}, AxisVector{0, 1, 2}), CheckFailure); } TEST(util, apply_permutation_too_long_fails) { ASSERT_THROW(apply_permutation(Shape{0, 1, 2, 3}, AxisVector{0, 1, 2, 3, 3}), CheckFailure); } TEST(util, apply_permutation_oob_axis_fails) { ASSERT_THROW(apply_permutation(Shape{0, 1, 2, 3}, AxisVector{0, 1, 2, 4}), CheckFailure); } TEST(util, apply_permutation_repeated_axis_fails) { ASSERT_THROW(apply_permutation(Shape{0, 1, 2, 3}, AxisVector{0, 1, 2, 2}), CheckFailure); } TEST(util, apply_permutation_pshape) { ASSERT_TRUE(apply_permutation(PartialShape{0, Dimension::dynamic(), 2, 3}, AxisVector{2, 1, 0, 3}) .same_scheme(PartialShape{2, Dimension::dynamic(), 0, 3})); } TEST(util, apply_permutation_pshape_rank_dynamic) { ASSERT_TRUE( apply_permutation(PartialShape::dynamic(), AxisVector{2, 1, 0, 3}).same_scheme(PartialShape::dynamic())); } TEST(util, apply_permutation_pshape_too_short_fails) { ASSERT_THROW(apply_permutation(PartialShape{0, Dimension::dynamic(), 2, 3}, AxisVector{0, 1, 2}), CheckFailure); } TEST(util, apply_permutation_pshape_too_long_fails) { ASSERT_THROW(apply_permutation(PartialShape{0, Dimension::dynamic(), 2, 3}, AxisVector{0, 1, 2, 3, 3}), CheckFailure); } TEST(util, apply_permutation_pshape_oob_axis_fails) { ASSERT_THROW(apply_permutation(PartialShape{0, Dimension::dynamic(), 2, 3}, AxisVector{0, 1, 2, 4}), CheckFailure); } TEST(util, apply_permutation_pshape_repeated_axis_fails) { ASSERT_THROW(apply_permutation(PartialShape{0, Dimension::dynamic(), 2, 3}, AxisVector{0, 1, 2, 2}), CheckFailure); } TEST(util, apply_permutation_pshape_rank_dynamic_inviable_permutation_fails) { ASSERT_THROW(apply_permutation(PartialShape::dynamic(), AxisVector{0, 1, 2, 2}), CheckFailure); } TEST(util, clone_function_friendly_name) { Shape shape{2, 2}; auto A = make_shared(element::f32, shape); auto B = make_shared(element::f32, shape); auto f = make_shared(make_shared(A, B), ParameterVector{A, B}); A->set_friendly_name("A"); B->set_friendly_name("B"); auto g = clone_function(*f); bool found_A = false; bool found_B = false; for (auto parameter : g->get_parameters()) { found_A |= parameter->get_friendly_name() == "A"; found_B |= parameter->get_friendly_name() == "B"; } EXPECT_TRUE(found_A); EXPECT_TRUE(found_B); } TEST(util, clone_function_op_annotations) { Shape shape{2, 2}; auto A = make_shared(element::f32, shape); auto B = make_shared(element::f32, shape); auto C = make_shared(element::f32, shape); auto f = make_shared(make_shared(make_shared(A, B), C), ParameterVector{A, B, C}); auto cacheable_op_annotation = std::make_shared(); cacheable_op_annotation->set_cacheable(true); A->set_op_annotations(cacheable_op_annotation); auto uncacheable_op_annotation = std::make_shared(); uncacheable_op_annotation->set_cacheable(false); B->set_op_annotations(uncacheable_op_annotation); auto g = clone_function(*f); bool found_A = false; bool found_B = false; for (auto parameter : g->get_parameters()) { if (auto op_annotation = parameter->get_op_annotations()) { if (op_annotation->is_cacheable()) { found_A = true; } else { found_B = true; } } } EXPECT_TRUE(found_A); EXPECT_TRUE(found_B); } TEST(util, topological_sort_replace) { Shape shape{2, 2}; auto A = make_shared(element::f32, shape); auto B = make_shared(element::f32, shape); auto C = make_shared(element::f32, shape); auto f = make_shared(make_shared(make_shared(A, B), C), ParameterVector{A, B, C}); bool custom_sorter_used = false; f->set_topological_sort([&custom_sorter_used](const std::vector>& root_nodes) { custom_sorter_used = true; return topological_sort(root_nodes); }); // Need to now call topological sort but don't care about the results f->get_ordered_ops(); EXPECT_TRUE(custom_sorter_used); } TEST(util, double_to_int_limits) { auto round_func = [](double x) { return std::round(x); }; double x = -std::numeric_limits::infinity(); EXPECT_TRUE(std::numeric_limits::min() == double_to_int(x, round_func)); EXPECT_TRUE(std::numeric_limits::min() == double_to_int(x, round_func)); EXPECT_TRUE(std::numeric_limits::min() == double_to_int(x, round_func)); EXPECT_TRUE(std::numeric_limits::min() == double_to_int(x, round_func)); EXPECT_TRUE(std::numeric_limits::min() == double_to_int(x, round_func)); EXPECT_TRUE(std::numeric_limits::min() == double_to_int(x, round_func)); EXPECT_TRUE(std::numeric_limits::min() == double_to_int(x, round_func)); EXPECT_TRUE(std::numeric_limits::min() == double_to_int(x, round_func)); x = std::numeric_limits::infinity(); EXPECT_TRUE(std::numeric_limits::max() == double_to_int(x, round_func)); EXPECT_TRUE(std::numeric_limits::max() == double_to_int(x, round_func)); EXPECT_TRUE(std::numeric_limits::max() == double_to_int(x, round_func)); EXPECT_TRUE(std::numeric_limits::max() == double_to_int(x, round_func)); EXPECT_TRUE(std::numeric_limits::max() == double_to_int(x, round_func)); EXPECT_TRUE(std::numeric_limits::max() == double_to_int(x, round_func)); EXPECT_TRUE(std::numeric_limits::max() == double_to_int(x, round_func)); EXPECT_TRUE(std::numeric_limits::max() == double_to_int(x, round_func)); } TEST(util, double_to_int_assert) { auto round_func = [](double x) { return std::round(x); }; ASSERT_THROW(double_to_int(123.123, round_func), std::runtime_error); ASSERT_THROW(double_to_int(123.123, round_func), std::runtime_error); } TEST(util, double_to_int) { auto ceil_func = [](double x) { return std::ceil(x); }; auto floor_func = [](double x) { return std::floor(x); }; auto round_func = [](double x) { return std::round(x); }; double x = -1.5; EXPECT_TRUE(double_to_int(x, ceil_func) == -1); EXPECT_TRUE(double_to_int(x, floor_func) == -2); EXPECT_TRUE(double_to_int(x, round_func) == -2); x = 1.5; EXPECT_TRUE(double_to_int(x, ceil_func) == 2); 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); }