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 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 61 void TestComposite::TearDown() { 62 // destroy resource 63 } 64 65 class UTCompositeUtils { 66 public: 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 } 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 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 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 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 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 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 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 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 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 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