1 //*****************************************************************************
2 // Copyright 2017-2020 Intel Corporation
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //*****************************************************************************
17 #include "gtest/gtest.h"
19 #include "ngraph/ngraph.hpp"
20 #include "ngraph/specialize_function.hpp"
22 NGRAPH_SUPPRESS_DEPRECATED_START
24 using namespace ngraph;
26 // Simple case: create a function with static parameter shapes and "specialize" them to the same
28 TEST(specialize_function, et_shape_static)
30 auto p0 = std::make_shared<op::Parameter>(element::f32, Shape{1, 2, 3});
31 auto p1 = std::make_shared<op::Parameter>(element::i32, Shape{1, 2, 3});
33 auto k = std::make_shared<op::Convert>(p1, element::f32);
36 auto f = std::make_shared<Function>(a, ParameterVector{p0, p1});
38 std::vector<void*> param_vals{nullptr, nullptr};
40 auto g = specialize_function(f,
41 {element::f32, element::i32},
42 {PartialShape{1, 2, 3}, PartialShape{1, 2, 3}},
45 ASSERT_EQ(g->get_output_shape(0), (Shape{1, 2, 3}));
46 ASSERT_EQ(g->get_output_element_type(0), element::f32);
49 // Test specialization of dynamic element types.
50 TEST(specialize_function, et_dynamic_shape_static)
52 auto p0 = std::make_shared<op::Parameter>(element::dynamic, Shape{1, 2, 3});
53 auto p1 = std::make_shared<op::Parameter>(element::dynamic, Shape{1, 2, 3});
55 auto k = std::make_shared<op::Convert>(p1, element::f32);
58 auto f = std::make_shared<Function>(a, ParameterVector{p0, p1});
60 std::vector<void*> param_vals{nullptr, nullptr};
62 auto g = specialize_function(f,
63 {element::f32, element::i32},
64 {PartialShape{1, 2, 3}, PartialShape{1, 2, 3}},
67 ASSERT_EQ(g->get_output_shape(0), (Shape{1, 2, 3}));
68 ASSERT_EQ(g->get_output_element_type(0), element::f32);
71 // Test specialization of rank-dynamic shapes.
72 TEST(specialize_function, et_static_shape_rank_dynamic)
74 auto p0 = std::make_shared<op::Parameter>(element::f32, PartialShape::dynamic());
75 auto p1 = std::make_shared<op::Parameter>(element::i32, PartialShape::dynamic());
77 auto k = std::make_shared<op::Convert>(p1, element::f32);
80 auto f = std::make_shared<Function>(a, ParameterVector{p0, p1});
82 std::vector<void*> param_vals{nullptr, nullptr};
84 auto g = specialize_function(f,
85 {element::f32, element::i32},
86 {PartialShape{1, 2, 3}, PartialShape{1, 2, 3}},
89 ASSERT_EQ(g->get_output_shape(0), (Shape{1, 2, 3}));
90 ASSERT_EQ(g->get_output_element_type(0), element::f32);
93 // Test specialization of rank-static dynamic shapes.
94 TEST(specialize_function, et_static_shape_rank_static_dynamic)
96 auto p0 = std::make_shared<op::Parameter>(element::f32, PartialShape::dynamic(3));
97 auto p1 = std::make_shared<op::Parameter>(element::i32, PartialShape::dynamic(3));
99 auto k = std::make_shared<op::Convert>(p1, element::f32);
102 auto f = std::make_shared<Function>(a, ParameterVector{p0, p1});
104 std::vector<void*> param_vals{nullptr, nullptr};
106 auto g = specialize_function(f,
107 {element::f32, element::i32},
108 {PartialShape{1, 2, 3}, PartialShape{1, 2, 3}},
111 ASSERT_EQ(g->get_output_shape(0), (Shape{1, 2, 3}));
112 ASSERT_EQ(g->get_output_element_type(0), element::f32);
115 // Test specialization of values to a shape-dynamic parameters.
116 TEST(specialize_function, et_static_shape_rank_static_dynamic_subst_val)
118 auto p0 = std::make_shared<op::Parameter>(element::f32, PartialShape::dynamic(3));
119 auto p1 = std::make_shared<op::Parameter>(element::i32, PartialShape::dynamic(3));
121 auto k = std::make_shared<op::Convert>(p1, element::f32);
124 auto f = std::make_shared<Function>(a, ParameterVector{p0, p1});
126 std::vector<int32_t> p1_subst_vals{5, 0, 3, 8, 5, 8};
128 std::vector<void*> param_vals{nullptr, p1_subst_vals.data()};
130 auto g = specialize_function(f,
131 {element::f32, element::i32},
132 {PartialShape{1, 2, 3}, PartialShape{1, 2, 3}},
135 ASSERT_EQ(g->get_output_shape(0), (Shape{1, 2, 3}));
136 ASSERT_EQ(g->get_output_element_type(0), element::f32);
139 as_type_ptr<op::Add>(g->get_results().at(0)->input_value(0).get_node_shared_ptr());
140 ASSERT_TRUE(plus_node);
141 auto convert_node = as_type_ptr<op::Convert>(plus_node->input_value(1).get_node_shared_ptr());
142 ASSERT_TRUE(convert_node);
143 auto const_node = as_type_ptr<op::Constant>(convert_node->input_value(0).get_node_shared_ptr());
144 ASSERT_TRUE(const_node);
146 ASSERT_EQ(const_node->get_output_element_type(0), element::i32);
147 ASSERT_EQ(const_node->get_output_shape(0), (Shape{1, 2, 3}));
148 ASSERT_EQ(const_node->get_vector<int32_t>(), p1_subst_vals);
151 // Test specialization of rank-dynamic shapes to a case where validation will fail.
153 // (The input shapes we provide at specialization time are inconsistent.)
154 TEST(specialize_function, et_static_shape_rank_dynamic_validation_fails)
156 auto p0 = std::make_shared<op::Parameter>(element::f32, PartialShape::dynamic());
157 auto p1 = std::make_shared<op::Parameter>(element::i32, PartialShape::dynamic());
159 auto k = std::make_shared<op::Convert>(p1, element::f32);
162 auto f = std::make_shared<Function>(a, ParameterVector{p0, p1});
164 std::vector<void*> param_vals{nullptr, nullptr};
168 specialize_function(f,
169 {element::f32, element::i32},
170 {PartialShape{1, 2, 3}, PartialShape{1, 2, 3, 4}},
173 NodeValidationFailure);
176 // Test specialization of dynamic element types to a case where validation will fail.
178 // (The input element types we provide at specialization time are inconsistent.)
179 TEST(specialize_function, et_dynamic_shape_static_validation_fails)
181 auto p0 = std::make_shared<op::Parameter>(element::dynamic, Shape{1, 2, 3});
182 auto p1 = std::make_shared<op::Parameter>(element::dynamic, Shape{1, 2, 3});
184 auto k = std::make_shared<op::Convert>(p1, element::f32);
187 auto f = std::make_shared<Function>(a, ParameterVector{p0, p1});
189 std::vector<void*> param_vals{nullptr, nullptr};
193 specialize_function(f,
194 {element::u32, element::i32},
195 {PartialShape{1, 2, 3}, PartialShape{1, 2, 3}},
198 NodeValidationFailure);
201 // Test specialization of rank-static dynamic shapes, where the replacement shapes have the wrong
204 // (Note that we are testing for a different exception class here because the failure is in
205 // specialize_shape's pre-checks, which use NGRAPH_CHECK, rather than inside validation as we
206 // reconstruct the graph.)
207 TEST(specialize_function, et_static_shape_rank_static_dynamic_rank_mismatch)
209 auto p0 = std::make_shared<op::Parameter>(element::f32, PartialShape::dynamic(3));
210 auto p1 = std::make_shared<op::Parameter>(element::i32, PartialShape::dynamic(3));
212 auto k = std::make_shared<op::Convert>(p1, element::f32);
215 auto f = std::make_shared<Function>(a, ParameterVector{p0, p1});
217 std::vector<void*> param_vals{nullptr, nullptr};
221 specialize_function(f,
222 {element::f32, element::i32},
223 {PartialShape{1, 2, 3}, PartialShape{1, 2, 3, 4}},
229 // Test specialization of rank-static dynamic shapes, where the replacement shapes have wrong
232 // (Note that we are testing for a different exception class here because the failure is in
233 // specialize_shape's pre-checks, which use NGRAPH_CHECK, rather than inside validation as we
234 // reconstruct the graph.)
235 TEST(specialize_function, et_static_shape_rank_static_dynamic_dim_mismatch)
237 auto p0 = std::make_shared<op::Parameter>(element::f32, PartialShape{1, 2, 3});
239 std::make_shared<op::Parameter>(element::i32, PartialShape{1, Dimension::dynamic(), 3});
241 auto k = std::make_shared<op::Convert>(p1, element::f32);
244 auto f = std::make_shared<Function>(a, ParameterVector{p0, p1});
246 std::vector<void*> param_vals{nullptr, nullptr};
250 specialize_function(f,
251 {element::f32, element::i32},
252 {PartialShape{1, 2, 3}, PartialShape{1, 9, 4}},
258 // Test for failure when we supply the wrong number of replacement element types.
259 TEST(specialize_function, et_count_wrong)
261 auto p0 = std::make_shared<op::Parameter>(element::f32, PartialShape{1, 2, 3});
262 auto p1 = std::make_shared<op::Parameter>(element::i32, PartialShape{1, 2, 3});
264 auto k = std::make_shared<op::Convert>(p1, element::f32);
267 auto f = std::make_shared<Function>(a, ParameterVector{p0, p1});
269 std::vector<void*> param_vals{nullptr, nullptr};
273 specialize_function(f,
274 {element::f32, element::i32, element::u32},
275 {PartialShape{1, 2, 3}, PartialShape{1, 2, 3}},
281 // Test for failure when we supply the wrong number of replacement shapes.
282 TEST(specialize_function, shape_count_wrong)
284 auto p0 = std::make_shared<op::Parameter>(element::f32, PartialShape{1, 2, 3});
285 auto p1 = std::make_shared<op::Parameter>(element::i32, PartialShape{1, 2, 3});
287 auto k = std::make_shared<op::Convert>(p1, element::f32);
290 auto f = std::make_shared<Function>(a, ParameterVector{p0, p1});
292 std::vector<void*> param_vals{nullptr, nullptr};
298 {element::f32, element::i32},
299 {PartialShape{1, 2, 3}, PartialShape{1, 2, 3}, PartialShape{4, 5, 6}},
305 // Test for failure when we supply the wrong number of replacement parameter values.
306 TEST(specialize_function, value_count_wrong)
308 auto p0 = std::make_shared<op::Parameter>(element::f32, PartialShape{1, 2, 3});
309 auto p1 = std::make_shared<op::Parameter>(element::i32, PartialShape{1, 2, 3});
311 auto k = std::make_shared<op::Convert>(p1, element::f32);
314 auto f = std::make_shared<Function>(a, ParameterVector{p0, p1});
316 std::vector<void*> param_vals{nullptr, nullptr, nullptr};
320 specialize_function(f,
321 {element::f32, element::i32},
322 {PartialShape{1, 2, 3}, PartialShape{1, 2, 3}},