You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

map_op_test.cc 27 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763
  1. /**
  2. * Copyright 2019-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. #include <iostream>
  17. #include <memory>
  18. #include <vector>
  19. #include "common/common.h"
  20. #include "minddata/dataset/core/client.h"
  21. #include "minddata/dataset/core/tensor.h"
  22. #include "minddata/dataset/engine/datasetops/source/image_folder_op.h"
  23. #include "minddata/dataset/kernels/image/decode_op.h"
  24. #include "minddata/dataset/kernels/image/resize_op.h"
  25. #include "minddata/dataset/kernels/tensor_op.h"
  26. #include "utils/log_adapter.h"
  27. using namespace mindspore::dataset;
  28. using mindspore::LogStream;
  29. using mindspore::MsLogLevel::INFO;
  30. namespace mindspore {
  31. namespace dataset {
  32. namespace test {
  33. class NoOp : public TensorOp {
  34. public:
  35. NoOp(){};
  36. ~NoOp(){};
  37. Status Compute(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) override {
  38. *output = std::move(input);
  39. return Status::OK();
  40. };
  41. void Print(std::ostream &out) const override { out << "NoOp"; };
  42. std::string Name() const override { return kNoOp; }
  43. };
  44. class ThreeToOneOp : public TensorOp {
  45. public:
  46. ThreeToOneOp(){};
  47. ~ThreeToOneOp(){};
  48. uint32_t NumInput() override { return 3; }
  49. // Compute function that holds the actual implementation of the operation.
  50. Status Compute(const TensorRow &input, TensorRow *output) override {
  51. output->push_back(input[0]);
  52. return Status::OK();
  53. };
  54. void Print(std::ostream &out) const override { out << "ThreeToOneOp"; };
  55. std::string Name() const override { return "ThreeToOneOp"; }
  56. };
  57. class OneToThreeOp : public TensorOp {
  58. public:
  59. OneToThreeOp(){};
  60. ~OneToThreeOp(){};
  61. uint32_t NumOutput() override { return 3; }
  62. // Compute function that holds the actual implementation of the operation.
  63. // Simply pushing the same shared pointer of the first element of input vector three times.
  64. Status Compute(const TensorRow &input, TensorRow *output) override {
  65. output->push_back(input[0]);
  66. output->push_back(input[0]);
  67. output->push_back(input[0]);
  68. return Status::OK();
  69. };
  70. void Print(std::ostream &out) const override { out << "OneToThreeOp"; };
  71. std::string Name() const override { return "OneToThreeOp"; };
  72. };
  73. } // namespace test
  74. } // namespace dataset
  75. } // namespace mindspore
  76. class MindDataTestMapOp : public UT::DatasetOpTesting {
  77. public:
  78. void SetUp() override {
  79. DatasetOpTesting::SetUp();
  80. dataset_path_ = datasets_root_path_ + "" + "/testDataset2/testDataset2.data";
  81. schema_path_ = datasets_root_path_ + "" + "/testDataset2/datasetSchema.json";
  82. GlobalInit();
  83. // Start with an empty execution tree
  84. my_tree_ = std::make_shared<ExecutionTree>();
  85. }
  86. std::shared_ptr<TFReaderOp> CreateTFReaderOp() {
  87. std::shared_ptr<TFReaderOp> my_tfreader_op;
  88. TFReaderOp::Builder builder;
  89. builder.SetDatasetFilesList({dataset_path_})
  90. .SetColumnsToLoad({"image", "label", "A", "B"})
  91. .SetWorkerConnectorSize(2)
  92. .SetNumWorkers(2);
  93. std::unique_ptr<DataSchema> schema = std::make_unique<DataSchema>();
  94. schema->LoadSchemaFile(schema_path_, {});
  95. builder.SetDataSchema(std::move(schema));
  96. Status rc = builder.Build(&my_tfreader_op);
  97. EXPECT_TRUE(rc.IsOk());
  98. return my_tfreader_op;
  99. }
  100. std::shared_ptr<ExecutionTree> my_tree_;
  101. private:
  102. std::string dataset_path_;
  103. std::string schema_path_;
  104. };
  105. std::shared_ptr<ImageFolderOp> ImageFolder(int64_t num_works, int64_t rows, int64_t conns, std::string path,
  106. bool shuf = false, std::shared_ptr<SamplerRT> sampler = nullptr,
  107. std::map<std::string, int32_t> map = {}, bool decode = false);
  108. std::shared_ptr<ExecutionTree> Build(std::vector<std::shared_ptr<DatasetOp>> ops);
  109. // TestAsMap scenario:
  110. // TFReaderOp reads a dataset that have column ordering |image|label|A|B|.
  111. // A TensorOp that does nothing picks the "image" column and produces a column named "X".
  112. // Thus, based on the new MapOp behaviour, the column ordering will be |X|label|A|B|.
  113. // Verify that the "image" column is removed and "X" column is added.
  114. TEST_F(MindDataTestMapOp, TestAsMap) {
  115. Status rc;
  116. MS_LOG(INFO) << "Doing TestAsMap.";
  117. // Note: The above TFReader config yields 5 buffers, each with 2 rows, for a total of 10 rows.
  118. auto my_tfreader_op = this->CreateTFReaderOp();
  119. rc = my_tree_->AssociateNode(my_tfreader_op);
  120. EXPECT_TRUE(rc.IsOk());
  121. auto my_no_op = std::make_shared<mindspore::dataset::test::NoOp>();
  122. std::vector<std::shared_ptr<TensorOp>> my_func_list;
  123. my_func_list.push_back(my_no_op);
  124. std::shared_ptr<MapOp> my_map_op;
  125. MapOp::Builder builder;
  126. builder.SetInColNames({"image"}).SetOutColNames({"X"}).SetTensorFuncs(std::move(my_func_list)).SetNumWorkers(1);
  127. rc = builder.Build(&my_map_op);
  128. rc = my_tree_->AssociateNode(my_map_op);
  129. EXPECT_TRUE(rc.IsOk());
  130. rc = my_map_op->AddChild(my_tfreader_op);
  131. EXPECT_TRUE(rc.IsOk());
  132. // Assign the tree root
  133. rc = my_tree_->AssignRoot(my_map_op);
  134. EXPECT_TRUE(rc.IsOk());
  135. // Now prepare the tree
  136. rc = my_tree_->Prepare();
  137. EXPECT_TRUE(rc.IsOk());
  138. rc = my_tree_->Launch();
  139. EXPECT_TRUE(rc.IsOk());
  140. // Start the loop of reading tensors from our pipeline
  141. DatasetIterator di(my_tree_);
  142. TensorMap tensor_map;
  143. rc = di.GetNextAsMap(&tensor_map);
  144. EXPECT_TRUE(rc.IsOk());
  145. EXPECT_EQ(tensor_map.size(), 4);
  146. EXPECT_EQ(tensor_map.find("image"), tensor_map.end());
  147. EXPECT_NE(tensor_map.find("label"), tensor_map.end());
  148. EXPECT_NE(tensor_map.find("X"), tensor_map.end());
  149. EXPECT_NE(tensor_map.find("A"), tensor_map.end());
  150. EXPECT_NE(tensor_map.find("B"), tensor_map.end());
  151. }
  152. // Test3to1 scenario:
  153. // TFReaderOp reads a dataset that have column ordering |image|label|A|B|.
  154. // A 3-to-1 TensorOp picks the columns [image, A, B] and produce a column named "X".
  155. // Thus, based on the new MapOp behaviour, the column ordering will be |X|label|.
  156. // Verify that the only columns "X" and "label" exist.
  157. TEST_F(MindDataTestMapOp, Test3to1) {
  158. Status rc;
  159. MS_LOG(INFO) << "Doing Test3to1.";
  160. // Note: The above TFReader config yields 5 buffers, each with 2 rows, for a total of 10 rows.
  161. auto my_tfreader_op = this->CreateTFReaderOp();
  162. rc = my_tree_->AssociateNode(my_tfreader_op);
  163. EXPECT_TRUE(rc.IsOk());
  164. auto my_op = std::make_shared<mindspore::dataset::test::ThreeToOneOp>();
  165. std::vector<std::shared_ptr<TensorOp>> my_func_list;
  166. my_func_list.push_back(my_op);
  167. std::shared_ptr<MapOp> my_map_op;
  168. MapOp::Builder builder;
  169. builder.SetInColNames({"image", "A", "B"})
  170. .SetOutColNames({"X"})
  171. .SetTensorFuncs(std::move(my_func_list))
  172. .SetNumWorkers(1);
  173. rc = builder.Build(&my_map_op);
  174. EXPECT_TRUE(rc.IsOk());
  175. rc = my_tree_->AssociateNode(my_map_op);
  176. EXPECT_TRUE(rc.IsOk());
  177. rc = my_map_op->AddChild(my_tfreader_op);
  178. EXPECT_TRUE(rc.IsOk());
  179. rc = my_tree_->AssignRoot(my_map_op);
  180. EXPECT_TRUE(rc.IsOk());
  181. rc = my_tree_->Prepare();
  182. EXPECT_TRUE(rc.IsOk());
  183. rc = my_tree_->Launch();
  184. EXPECT_TRUE(rc.IsOk());
  185. // Start the loop of reading tensors from our pipeline
  186. DatasetIterator di(my_tree_);
  187. TensorMap tensor_map;
  188. rc = di.GetNextAsMap(&tensor_map);
  189. EXPECT_TRUE(rc.IsOk());
  190. while (!tensor_map.empty()) {
  191. EXPECT_EQ(tensor_map.size(), 2);
  192. EXPECT_EQ(tensor_map.find("image"), tensor_map.end());
  193. EXPECT_NE(tensor_map.find("label"), tensor_map.end());
  194. EXPECT_NE(tensor_map.find("X"), tensor_map.end());
  195. EXPECT_EQ(tensor_map.find("A"), tensor_map.end());
  196. EXPECT_EQ(tensor_map.find("B"), tensor_map.end());
  197. rc = di.GetNextAsMap(&tensor_map);
  198. EXPECT_TRUE(rc.IsOk());
  199. }
  200. }
  201. // Test1to3 scenario:
  202. // TFReaderOp reads a dataset that have column ordering |image|label|A|B|.
  203. // A 1-to-3 TensorOp picks the columns [image] and produce a column named [X, Y, Z].
  204. // Thus, based on the new MapOp behaviour, the column ordering will be |X|Y|Z|label|A|B|.
  205. // Verify that the only columns X, Y, Z are added (to the front) and followed by columns label, A, B..
  206. TEST_F(MindDataTestMapOp, Test1to3) {
  207. Status rc;
  208. MS_LOG(INFO) << "Doing Test1to3.";
  209. // Note: The above TFReader config yields 5 buffers, each with 2 rows, for a total of 10 rows.
  210. auto my_tfreader_op = this->CreateTFReaderOp();
  211. rc = my_tree_->AssociateNode(my_tfreader_op);
  212. EXPECT_TRUE(rc.IsOk());
  213. auto my_op = std::make_shared<mindspore::dataset::test::OneToThreeOp>();
  214. std::vector<std::shared_ptr<TensorOp>> my_func_list;
  215. my_func_list.push_back(my_op);
  216. std::shared_ptr<MapOp> my_map_op;
  217. MapOp::Builder builder;
  218. builder.SetInColNames({"image"})
  219. .SetOutColNames({"X", "Y", "Z"})
  220. .SetTensorFuncs(std::move(my_func_list))
  221. .SetNumWorkers(1);
  222. // ProjectOp
  223. std::vector<std::string> columns_to_project = {"X", "Y", "Z", "label", "A", "B"};
  224. std::shared_ptr<ProjectOp> my_project_op = std::make_shared<ProjectOp>(columns_to_project);
  225. rc = my_tree_->AssociateNode(my_project_op);
  226. ASSERT_TRUE(rc.IsOk());
  227. rc = my_tree_->AssignRoot(my_project_op);
  228. ASSERT_TRUE(rc.IsOk());
  229. rc = builder.Build(&my_map_op);
  230. rc = my_tree_->AssociateNode(my_map_op);
  231. EXPECT_TRUE(rc.IsOk());
  232. rc = my_project_op->AddChild(my_map_op);
  233. EXPECT_TRUE(rc.IsOk());
  234. rc = my_map_op->AddChild(my_tfreader_op);
  235. EXPECT_TRUE(rc.IsOk());
  236. rc = my_tree_->Prepare();
  237. EXPECT_TRUE(rc.IsOk());
  238. rc = my_tree_->Launch();
  239. EXPECT_TRUE(rc.IsOk());
  240. // Start the loop of reading tensors from our pipeline
  241. DatasetIterator di(my_tree_);
  242. TensorMap tensor_map;
  243. rc = di.GetNextAsMap(&tensor_map);
  244. EXPECT_TRUE(rc.IsOk());
  245. EXPECT_EQ(tensor_map.size(), 6);
  246. EXPECT_EQ(tensor_map.find("image"), tensor_map.end());
  247. EXPECT_NE(tensor_map.find("label"), tensor_map.end());
  248. EXPECT_NE(tensor_map.find("A"), tensor_map.end());
  249. EXPECT_NE(tensor_map.find("B"), tensor_map.end());
  250. EXPECT_NE(tensor_map.find("X"), tensor_map.end());
  251. EXPECT_NE(tensor_map.find("Y"), tensor_map.end());
  252. EXPECT_NE(tensor_map.find("Z"), tensor_map.end());
  253. // Getting the next row as vector (by position).
  254. TensorRow tensor_list;
  255. rc = di.FetchNextTensorRow(&tensor_list);
  256. EXPECT_TRUE(rc.IsOk());
  257. // Based on the schema file, create the golden result to compare with.
  258. std::vector<DataType::Type> golden_types({DataType::Type::DE_UINT8, DataType::Type::DE_UINT8,
  259. DataType::Type::DE_UINT8, DataType::Type::DE_INT64,
  260. DataType::Type::DE_FLOAT32, DataType::Type::DE_INT64});
  261. std::vector<uint64_t> golden_ranks({3, 3, 3, 1, 4, 1});
  262. std::vector<TensorShape> golden_shapes({TensorShape({3, 4, 2}), TensorShape({3, 4, 2}), TensorShape({3, 4, 2}),
  263. TensorShape({7}), TensorShape({1, 13, 14, 12}), TensorShape({9})});
  264. while (!tensor_list.empty()) {
  265. for (uint32_t i = 0; i < tensor_list.size(); i++) {
  266. EXPECT_EQ(tensor_list[i]->type(), golden_types[i]);
  267. EXPECT_EQ(tensor_list[i]->Rank(), golden_ranks[i]);
  268. EXPECT_EQ(tensor_list[i]->shape(), golden_shapes[i]);
  269. EXPECT_NE(tensor_list[i]->GetBuffer(), nullptr);
  270. }
  271. rc = di.FetchNextTensorRow(&tensor_list);
  272. EXPECT_TRUE(rc.IsOk());
  273. }
  274. }
  275. // TestMultiTensorOp scenario:
  276. // TFReaderOp reads a dataset that have column ordering |image|label|A|B|.
  277. // A series of 3-to-1 and 1-to-3 TensorOps are applied to [image, A, B] and
  278. // produce final output columns [X, Y, Z].
  279. // Based on the new MapOp behaviour, the column ordering will be |X|Y|Z|label|.
  280. TEST_F(MindDataTestMapOp, TestMultiTensorOp) {
  281. Status rc;
  282. MS_LOG(INFO) << "Doing TestMultiTensorOp.";
  283. // Note: The above TFReader config yields 5 buffers, each with 2 rows, for a total of 10 rows.
  284. auto my_tfreader_op = this->CreateTFReaderOp();
  285. rc = my_tree_->AssociateNode(my_tfreader_op);
  286. EXPECT_TRUE(rc.IsOk());
  287. auto my_op1 = std::make_shared<mindspore::dataset::test::ThreeToOneOp>();
  288. auto my_op2 = std::make_shared<mindspore::dataset::test::OneToThreeOp>();
  289. std::vector<std::shared_ptr<TensorOp>> my_func_list;
  290. my_func_list.push_back(my_op1);
  291. my_func_list.push_back(my_op2);
  292. std::shared_ptr<MapOp> my_map_op;
  293. MapOp::Builder builder;
  294. builder.SetInColNames({"image", "A", "B"})
  295. .SetOutColNames({"X", "Y", "Z"})
  296. .SetTensorFuncs(std::move(my_func_list))
  297. .SetNumWorkers(1);
  298. rc = builder.Build(&my_map_op);
  299. EXPECT_TRUE(rc.IsOk());
  300. rc = my_tree_->AssociateNode(my_map_op);
  301. EXPECT_TRUE(rc.IsOk());
  302. rc = my_map_op->AddChild(my_tfreader_op);
  303. EXPECT_TRUE(rc.IsOk());
  304. rc = my_tree_->AssignRoot(my_map_op);
  305. EXPECT_TRUE(rc.IsOk());
  306. rc = my_tree_->Prepare();
  307. EXPECT_TRUE(rc.IsOk());
  308. rc = my_tree_->Launch();
  309. EXPECT_TRUE(rc.IsOk());
  310. // Start the loop of reading tensors from our pipeline
  311. DatasetIterator di(my_tree_);
  312. TensorMap tensor_map;
  313. rc = di.GetNextAsMap(&tensor_map);
  314. EXPECT_TRUE(rc.IsOk());
  315. while (!tensor_map.empty()) {
  316. EXPECT_EQ(tensor_map.size(), 4);
  317. EXPECT_EQ(tensor_map.find("image"), tensor_map.end());
  318. EXPECT_EQ(tensor_map.find("A"), tensor_map.end());
  319. EXPECT_EQ(tensor_map.find("B"), tensor_map.end());
  320. EXPECT_NE(tensor_map.find("label"), tensor_map.end());
  321. EXPECT_NE(tensor_map.find("X"), tensor_map.end());
  322. EXPECT_NE(tensor_map.find("Y"), tensor_map.end());
  323. EXPECT_NE(tensor_map.find("Z"), tensor_map.end());
  324. // XYZ are Tensor shared_ptr to image, so it should have the same shape as image column.
  325. EXPECT_EQ(tensor_map["X"]->shape(), TensorShape({3, 4, 2}));
  326. EXPECT_EQ(tensor_map["Y"]->shape(), TensorShape({3, 4, 2}));
  327. EXPECT_EQ(tensor_map["Z"]->shape(), TensorShape({3, 4, 2}));
  328. rc = di.GetNextAsMap(&tensor_map);
  329. EXPECT_TRUE(rc.IsOk());
  330. }
  331. }
  332. TEST_F(MindDataTestMapOp, TestTFReaderRepeatMap) {
  333. Status rc;
  334. MS_LOG(INFO) << "Doing TestTFReaderRepeatMap.";
  335. uint32_t num_repeats = 3;
  336. // Note: The above TFReader config yields 5 buffers, each with 2 rows, for a total
  337. // of 10 rows.
  338. auto my_tfreader_op = this->CreateTFReaderOp();
  339. rc = my_tree_->AssociateNode(my_tfreader_op);
  340. EXPECT_TRUE(rc.IsOk());
  341. auto my_no_op = std::make_shared<mindspore::dataset::test::NoOp>();
  342. std::vector<std::shared_ptr<TensorOp>> my_func_list;
  343. my_func_list.push_back(my_no_op);
  344. std::shared_ptr<RepeatOp> my_repeat_op;
  345. rc = RepeatOp::Builder(num_repeats).Build(&my_repeat_op);
  346. EXPECT_TRUE(rc.IsOk());
  347. rc = my_tree_->AssociateNode(my_repeat_op);
  348. EXPECT_TRUE(rc.IsOk());
  349. std::shared_ptr<MapOp> my_map_op;
  350. MapOp::Builder builder;
  351. builder.SetInColNames({"label"}).SetOutColNames({}).SetTensorFuncs(std::move(my_func_list)).SetNumWorkers(5);
  352. rc = builder.Build(&my_map_op);
  353. EXPECT_TRUE(rc.IsOk());
  354. rc = my_tree_->AssociateNode(my_map_op);
  355. EXPECT_TRUE(rc.IsOk());
  356. rc = my_map_op->AddChild(my_repeat_op);
  357. EXPECT_TRUE(rc.IsOk());
  358. my_tfreader_op->set_total_repeats(num_repeats);
  359. my_tfreader_op->set_num_repeats_per_epoch(num_repeats);
  360. rc = my_repeat_op->AddChild(my_tfreader_op);
  361. EXPECT_TRUE(rc.IsOk());
  362. rc = my_tree_->AssignRoot(my_map_op);
  363. EXPECT_TRUE(rc.IsOk());
  364. rc = my_tree_->Prepare();
  365. EXPECT_TRUE(rc.IsOk());
  366. rc = my_tree_->Launch();
  367. EXPECT_TRUE(rc.IsOk());
  368. // Start the loop of reading tensors from our pipeline
  369. DatasetIterator di(my_tree_);
  370. TensorRow tensor_list;
  371. rc = di.FetchNextTensorRow(&tensor_list);
  372. EXPECT_TRUE(rc.IsOk());
  373. EXPECT_EQ(tensor_list.size(), 4);
  374. uint32_t row_count = 0;
  375. while (!tensor_list.empty()) {
  376. row_count++;
  377. MS_LOG(INFO) << "row_count: " << row_count << ".";
  378. rc = di.FetchNextTensorRow(&tensor_list);
  379. EXPECT_TRUE(rc.IsOk());
  380. }
  381. ASSERT_EQ(row_count, 10 * num_repeats);
  382. }
  383. TEST_F(MindDataTestMapOp, TestTFReaderMapRepeat) {
  384. Status rc;
  385. MS_LOG(INFO) << "Doing TestTFReaderMapRepeat.";
  386. uint32_t num_repeats = 3;
  387. // Note: The above TFReader config yields 5 buffers, each with 2 rows, for a total
  388. // of 10 rows.
  389. auto my_tfreader_op = this->CreateTFReaderOp();
  390. rc = my_tree_->AssociateNode(my_tfreader_op);
  391. EXPECT_TRUE(rc.IsOk());
  392. auto my_no_op = std::make_shared<mindspore::dataset::test::NoOp>();
  393. std::vector<std::shared_ptr<TensorOp>> my_func_list;
  394. my_func_list.push_back(my_no_op);
  395. std::shared_ptr<RepeatOp> my_repeat_op;
  396. rc = RepeatOp::Builder(num_repeats).Build(&my_repeat_op);
  397. EXPECT_TRUE(rc.IsOk());
  398. rc = my_tree_->AssociateNode(my_repeat_op);
  399. EXPECT_TRUE(rc.IsOk());
  400. std::shared_ptr<MapOp> my_map_op;
  401. MapOp::Builder builder;
  402. builder.SetInColNames({"label"}).SetOutColNames({}).SetTensorFuncs(std::move(my_func_list)).SetNumWorkers(50);
  403. rc = builder.Build(&my_map_op);
  404. EXPECT_TRUE(rc.IsOk());
  405. rc = my_tree_->AssociateNode(my_map_op);
  406. EXPECT_TRUE(rc.IsOk());
  407. my_map_op->set_total_repeats(num_repeats);
  408. my_map_op->set_num_repeats_per_epoch(num_repeats);
  409. rc = my_repeat_op->AddChild(my_map_op);
  410. EXPECT_TRUE(rc.IsOk());
  411. my_tfreader_op->set_total_repeats(num_repeats);
  412. my_tfreader_op->set_num_repeats_per_epoch(num_repeats);
  413. rc = my_map_op->AddChild(my_tfreader_op);
  414. EXPECT_TRUE(rc.IsOk());
  415. rc = my_tree_->AssignRoot(my_repeat_op);
  416. EXPECT_TRUE(rc.IsOk());
  417. rc = my_tree_->Prepare();
  418. EXPECT_TRUE(rc.IsOk());
  419. rc = my_tree_->Launch();
  420. EXPECT_TRUE(rc.IsOk());
  421. // Start the loop of reading tensors from our pipeline
  422. DatasetIterator di(my_tree_);
  423. TensorRow tensor_list;
  424. rc = di.FetchNextTensorRow(&tensor_list);
  425. EXPECT_TRUE(rc.IsOk());
  426. EXPECT_EQ(tensor_list.size(), 4);
  427. uint32_t row_count = 0;
  428. while (!tensor_list.empty()) {
  429. row_count++;
  430. MS_LOG(INFO) << "row_count: " << row_count << ".";
  431. rc = di.FetchNextTensorRow(&tensor_list);
  432. EXPECT_TRUE(rc.IsOk());
  433. }
  434. ASSERT_EQ(row_count, 10 * num_repeats);
  435. }
  436. TEST_F(MindDataTestMapOp, TFReader_Decode_Repeat_Resize) {
  437. Status rc;
  438. MS_LOG(INFO) << "Doing TFReader_Decode_Repeat_Resize.";
  439. uint32_t num_repeats = 2;
  440. std::string dataset_path_ = datasets_root_path_ + "/" + "test_tf_file_3_images/train-0000-of-0001.data";
  441. std::shared_ptr<TFReaderOp> my_tfreader_op;
  442. TFReaderOp::Builder sobuilder;
  443. sobuilder.SetDatasetFilesList({dataset_path_})
  444. .SetColumnsToLoad({"image", "label"})
  445. .SetWorkerConnectorSize(2)
  446. .SetNumWorkers(2);
  447. rc = sobuilder.Build(&my_tfreader_op);
  448. EXPECT_TRUE(rc.IsOk());
  449. rc = my_tree_->AssociateNode(my_tfreader_op);
  450. EXPECT_TRUE(rc.IsOk());
  451. auto decode_op = std::make_shared<DecodeOp>();
  452. std::vector<std::shared_ptr<TensorOp>> my_func_list;
  453. my_func_list.push_back(decode_op);
  454. std::shared_ptr<RepeatOp> my_repeat_op;
  455. rc = RepeatOp::Builder(num_repeats).Build(&my_repeat_op);
  456. EXPECT_TRUE(rc.IsOk());
  457. rc = my_tree_->AssociateNode(my_repeat_op);
  458. EXPECT_TRUE(rc.IsOk());
  459. std::shared_ptr<MapOp> my_map_decode_op;
  460. MapOp::Builder builder;
  461. builder.SetInColNames({"image"}).SetOutColNames({}).SetTensorFuncs(std::move(my_func_list)).SetNumWorkers(4);
  462. rc = builder.Build(&my_map_decode_op);
  463. EXPECT_TRUE(rc.IsOk());
  464. rc = my_tree_->AssociateNode(my_map_decode_op);
  465. EXPECT_TRUE(rc.IsOk());
  466. auto resize_op = std::make_shared<ResizeOp>(300, 300);
  467. std::vector<std::shared_ptr<TensorOp>> my_func_list2;
  468. my_func_list2.push_back(resize_op);
  469. std::shared_ptr<MapOp> my_map_resize_op;
  470. MapOp::Builder builder2;
  471. builder2.SetInColNames({"image"}).SetOutColNames({}).SetTensorFuncs(std::move(my_func_list2)).SetNumWorkers(5);
  472. rc = builder2.Build(&my_map_resize_op);
  473. EXPECT_TRUE(rc.IsOk());
  474. rc = my_tree_->AssociateNode(my_map_resize_op);
  475. EXPECT_TRUE(rc.IsOk());
  476. my_tfreader_op->set_total_repeats(num_repeats);
  477. my_tfreader_op->set_num_repeats_per_epoch(num_repeats);
  478. rc = my_map_decode_op->AddChild(my_tfreader_op);
  479. EXPECT_TRUE(rc.IsOk());
  480. my_map_decode_op->set_total_repeats(num_repeats);
  481. my_map_decode_op->set_num_repeats_per_epoch(num_repeats);
  482. rc = my_repeat_op->AddChild(my_map_decode_op);
  483. EXPECT_TRUE(rc.IsOk());
  484. rc = my_map_resize_op->AddChild(my_repeat_op);
  485. EXPECT_TRUE(rc.IsOk());
  486. rc = my_tree_->AssignRoot(my_map_resize_op);
  487. EXPECT_TRUE(rc.IsOk());
  488. rc = my_tree_->Prepare();
  489. EXPECT_TRUE(rc.IsOk());
  490. rc = my_tree_->Launch();
  491. EXPECT_TRUE(rc.IsOk());
  492. // Start the loop of reading tensors from our pipeline
  493. DatasetIterator di(my_tree_);
  494. TensorRow tensor_list;
  495. rc = di.FetchNextTensorRow(&tensor_list);
  496. EXPECT_TRUE(rc.IsOk());
  497. EXPECT_EQ(tensor_list.size(), 2);
  498. uint32_t row_count = 0;
  499. while (!tensor_list.empty()) {
  500. row_count++;
  501. rc = di.FetchNextTensorRow(&tensor_list);
  502. EXPECT_TRUE(rc.IsOk());
  503. }
  504. ASSERT_EQ(row_count, 6);
  505. }
  506. TEST_F(MindDataTestMapOp, ImageFolder_Decode_Repeat_Resize) {
  507. Status rc;
  508. MS_LOG(INFO) << "Doing ImageFolder_Decode_Repeat_Resize.";
  509. std::string folder_path = datasets_root_path_ + "/testPK/data";
  510. uint32_t num_repeats = 2;
  511. std::shared_ptr<RepeatOp> repeat_op;
  512. rc = RepeatOp::Builder(num_repeats).Build(&repeat_op);
  513. EXPECT_TRUE(rc.IsOk());
  514. auto decode_op = std::make_shared<DecodeOp>();
  515. std::vector<std::shared_ptr<TensorOp>> func_list;
  516. func_list.push_back(decode_op);
  517. std::shared_ptr<MapOp> map_decode_map;
  518. MapOp::Builder map_decode_builder;
  519. map_decode_builder.SetInColNames({"image"}).SetOutColNames({}).SetTensorFuncs(func_list).SetNumWorkers(4);
  520. rc = map_decode_builder.Build(&map_decode_map);
  521. EXPECT_TRUE(rc.IsOk());
  522. auto resize_op = std::make_shared<ResizeOp>(300, 300);
  523. std::vector<std::shared_ptr<TensorOp>> func_list2;
  524. func_list2.push_back(resize_op);
  525. std::shared_ptr<MapOp> map_resize_op;
  526. MapOp::Builder map_resize_builder;
  527. map_resize_builder.SetInColNames({"image"}).SetOutColNames({}).SetTensorFuncs(func_list2).SetNumWorkers(5);
  528. rc = map_resize_builder.Build(&map_resize_op);
  529. EXPECT_TRUE(rc.IsOk());
  530. auto image_folder_op = ImageFolder(16, 2, 32, folder_path, false);
  531. image_folder_op->set_total_repeats(num_repeats);
  532. image_folder_op->set_num_repeats_per_epoch(num_repeats);
  533. map_decode_map->set_total_repeats(num_repeats);
  534. map_decode_map->set_num_repeats_per_epoch(num_repeats);
  535. my_tree_ = Build({image_folder_op, map_decode_map, repeat_op, map_resize_op});
  536. rc = my_tree_->Prepare();
  537. EXPECT_TRUE(rc.IsOk());
  538. rc = my_tree_->Launch();
  539. EXPECT_TRUE(rc.IsOk());
  540. // Start the loop of reading tensors from our pipeline
  541. DatasetIterator di(my_tree_);
  542. TensorMap tensor_map;
  543. ASSERT_OK(di.GetNextAsMap(&tensor_map));
  544. EXPECT_TRUE(rc.IsOk());
  545. uint64_t i = 0;
  546. int32_t label = 0;
  547. int32_t img_class[] = {0, 1, 2, 3};
  548. std::string result;
  549. while (tensor_map.size() != 0) {
  550. tensor_map["label"]->GetItemAt<int32_t>(&label, {});
  551. MS_LOG(DEBUG) << "row:" << i << "\tlabel:" << label << "\n";
  552. EXPECT_TRUE(img_class[(i % 44) / 11] == label);
  553. // Dump all the image into string, to be used as a comparison later.
  554. result.append((char *)tensor_map["image"]->GetBuffer(), (int64_t)tensor_map["image"]->Size());
  555. ASSERT_OK(di.GetNextAsMap(&tensor_map));
  556. i++;
  557. }
  558. EXPECT_TRUE(i == 88);
  559. // Part-2 : creating mapop with performance mode = false, to check if the result is the same
  560. // as when performance mode = true.
  561. rc = RepeatOp::Builder(num_repeats).Build(&repeat_op);
  562. EXPECT_TRUE(rc.IsOk());
  563. map_decode_builder.SetInColNames({"image"})
  564. .SetOutColNames({})
  565. .SetTensorFuncs(func_list)
  566. .SetNumWorkers(14);
  567. rc = map_decode_builder.Build(&map_decode_map);
  568. EXPECT_TRUE(rc.IsOk());
  569. map_resize_builder.SetInColNames({"image"})
  570. .SetOutColNames({})
  571. .SetTensorFuncs(func_list2)
  572. .SetNumWorkers(15);
  573. rc = map_resize_builder.Build(&map_resize_op);
  574. EXPECT_TRUE(rc.IsOk());
  575. image_folder_op = ImageFolder(16, 2, 32, folder_path, false);
  576. image_folder_op->set_total_repeats(num_repeats);
  577. image_folder_op->set_num_repeats_per_epoch(num_repeats);
  578. map_decode_map->set_total_repeats(num_repeats);
  579. map_decode_map->set_num_repeats_per_epoch(num_repeats);
  580. auto my_tree_2 = Build({image_folder_op, map_decode_map, repeat_op, map_resize_op});
  581. rc = my_tree_2->Prepare();
  582. EXPECT_TRUE(rc.IsOk());
  583. rc = my_tree_2->Launch();
  584. EXPECT_TRUE(rc.IsOk());
  585. // Start the loop of reading tensors from our pipeline
  586. DatasetIterator di2(my_tree_2);
  587. ASSERT_OK(di2.GetNextAsMap(&tensor_map));
  588. EXPECT_TRUE(rc.IsOk());
  589. i = 0;
  590. label = 0;
  591. std::string result2;
  592. while (tensor_map.size() != 0) {
  593. tensor_map["label"]->GetItemAt<int32_t>(&label, {});
  594. MS_LOG(DEBUG) << "row:" << i << "\tlabel:" << label << "\n";
  595. EXPECT_TRUE(img_class[(i % 44) / 11] == label);
  596. result2.append((char *)tensor_map["image"]->GetBuffer(), (int64_t)tensor_map["image"]->Size());
  597. ASSERT_OK(di2.GetNextAsMap(&tensor_map));
  598. i++;
  599. }
  600. EXPECT_TRUE(i == 88);
  601. EXPECT_EQ(result.size(), result2.size());
  602. EXPECT_EQ(result, result2);
  603. }
  604. TEST_F(MindDataTestMapOp, ImageFolder_Decode_Repeat_Resize_NoInputColumns) {
  605. Status rc;
  606. MS_LOG(INFO) << "Doing ImageFolder_Decode_Repeat_Resize_NoInputColumns.";
  607. std::string folder_path = datasets_root_path_ + "/testPK/data";
  608. uint32_t num_repeats = 2;
  609. std::shared_ptr<RepeatOp> repeat_op;
  610. rc = RepeatOp::Builder(num_repeats).Build(&repeat_op);
  611. EXPECT_TRUE(rc.IsOk());
  612. auto decode_op = std::make_shared<DecodeOp>();
  613. std::vector<std::shared_ptr<TensorOp>> func_list;
  614. func_list.push_back(decode_op);
  615. std::shared_ptr<MapOp> map_decode_map;
  616. MapOp::Builder map_decode_builder;
  617. map_decode_builder.SetInColNames({}).SetOutColNames({}).SetTensorFuncs(func_list).SetNumWorkers(4);
  618. rc = map_decode_builder.Build(&map_decode_map);
  619. EXPECT_TRUE(rc.IsOk());
  620. auto resize_op = std::make_shared<ResizeOp>(300, 300);
  621. std::vector<std::shared_ptr<TensorOp>> func_list2;
  622. func_list2.push_back(resize_op);
  623. std::shared_ptr<MapOp> map_resize_op;
  624. MapOp::Builder map_resize_builder;
  625. map_resize_builder.SetTensorFuncs(func_list2).SetNumWorkers(5);
  626. rc = map_resize_builder.Build(&map_resize_op);
  627. EXPECT_TRUE(rc.IsOk());
  628. auto image_folder_op = ImageFolder(16, 2, 32, folder_path, false);
  629. image_folder_op->set_total_repeats(num_repeats);
  630. image_folder_op->set_num_repeats_per_epoch(num_repeats);
  631. map_decode_map->set_total_repeats(num_repeats);
  632. map_decode_map->set_num_repeats_per_epoch(num_repeats);
  633. my_tree_ = Build({image_folder_op, map_decode_map, repeat_op, map_resize_op});
  634. rc = my_tree_->Prepare();
  635. EXPECT_TRUE(rc.IsOk());
  636. rc = my_tree_->Launch();
  637. EXPECT_TRUE(rc.IsOk());
  638. // Start the loop of reading tensors from our pipeline
  639. DatasetIterator di(my_tree_);
  640. TensorMap tensor_map;
  641. ASSERT_OK(di.GetNextAsMap(&tensor_map));
  642. EXPECT_TRUE(rc.IsOk());
  643. uint64_t i = 0;
  644. int32_t label = 0;
  645. int32_t img_class[] = {0, 1, 2, 3};
  646. std::string result;
  647. while (tensor_map.size() != 0) {
  648. tensor_map["label"]->GetItemAt<int32_t>(&label, {});
  649. EXPECT_TRUE(img_class[(i % 44) / 11] == label);
  650. ASSERT_OK(di.GetNextAsMap(&tensor_map));
  651. i++;
  652. }
  653. EXPECT_TRUE(i == 88);
  654. }