1 /**
2 * Copyright 2020 Huawei Technologies Co., Ltd
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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 */
16 #include <memory>
17
18 #include "common/common_test.h"
19 #include "ir/anf.h"
20 #include "ir/value.h"
21 #include "frontend/operator/composite/composite.h"
22 #include "frontend/operator/ops.h"
23 #include "pipeline/jit/static_analysis/prim.h"
24 #include "abstract/abstract_function.h"
25 #include "debug/trace.h"
26
27 namespace mindspore {
28 using Shape = abstract::Shape;
29
30 using AbstractScalar = abstract::AbstractScalar;
31 using AbstractScalarPtr = abstract::AbstractScalarPtr;
32
33 using AbstractSlice = abstract::AbstractSlice;
34 using AbstractSlicePtr = abstract::AbstractSlicePtr;
35
36 using AbstractTuple = abstract::AbstractTuple;
37 using AbstractTuplePtr = abstract::AbstractTuplePtr;
38
39 using AbstractTensor = abstract::AbstractTensor;
40 using AbstractTensorPtr = abstract::AbstractTensorPtr;
41
42 using AbstractNone = abstract::AbstractNone;
43 using AbstractAttribute = abstract::AbstractAttribute;
44 using AnalysisEngine = abstract::AnalysisEngine;
45 using AnalysisEnginePtr = abstract::AnalysisEnginePtr;
46
47 class TestComposite : public UT::Common {
48 public:
49 virtual void SetUp();
50 virtual void TearDown();
51
52 AnalysisEnginePtr engine_;
53 };
54
SetUp()55 void TestComposite::SetUp() {
56 // init resource
57 std::shared_ptr<FuncGraphManager> graph_manager = MakeManager();
58 engine_ = std::make_shared<AnalysisEngine>(abstract::GetPrimEvaluatorConstructors(), graph_manager);
59 }
60
TearDown()61 void TestComposite::TearDown() {
62 // destroy resource
63 }
64
65 class UTCompositeUtils {
66 public:
ArrayInt32Of(std::initializer_list<int64_t> shp)67 static AbstractTensorPtr ArrayInt32Of(std::initializer_list<int64_t> shp) {
68 auto ele = std::make_shared<AbstractScalar>(kAnyValue, kInt64);
69 return std::make_shared<AbstractTensor>(ele, std::make_shared<Shape>(shp));
70 }
MakeFuncGraph(const MetaFuncGraphPtr & metaFuncGraphPtr,size_t nparam)71 static FuncGraphPtr MakeFuncGraph(const MetaFuncGraphPtr &metaFuncGraphPtr, size_t nparam) {
72 FuncGraphPtr func_graph = std::make_shared<FuncGraph>();
73 std::vector<AnfNodePtr> inputs;
74 inputs.push_back(NewValueNode(metaFuncGraphPtr));
75 for (size_t i = 0; i < nparam; i++) {
76 inputs.push_back(func_graph->add_parameter());
77 }
78 CNodePtr cnode_prim = func_graph->NewCNode(inputs);
79 inputs.clear();
80 inputs.push_back(NewValueNode(prim::kPrimReturn));
81 inputs.push_back(cnode_prim);
82 CNodePtr cnode_return = func_graph->NewCNode(inputs);
83 func_graph->set_return(cnode_return);
84 return func_graph;
85 }
86 };
87
TEST_F(TestComposite,test_TupleSlice_arg_two_numbers)88 TEST_F(TestComposite, test_TupleSlice_arg_two_numbers) {
89 MetaFuncGraphPtr tupleSlicePtr = std::make_shared<prim::TupleSlice>("tuple_slice");
90 FuncGraphPtr tupleSliceGraphPtr = UTCompositeUtils::MakeFuncGraph(tupleSlicePtr, 3);
91
92 AbstractBasePtrList eles;
93 auto tensor = UTCompositeUtils::ArrayInt32Of({2, 3, 4});
94 size_t tuple_size = 6;
95 for (size_t i = 0; i < tuple_size; i++) {
96 eles.push_back(tensor);
97 }
98 auto tuple_tensor = std::make_shared<AbstractTuple>(eles);
99 auto start_index = std::make_shared<AbstractScalar>(static_cast<int64_t>(1));
100 auto stop_index = std::make_shared<AbstractScalar>(static_cast<int64_t>(5));
101 AbstractBasePtrList args_spec_list = {tuple_tensor, start_index, stop_index};
102
103 try {
104 engine_->Run(tupleSliceGraphPtr, args_spec_list);
105 FAIL() << "Excepted exception :Args type is wrong";
106 } catch (std::runtime_error const &err) {
107 ASSERT_TRUE(std::string(err.what()).find("TupleSlice input args size should be 2, but got 3") != std::string::npos);
108 } catch (...) {
109 FAIL() << "Excepted exception :Args type is wrong";
110 }
111 }
112
TEST_F(TestComposite,test_TupleSlice_arg_one_number)113 TEST_F(TestComposite, test_TupleSlice_arg_one_number) {
114 MetaFuncGraphPtr tupleSlicePtr = std::make_shared<prim::TupleSlice>("tuple_slice");
115 FuncGraphPtr tupleSliceGraphPtr = UTCompositeUtils::MakeFuncGraph(tupleSlicePtr, 2);
116
117 AbstractBasePtrList eles;
118 auto tensor = UTCompositeUtils::ArrayInt32Of({2, 3, 4});
119 size_t tuple_size = 6;
120 for (size_t i = 0; i < tuple_size; i++) {
121 eles.push_back(tensor);
122 }
123 auto tuple_tensor = std::make_shared<AbstractTuple>(eles);
124 auto start_index = std::make_shared<AbstractScalar>(static_cast<int64_t>(1));
125 AbstractBasePtrList args_spec_list = {tuple_tensor, start_index};
126
127 try {
128 trace::ClearTraceStack();
129 engine_->Run(tupleSliceGraphPtr, args_spec_list);
130 FAIL() << "Excepted exception: Args type is wrong";
131 } catch (pybind11::type_error const &err) {
132 ASSERT_TRUE(true);
133 } catch (std::runtime_error const &err) {
134 if (std::strstr(err.what(), "TypeError") != nullptr) {
135 ASSERT_TRUE(true);
136 } else {
137 FAIL() << "Excepted exception: Args type is wrong, message: " << err.what();
138 }
139 } catch (...) {
140 FAIL() << "Excepted exception: Args type is wrong";
141 }
142 }
143
TEST_F(TestComposite,test_TupleSlice_arg_slice)144 TEST_F(TestComposite, test_TupleSlice_arg_slice) {
145 std::shared_ptr<py::scoped_interpreter> env = parse::python_adapter::set_python_scoped();
146 MetaFuncGraphPtr tupleSlicePtr = std::make_shared<prim::TupleSlice>("tuple_slice");
147 FuncGraphPtr tupleSliceGraphPtr = UTCompositeUtils::MakeFuncGraph(tupleSlicePtr, 2);
148
149 AbstractBasePtrList eles;
150 auto tensor = UTCompositeUtils::ArrayInt32Of({2, 3, 4});
151 size_t tuple_size = 6;
152 for (size_t i = 0; i < tuple_size; i++) {
153 eles.push_back(tensor);
154 }
155 auto tuple_tensor = std::make_shared<AbstractTuple>(eles);
156 auto start_index = std::make_shared<AbstractScalar>(static_cast<int64_t>(1));
157 auto stop_index = std::make_shared<AbstractScalar>(static_cast<int64_t>(6));
158 auto step = std::make_shared<AbstractScalar>(static_cast<int64_t>(2));
159 auto slice = std::make_shared<AbstractSlice>(start_index, stop_index, step);
160 AbstractBasePtrList args_spec_list = {tuple_tensor, slice};
161
162 AbstractTuplePtr ret = dyn_cast<AbstractTuple>(engine_->Run(tupleSliceGraphPtr, args_spec_list).inferred->abstract());
163 if (ret == nullptr) {
164 FAIL() << "Cast ret to abstract tuple failed.";
165 }
166 size_t real = ret->size();
167 size_t expect = 3;
168 ASSERT_EQ(real, expect);
169 }
170
TEST_F(TestComposite,test_TupleSlice_arg_slice_step_none)171 TEST_F(TestComposite, test_TupleSlice_arg_slice_step_none) {
172 MetaFuncGraphPtr tupleSlicePtr = std::make_shared<prim::TupleSlice>("tuple_slice");
173 FuncGraphPtr tupleSliceGraphPtr = UTCompositeUtils::MakeFuncGraph(tupleSlicePtr, 2);
174
175 AbstractBasePtrList eles;
176 auto tensor = UTCompositeUtils::ArrayInt32Of({2, 3, 4});
177 size_t tuple_size = 6;
178 for (size_t i = 0; i < tuple_size; i++) {
179 eles.push_back(tensor);
180 }
181 auto tuple_tensor = std::make_shared<AbstractTuple>(eles);
182 auto start_index = std::make_shared<AbstractScalar>(static_cast<int64_t>(1));
183 auto stop_index = std::make_shared<AbstractScalar>(static_cast<int64_t>(5));
184 auto step = std::make_shared<AbstractNone>();
185 auto slice = std::make_shared<AbstractSlice>(start_index, stop_index, step);
186 AbstractBasePtrList args_spec_list = {tuple_tensor, slice};
187
188 AbstractTuplePtr ret = dyn_cast<AbstractTuple>(engine_->Run(tupleSliceGraphPtr, args_spec_list).inferred->abstract());
189 if (ret == nullptr) {
190 FAIL() << "Cast ret to abstract tuple failed.";
191 }
192 size_t real = ret->size();
193 size_t expect = 4;
194 ASSERT_EQ(real, expect);
195 }
196
TEST_F(TestComposite,test_TupleSlice_arg_slice_step_negative)197 TEST_F(TestComposite, test_TupleSlice_arg_slice_step_negative) {
198 MetaFuncGraphPtr tupleSlicePtr = std::make_shared<prim::TupleSlice>("tuple_slice");
199 FuncGraphPtr tupleSliceGraphPtr = UTCompositeUtils::MakeFuncGraph(tupleSlicePtr, 2);
200
201 AbstractBasePtrList eles;
202 auto tensor = UTCompositeUtils::ArrayInt32Of({2, 3, 4});
203 size_t tuple_size = 6;
204 for (size_t i = 0; i < tuple_size; i++) {
205 eles.push_back(tensor);
206 }
207 auto tuple_tensor = std::make_shared<AbstractTuple>(eles);
208 auto start_index = std::make_shared<AbstractNone>();
209 auto stop_index = std::make_shared<AbstractNone>();
210 auto step = std::make_shared<AbstractScalar>(static_cast<int64_t>(-1));
211 auto slice = std::make_shared<AbstractSlice>(start_index, stop_index, step);
212 AbstractBasePtrList args_spec_list = {tuple_tensor, slice};
213
214 AbstractTuplePtr ret = dyn_cast<AbstractTuple>(engine_->Run(tupleSliceGraphPtr, args_spec_list).inferred->abstract());
215 if (ret == nullptr) {
216 FAIL() << "Cast ret to abstract tuple failed.";
217 }
218 size_t real = ret->size();
219 size_t expect = 6;
220 ASSERT_EQ(real, expect);
221 }
222
TEST_F(TestComposite,test_TupleSlice_arg_slice_step_positive)223 TEST_F(TestComposite, test_TupleSlice_arg_slice_step_positive) {
224 MetaFuncGraphPtr tupleSlicePtr = std::make_shared<prim::TupleSlice>("tuple_slice");
225 FuncGraphPtr tupleSliceGraphPtr = UTCompositeUtils::MakeFuncGraph(tupleSlicePtr, 2);
226
227 AbstractBasePtrList eles;
228 auto tensor = UTCompositeUtils::ArrayInt32Of({2, 3, 4});
229 size_t tuple_size = 6;
230 for (size_t i = 0; i < tuple_size; i++) {
231 eles.push_back(tensor);
232 }
233 auto tuple_tensor = std::make_shared<AbstractTuple>(eles);
234 auto start_index = std::make_shared<AbstractScalar>(static_cast<int64_t>(-2));
235 auto stop_index = std::make_shared<AbstractNone>();
236 auto step = std::make_shared<AbstractScalar>(static_cast<int64_t>(-1));
237 auto slice = std::make_shared<AbstractSlice>(start_index, stop_index, step);
238 AbstractBasePtrList args_spec_list = {tuple_tensor, slice};
239
240 AbstractTuplePtr ret = dyn_cast<AbstractTuple>(engine_->Run(tupleSliceGraphPtr, args_spec_list).inferred->abstract());
241 if (ret == nullptr) {
242 FAIL() << "Cast ret to abstract tuple failed.";
243 }
244 size_t real = ret->size();
245 size_t expect = 5;
246 ASSERT_EQ(real, expect);
247 }
248
TEST_F(TestComposite,test_UnpackCall_3args)249 TEST_F(TestComposite, test_UnpackCall_3args) {
250 MetaFuncGraphPtr unPackCallPtr = std::make_shared<prim::UnpackCall>("UnPackCall");
251 FuncGraphPtr unPackCallGraphPtr = UTCompositeUtils::MakeFuncGraph(unPackCallPtr, 3);
252
253 auto fn_arg= std::make_shared<abstract::PrimitiveAbstractClosure>(prim::kPrimMakeTuple);
254 AbstractTensorPtr tensor = UTCompositeUtils::ArrayInt32Of({2, 3, 4});
255 AbstractBasePtrList eles;
256 for (size_t i = 0; i < 6; i++) {
257 eles.push_back(tensor);
258 }
259 AbstractTuplePtr tensor_tuple = std::make_shared<AbstractTuple>(eles);
260 AbstractTensorPtr arr_x = UTCompositeUtils::ArrayInt32Of({2, 3, 4});
261 AbstractTensorPtr arr_y = UTCompositeUtils::ArrayInt32Of({2, 3, 4});
262 AbstractTensorPtr arr_z = UTCompositeUtils::ArrayInt32Of({2, 3, 4});
263 std::vector<AbstractAttribute> tensor_map{{"x", arr_x}, {"y", arr_y}, {"z", arr_z}};
264 abstract::AbstractDictionaryPtr tensor_dict = std::make_shared<abstract::AbstractDictionary>(tensor_map);
265
266 AbstractBasePtrList args_spec_list = {fn_arg, tensor_tuple, tensor_dict};
267 AbstractTuplePtr ret = dyn_cast<AbstractTuple>(engine_->Run(unPackCallGraphPtr, args_spec_list).inferred->abstract());
268 if (ret == nullptr) {
269 FAIL() << "Cast ret to abstract tuple failed.";
270 }
271 size_t real = ret->size();
272 size_t expect = 9;
273 ASSERT_EQ(real, expect);
274 }
275
TEST_F(TestComposite,test_UnpackCall_5args)276 TEST_F(TestComposite, test_UnpackCall_5args) {
277 MetaFuncGraphPtr unPackCallPtr = std::make_shared<prim::UnpackCall>("UnPackCall");
278 FuncGraphPtr unPackCallGraphPtr = UTCompositeUtils::MakeFuncGraph(unPackCallPtr, 5);
279
280 auto fn_arg = std::make_shared<abstract::PrimitiveAbstractClosure>(prim::kPrimMakeTuple);
281 AbstractTensorPtr tensor = UTCompositeUtils::ArrayInt32Of({2, 3, 4});
282 AbstractBasePtrList eles;
283 for (size_t i = 0; i < 6; i++) {
284 eles.push_back(tensor);
285 }
286 AbstractTuplePtr tensor_tuple = std::make_shared<AbstractTuple>(eles);
287 AbstractTensorPtr arr_x = UTCompositeUtils::ArrayInt32Of({2, 3, 4});
288 AbstractTensorPtr arr_y = UTCompositeUtils::ArrayInt32Of({2, 3, 4});
289 AbstractTensorPtr arr_z = UTCompositeUtils::ArrayInt32Of({2, 3, 4});
290 std::vector<AbstractAttribute> tensor_map{{"x", arr_x}, {"y", arr_y}, {"z", arr_z}};
291 abstract::AbstractDictionaryPtr tensor_dict = std::make_shared<abstract::AbstractDictionary>(tensor_map);
292
293 AbstractBasePtrList args_spec_list = {fn_arg, tensor_dict, tensor_tuple, tensor_dict, tensor_tuple};
294 AbstractTuplePtr ret = dyn_cast<AbstractTuple>(engine_->Run(unPackCallGraphPtr, args_spec_list).inferred->abstract());
295 if (ret == nullptr) {
296 FAIL() << "Cast ret to abstract tuple failed.";
297 }
298 size_t real = ret->size();
299 size_t expect = 18;
300 ASSERT_EQ(real, expect);
301 }
302
TEST_F(TestComposite,test_ZipOperation)303 TEST_F(TestComposite, test_ZipOperation) {
304 MetaFuncGraphPtr zip_op = std::make_shared<prim::ZipOperation>("zip_op");
305 FuncGraphPtr zip_op_graph = UTCompositeUtils::MakeFuncGraph(zip_op, 1);
306
307 AbstractBasePtrList eles;
308 auto tensor = UTCompositeUtils::ArrayInt32Of({2, 3, 4});
309 size_t tuple_size = 3;
310 for (size_t i = 0; i < tuple_size; i++) {
311 eles.push_back(tensor);
312 }
313 auto tuple = std::make_shared<AbstractTuple>(eles);
314 AbstractBasePtrList args_spec_list = {tuple};
315
316 AbstractTuplePtr ret = dyn_cast<AbstractTuple>(engine_->Run(zip_op_graph, args_spec_list).inferred->abstract());
317 if (ret == nullptr) {
318 FAIL() << "Cast ret to abstract tuple failed.";
319 }
320 size_t real = ret->size();
321 size_t expect = 3;
322 ASSERT_EQ(real, expect);
323 }
324 } // namespace mindspore
325