1 /** 2 * Copyright 2020-2021 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 17 #include <memory> 18 #include <string> 19 20 #include "common/common.h" 21 #include "gtest/gtest.h" 22 #include "minddata/dataset/core/client.h" 23 #include "minddata/dataset/engine/ir/datasetops/dataset_node.h" 24 #include "minddata/dataset/engine/ir/datasetops/map_node.h" 25 #include "minddata/dataset/engine/opt/optional/tensor_op_fusion_pass.h" 26 #include "minddata/dataset/engine/opt/post/auto_worker_pass.h" 27 #include "minddata/dataset/include/dataset/transforms.h" 28 #include "minddata/dataset/include/dataset/vision.h" 29 #include "minddata/dataset/include/dataset/vision_lite.h" 30 #include "minddata/dataset/kernels/ir/data/transforms_ir.h" 31 #include "minddata/dataset/kernels/ir/vision/decode_ir.h" 32 #include "minddata/dataset/kernels/ir/vision/random_crop_decode_resize_ir.h" 33 #include "minddata/dataset/kernels/ir/vision/random_resized_crop_ir.h" 34 35 using namespace mindspore::dataset; 36 using mindspore::LogStream; 37 using mindspore::MsLogLevel::INFO; 38 39 class MindDataTestOptimizationPass : public UT::DatasetOpTesting {}; 40 41 TEST_F(MindDataTestOptimizationPass, MindDataTestAutoWorkerPass) { 42 MS_LOG(INFO) << "Doing MindDataTestOptimizationPass-MindDataTestAutoWorkerPass."; 43 44 std::shared_ptr<SchemaObj> schema = std::make_shared<SchemaObj>(); 45 ASSERT_OK(schema->add_column("label", "uint32", {})); 46 std::shared_ptr<Dataset> map_leaf = ImageFolder("dir")->SetNumWorkers(0); 47 std::shared_ptr<Dataset> nonmap_leaf = RandomData(44, schema)->SetNumWorkers(0); 48 std::shared_ptr<Dataset> batch = Zip({map_leaf, nonmap_leaf})->Batch(1)->SetNumWorkers(0); 49 std::shared_ptr<Dataset> map = batch->Map({std::shared_ptr<TensorTransform>()})->SetNumWorkers(0); 50 // {ImageFolder, RandomData} -> zip -> batch 51 EXPECT_EQ(map_leaf->IRNode()->NumWorkers(), 0); 52 EXPECT_EQ(nonmap_leaf->IRNode()->NumWorkers(), 0); 53 EXPECT_EQ(batch->IRNode()->NumWorkers(), 0); 54 EXPECT_EQ(map->IRNode()->NumWorkers(), 0); 55 56 std::unique_ptr<IRPass> pass = std::make_unique<AutoWorkerPass>(); 57 bool m = false; 58 ASSERT_OK(pass->Run(map->IRNode(), &m)); 59 60 // checking that after this pass, num_workers are set correctly (aka a positive number) 61 // It is hard to test a exact value because num_threads are different for different machine 62 // however, this will for sure succeed bc regardless of the total threads on cpu, this would always be >= 1 63 EXPECT_NE(map_leaf->IRNode()->NumWorkers(), 0); 64 EXPECT_NE(nonmap_leaf->IRNode()->NumWorkers(), 0); 65 EXPECT_NE(batch->IRNode()->NumWorkers(), 0); 66 EXPECT_NE(map->IRNode()->NumWorkers(), 0); 67 MS_LOG(DEBUG) << map_leaf->IRNode()->Name() << ": num_worker=" << map_leaf->IRNode()->NumWorkers(); 68 MS_LOG(DEBUG) << nonmap_leaf->IRNode()->Name() << ": num_worker=" << nonmap_leaf->IRNode()->NumWorkers(); 69 MS_LOG(DEBUG) << batch->IRNode()->Name() << ": num_worker=" << batch->IRNode()->NumWorkers(); 70 MS_LOG(DEBUG) << map->IRNode()->Name() << ": num_worker=" << map->IRNode()->NumWorkers(); 71 } 72 73 TEST_F(MindDataTestOptimizationPass, MindDataTestTensorFusionPass) { 74 MS_LOG(INFO) << "Doing MindDataTestOptimizationPass-MindDataTestTensorFusionPass."; 75 std::string folder_path = datasets_root_path_ + "/testPK/data/"; 76 auto decode_op = vision::Decode(); 77 auto random_resized_crop_op = vision::RandomResizedCrop({100}); 78 std::shared_ptr<Dataset> root = ImageFolder(folder_path, false)->Map({decode_op, random_resized_crop_op}, {"image"}); 79 80 TensorOpFusionPass fusion_pass; 81 bool modified = false; 82 std::shared_ptr<MapNode> map_node = std::dynamic_pointer_cast<MapNode>(root->IRNode()); 83 // no deepcopy is performed because this doesn't go through tree_adapter 84 fusion_pass.Run(root->IRNode(), &modified); 85 EXPECT_EQ(modified, true); 86 ASSERT_NE(map_node, nullptr); 87 auto fused_ops = map_node->operations(); 88 ASSERT_EQ(fused_ops.size(), 1); 89 ASSERT_EQ(fused_ops[0]->Name(), vision::kRandomCropDecodeResizeOperation); 90 } 91 92 TEST_F(MindDataTestOptimizationPass, MindDataTestTensorFusionPassPreBuiltTensorOperation) { 93 MS_LOG(INFO) << "Doing MindDataTestOptimizationPass-MindDataTestTensorFusionPassPreBuiltTensorOperation."; 94 std::string folder_path = datasets_root_path_ + "/testPK/data/"; 95 // make prebuilt tensor operation 96 auto decode = std::make_shared<transforms::PreBuiltOperation>(vision::DecodeOperation(true).Build()); 97 auto resize = std::make_shared<transforms::PreBuiltOperation>( 98 vision::RandomResizedCropOperation({100, 100}, {0.5, 1.0}, {0.1, 0.2}, InterpolationMode::kNearestNeighbour, 5).Build()); 99 std::vector<std::shared_ptr<TensorOperation>> op_list = {decode, resize}; 100 std::vector<std::string> op_name = {"image"}; 101 std::shared_ptr<DatasetNode> root = ImageFolder(folder_path, false)->IRNode(); 102 std::shared_ptr<MapNode> map_node = std::make_shared<MapNode>(root, op_list, op_name); 103 104 TensorOpFusionPass fusion_pass; 105 bool modified = false; 106 // no deepcopy is performed because this doesn't go through tree_adapter 107 fusion_pass.Run(map_node, &modified); 108 EXPECT_EQ(modified, true); 109 ASSERT_NE(map_node, nullptr); 110 auto fused_ops = map_node->operations(); 111 ASSERT_EQ(fused_ops.size(), 1); 112 ASSERT_EQ(fused_ops[0]->Name(), kRandomCropDecodeResizeOp); 113 } 114