AUTH's THMMY "Parallel and distributed systems" course assignments.
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 
 
 
 

212 Zeilen
6.8 KiB

  1. /**
  2. * \file
  3. * \brief PDS HW2 tests
  4. *
  5. * To run these test execute:
  6. * export OMP_NUM_THREADS=4 # optional to see parallelization speed-up
  7. * make tests
  8. * mpirun -np <N> ./out/tests
  9. *
  10. * Note:
  11. * Yes each process runs the entire test suite!!
  12. *
  13. * \author
  14. * Christos Choutouridis AEM:8997
  15. * <cchoutou@ece.auth.gr>
  16. */
  17. #include <gtest/gtest.h>
  18. #include <mpi.h>
  19. #include <random>
  20. #include "distsort.hpp"
  21. /*
  22. * Global fixtures
  23. */
  24. // MPI handler for the test session
  25. MPI_t<> ts_mpi;
  26. // Mersenne seeded from hw if possible. range: [type_min, type_max]
  27. std::random_device rd;
  28. std::mt19937 gen(rd());
  29. class TMPIdistSort : public ::testing::Test {
  30. protected:
  31. static void SetUpTestSuite() {
  32. int argc = 0;
  33. char** argv = nullptr;
  34. ts_mpi.init(&argc, &argv);
  35. }
  36. static void TearDownTestSuite() {
  37. ts_mpi.finalize();
  38. }
  39. };
  40. /*
  41. * MPI: SysTest (acceptance)
  42. * Each process executes distBubbletonic for uin8_t [16]
  43. */
  44. TEST_F(TMPIdistSort, distBubbletonic_test1) {
  45. // Create and fill vector
  46. using tsValue_t = uint8_t; // Test parameters
  47. size_t ts_buffer_size = 16;
  48. ShadowedVec_t<tsValue_t> ts_Data;
  49. std::uniform_int_distribution<tsValue_t > dis(
  50. std::numeric_limits<tsValue_t>::min(),
  51. std::numeric_limits<tsValue_t>::max()
  52. );
  53. ts_Data.resize(ts_buffer_size);
  54. std::generate(ts_Data.begin(), ts_Data.end(), [&]() { return dis(gen); });
  55. // Execute function under test in all processes
  56. distBubbletonic(ts_Data, ts_mpi.size(), ts_mpi.rank());
  57. // Local min and max
  58. auto local_min = *std::min_element(ts_Data.begin(), ts_Data.end());
  59. auto local_max = *std::max_element(ts_Data.begin(), ts_Data.end());
  60. // Gather min/max to rank 0
  61. std::vector<tsValue_t> global_mins(ts_mpi.size());
  62. std::vector<tsValue_t> global_maxes(ts_mpi.size());
  63. MPI_Datatype datatype = MPI_TypeMapper<tsValue_t>::getType();
  64. MPI_Gather(&local_min, 1, datatype, global_mins.data(), 1, datatype, 0, MPI_COMM_WORLD);
  65. MPI_Gather(&local_max, 1, datatype, global_maxes.data(), 1, datatype, 0, MPI_COMM_WORLD);
  66. // Check results
  67. EXPECT_EQ(std::is_sorted(ts_Data.begin(), ts_Data.end()), true);
  68. if (ts_mpi.rank() == 0) {
  69. for (size_t i = 1; i < global_mins.size(); ++i) {
  70. EXPECT_LE(global_maxes[i - 1], global_mins[i]);
  71. }
  72. }
  73. }
  74. /*
  75. * MPI: SysTest (acceptance)
  76. * Each process executes distBubbletonic for uin32_t [1 << 16]
  77. */
  78. TEST_F(TMPIdistSort, distBubbletonic_test2) {
  79. // Create and fill vector
  80. using tsValue_t = uint32_t; // Test parameters
  81. size_t ts_buffer_size = 1 << 16;
  82. ShadowedVec_t<tsValue_t> ts_Data;
  83. std::uniform_int_distribution<tsValue_t > dis(
  84. std::numeric_limits<tsValue_t>::min(),
  85. std::numeric_limits<tsValue_t>::max()
  86. );
  87. ts_Data.resize(ts_buffer_size);
  88. std::generate(ts_Data.begin(), ts_Data.end(), [&]() { return dis(gen); });
  89. // Execute function under test in all processes
  90. distBubbletonic(ts_Data, ts_mpi.size(), ts_mpi.rank());
  91. // Local min and max
  92. auto local_min = *std::min_element(ts_Data.begin(), ts_Data.end());
  93. auto local_max = *std::max_element(ts_Data.begin(), ts_Data.end());
  94. // Gather min/max to rank 0
  95. std::vector<tsValue_t> global_mins(ts_mpi.size());
  96. std::vector<tsValue_t> global_maxes(ts_mpi.size());
  97. MPI_Datatype datatype = MPI_TypeMapper<tsValue_t>::getType();
  98. MPI_Gather(&local_min, 1, datatype, global_mins.data(), 1, datatype, 0, MPI_COMM_WORLD);
  99. MPI_Gather(&local_max, 1, datatype, global_maxes.data(), 1, datatype, 0, MPI_COMM_WORLD);
  100. // Check results
  101. EXPECT_EQ(std::is_sorted(ts_Data.begin(), ts_Data.end()), true);
  102. if (ts_mpi.rank() == 0) {
  103. for (size_t i = 1; i < global_mins.size(); ++i) {
  104. EXPECT_LE(global_maxes[i - 1], global_mins[i]);
  105. }
  106. }
  107. }
  108. /*
  109. * MPI: SysTest (acceptance)
  110. * Each process executes distBitonic for uin8_t [16]
  111. */
  112. TEST_F(TMPIdistSort, distBitonic_test1) {
  113. // Create and fill vector
  114. using tsValue_t = uint8_t; // Test parameters
  115. size_t ts_buffer_size = 16;
  116. ShadowedVec_t<tsValue_t> ts_Data;
  117. std::uniform_int_distribution<tsValue_t > dis(
  118. std::numeric_limits<tsValue_t>::min(),
  119. std::numeric_limits<tsValue_t>::max()
  120. );
  121. ts_Data.resize(ts_buffer_size);
  122. std::generate(ts_Data.begin(), ts_Data.end(), [&]() { return dis(gen); });
  123. // Execute function under test in all processes
  124. distBitonic(ts_Data, ts_mpi.size(), ts_mpi.rank());
  125. // Local min and max
  126. auto local_min = *std::min_element(ts_Data.begin(), ts_Data.end());
  127. auto local_max = *std::max_element(ts_Data.begin(), ts_Data.end());
  128. // Gather min/max to rank 0
  129. std::vector<tsValue_t> global_mins(ts_mpi.size());
  130. std::vector<tsValue_t> global_maxes(ts_mpi.size());
  131. MPI_Datatype datatype = MPI_TypeMapper<tsValue_t>::getType();
  132. MPI_Gather(&local_min, 1, datatype, global_mins.data(), 1, datatype, 0, MPI_COMM_WORLD);
  133. MPI_Gather(&local_max, 1, datatype, global_maxes.data(), 1, datatype, 0, MPI_COMM_WORLD);
  134. // Check results
  135. EXPECT_EQ(std::is_sorted(ts_Data.begin(), ts_Data.end()), true);
  136. if (ts_mpi.rank() == 0) {
  137. for (size_t i = 1; i < global_mins.size(); ++i) {
  138. EXPECT_LE(global_maxes[i - 1], global_mins[i]);
  139. }
  140. }
  141. }
  142. /*
  143. * MPI: SysTest (acceptance)
  144. * Each process executes distBitonic for uin32_t [1 << 16]
  145. */
  146. TEST_F(TMPIdistSort, distBitonic_test2) {
  147. // Create and fill vector
  148. using tsValue_t = uint32_t; // Test parameters
  149. size_t ts_buffer_size = 1 << 16;
  150. ShadowedVec_t<tsValue_t> ts_Data;
  151. std::uniform_int_distribution<tsValue_t > dis(
  152. std::numeric_limits<tsValue_t>::min(),
  153. std::numeric_limits<tsValue_t>::max()
  154. );
  155. ts_Data.resize(ts_buffer_size);
  156. std::generate(ts_Data.begin(), ts_Data.end(), [&]() { return dis(gen); });
  157. // Execute function under test in all processes
  158. distBitonic(ts_Data, ts_mpi.size(), ts_mpi.rank());
  159. // Local min and max
  160. auto local_min = *std::min_element(ts_Data.begin(), ts_Data.end());
  161. auto local_max = *std::max_element(ts_Data.begin(), ts_Data.end());
  162. // Gather min/max to rank 0
  163. std::vector<tsValue_t> global_mins(ts_mpi.size());
  164. std::vector<tsValue_t> global_maxes(ts_mpi.size());
  165. MPI_Datatype datatype = MPI_TypeMapper<tsValue_t>::getType();
  166. MPI_Gather(&local_min, 1, datatype, global_mins.data(), 1, datatype, 0, MPI_COMM_WORLD);
  167. MPI_Gather(&local_max, 1, datatype, global_maxes.data(), 1, datatype, 0, MPI_COMM_WORLD);
  168. // Check results
  169. EXPECT_EQ(std::is_sorted(ts_Data.begin(), ts_Data.end()), true);
  170. if (ts_mpi.rank() == 0) {
  171. for (size_t i = 1; i < global_mins.size(); ++i) {
  172. EXPECT_LE(global_maxes[i - 1], global_mins[i]);
  173. }
  174. }
  175. }