stage_3.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. //#define DEBUG
  2. #include "mpi.h"
  3. #include <cstdio>
  4. #include <cmath>
  5. #include <list>
  6. #include <tuple>
  7. #include "data_format.hpp"
  8. #include "data_output.hpp"
  9. #include "function.hpp"
  10. #include "integral_calc.hpp"
  11. Interval_t get_local_interval(double inf, double sup, size_t interval_count, size_t current_rank, size_t proc_count);
  12. int main(int argc, char* argv[]){
  13. freopen("input.txt", "r", stdin);
  14. // Локальные параметры
  15. int proc_count;
  16. int current_rank;
  17. MPI_Status mpi_status;
  18. size_t IO_PROC_RANK = 0;
  19. size_t INTERVAL_MSG = 0;
  20. size_t RESULT_MSG = 1;
  21. size_t test_count = 0;
  22. double inf = 0;
  23. double sup = 0;
  24. double param = 0;
  25. std::list<trip_t> integral_list;
  26. //-------------------------------------------------------------
  27. // MPI - часть
  28. MPI_Init(&argc, &argv);
  29. MPI_Comm_size(MPI_COMM_WORLD, &proc_count);
  30. MPI_Comm_rank(MPI_COMM_WORLD, &current_rank);
  31. std::cin >> inf >> sup >> param;
  32. std::cin >> test_count;
  33. for(int i = 0; i < test_count; ++i){
  34. size_t interval_count = 0;
  35. double integral_val = 0;
  36. double calc_param = 0;
  37. bool out_flag = false;
  38. int mpi_bufpos = 0;
  39. char mpi_buf[4 * sizeof(double)+1];
  40. double start = MPI_Wtime();
  41. //// Чтение и обмен входными данными
  42. if(current_rank == IO_PROC_RANK){
  43. std::cin >> calc_param;
  44. if(calc_param >= 1){
  45. interval_count = calc_param;
  46. out_flag = true;
  47. }
  48. else{
  49. interval_count = 1.0 / calc_param;
  50. out_flag = false;
  51. }
  52. #ifdef DEBUG
  53. std::cout << test_count << " " << interval_count << '\n';
  54. #endif // DEBUG
  55. //
  56. MPI_Pack(&inf, 1, MPI_DOUBLE, mpi_buf, sizeof(mpi_buf), &mpi_bufpos, MPI_COMM_WORLD);
  57. MPI_Pack(&sup, 1, MPI_DOUBLE, mpi_buf, sizeof(mpi_buf), &mpi_bufpos, MPI_COMM_WORLD);
  58. MPI_Pack(&param, 1, MPI_DOUBLE, mpi_buf, sizeof(mpi_buf), &mpi_bufpos, MPI_COMM_WORLD);
  59. MPI_Pack(&interval_count, 1, MPI_UINT32_T, mpi_buf, sizeof(mpi_buf), &mpi_bufpos, MPI_COMM_WORLD);
  60. }
  61. MPI_Bcast(&mpi_buf
  62. , sizeof(mpi_buf)
  63. , MPI_PACKED
  64. , IO_PROC_RANK
  65. , MPI_COMM_WORLD);
  66. if(current_rank != IO_PROC_RANK){
  67. MPI_Unpack(mpi_buf, sizeof(mpi_buf), &mpi_bufpos, &inf, 1, MPI_DOUBLE, MPI_COMM_WORLD);
  68. MPI_Unpack(mpi_buf, sizeof(mpi_buf), &mpi_bufpos, &sup, 1, MPI_DOUBLE, MPI_COMM_WORLD);
  69. MPI_Unpack(mpi_buf, sizeof(mpi_buf), &mpi_bufpos, &param, 1, MPI_DOUBLE, MPI_COMM_WORLD);
  70. MPI_Unpack(mpi_buf, sizeof(mpi_buf), &mpi_bufpos, &interval_count, 1, MPI_UINT32_T, MPI_COMM_WORLD);
  71. }
  72. ////-------------------------------------------------------------
  73. //// Вычисления
  74. Interval_t local_interval = get_local_interval(inf, sup, interval_count, current_rank, proc_count);
  75. #ifdef DEBUG
  76. std::cout << ">>Local inf: " << local_interval.inf << '\n';
  77. std::cout << ">>Local sup: " << local_interval.sup << '\n';
  78. std::cout << ">>Local inc_count: " << local_interval.increase_count << '\n';
  79. #endif // DEBUG
  80. double local_res = integral_calc(param, local_interval);
  81. #ifdef DEBUG
  82. std::cout << "Local res: " << local_res << '\n';
  83. #endif // DEBUG
  84. ////-------------------------------------------------------------
  85. //// Обмен результатами вычислений
  86. MPI_Reduce(&local_res
  87. , &integral_val
  88. , sizeof(local_res)/sizeof(double)
  89. , MPI_DOUBLE
  90. , MPI_SUM
  91. , IO_PROC_RANK
  92. , MPI_COMM_WORLD);
  93. if(current_rank == IO_PROC_RANK){
  94. #ifdef DEBUG
  95. std::cout << "Результат: " << integral_val << '\n';
  96. std::cout << "Образец: " << (primal(sup, param) - primal(inf, param)) << '\n';
  97. #endif // DEBUG
  98. double exact_val = primal(sup, param) - primal(inf, param);
  99. double err = fabsl(integral_val - exact_val) / fabsl(integral_val);
  100. double difftime = MPI_Wtime() - start;
  101. integral_list.push_back(std::make_tuple(interval_count, err, difftime, out_flag));
  102. }
  103. ////-------------------------------------------------------------
  104. }
  105. //// Вывод результатов
  106. if(current_rank == IO_PROC_RANK)
  107. print_table_2(integral_list);
  108. ////-------------------------------------------------------------
  109. MPI_Finalize();
  110. //-------------------------------------------------------------
  111. return 0;
  112. }
  113. Interval_t get_local_interval(double inf, double sup, size_t interval_count, size_t current_rank, size_t proc_count){
  114. Interval_t res;
  115. double increase = (sup - inf) / (double) interval_count;
  116. size_t base = interval_count / proc_count;
  117. size_t residue = interval_count % proc_count;
  118. res.increase_count = base + (residue > current_rank ? 1 : 0);
  119. res.inf = inf + increase *
  120. (base * current_rank + (residue > current_rank ? current_rank : residue));
  121. res.sup = res.inf + increase * res.increase_count;
  122. return res;
  123. }