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 29 kB

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