123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- //#define DEBUG
- #include "mpi.h"
- #include <cstdio>
- #include <cmath>
- #include <list>
- #include <tuple>
- #include "data_format.hpp"
- #include "data_output.hpp"
- #include "function.hpp"
- #include "integral_calc.hpp"
- Interval_t get_local_interval(double inf, double sup, size_t interval_count, size_t current_rank, size_t proc_count);
- int main(int argc, char* argv[]){
- freopen("input.txt", "r", stdin);
- // Локальные параметры
- int proc_count;
- int current_rank;
- MPI_Status mpi_status;
- size_t IO_PROC_RANK = 0;
- size_t INTERVAL_MSG = 0;
- size_t RESULT_MSG = 1;
- size_t test_count = 0;
- double inf = 0;
- double sup = 0;
- double param = 0;
-
- std::list<trip_t> integral_list;
- //-------------------------------------------------------------
- // MPI - часть
- MPI_Init(&argc, &argv);
-
- MPI_Comm_size(MPI_COMM_WORLD, &proc_count);
- MPI_Comm_rank(MPI_COMM_WORLD, ¤t_rank);
- std::cin >> inf >> sup >> param;
- std::cin >> test_count;
- for(int i = 0; i < test_count; ++i){
- size_t interval_count = 0;
- double integral_val = 0;
- double calc_param = 0;
- bool out_flag = false;
-
- int mpi_bufpos = 0;
- char mpi_buf[4 * sizeof(double)+1];
- double start = MPI_Wtime();
- //// Чтение и обмен входными данными
- if(current_rank == IO_PROC_RANK){
- std::cin >> calc_param;
- if(calc_param >= 1){
- interval_count = calc_param;
- out_flag = true;
- }
- else{
- interval_count = 1.0 / calc_param;
- out_flag = false;
- }
- #ifdef DEBUG
- std::cout << test_count << " " << interval_count << '\n';
- #endif // DEBUG
- //
-
- MPI_Pack(&inf, 1, MPI_DOUBLE, mpi_buf, sizeof(mpi_buf), &mpi_bufpos, MPI_COMM_WORLD);
- MPI_Pack(&sup, 1, MPI_DOUBLE, mpi_buf, sizeof(mpi_buf), &mpi_bufpos, MPI_COMM_WORLD);
- MPI_Pack(¶m, 1, MPI_DOUBLE, mpi_buf, sizeof(mpi_buf), &mpi_bufpos, MPI_COMM_WORLD);
- MPI_Pack(&interval_count, 1, MPI_UINT32_T, mpi_buf, sizeof(mpi_buf), &mpi_bufpos, MPI_COMM_WORLD);
-
- }
-
- MPI_Bcast(&mpi_buf
- , sizeof(mpi_buf)
- , MPI_PACKED
- , IO_PROC_RANK
- , MPI_COMM_WORLD);
- if(current_rank != IO_PROC_RANK){
- MPI_Unpack(mpi_buf, sizeof(mpi_buf), &mpi_bufpos, &inf, 1, MPI_DOUBLE, MPI_COMM_WORLD);
- MPI_Unpack(mpi_buf, sizeof(mpi_buf), &mpi_bufpos, &sup, 1, MPI_DOUBLE, MPI_COMM_WORLD);
- MPI_Unpack(mpi_buf, sizeof(mpi_buf), &mpi_bufpos, ¶m, 1, MPI_DOUBLE, MPI_COMM_WORLD);
- MPI_Unpack(mpi_buf, sizeof(mpi_buf), &mpi_bufpos, &interval_count, 1, MPI_UINT32_T, MPI_COMM_WORLD);
- }
- ////-------------------------------------------------------------
- //// Вычисления
- Interval_t local_interval = get_local_interval(inf, sup, interval_count, current_rank, proc_count);
- #ifdef DEBUG
- std::cout << ">>Local inf: " << local_interval.inf << '\n';
- std::cout << ">>Local sup: " << local_interval.sup << '\n';
- std::cout << ">>Local inc_count: " << local_interval.increase_count << '\n';
- #endif // DEBUG
-
- double local_res = integral_calc(param, local_interval);
- #ifdef DEBUG
- std::cout << "Local res: " << local_res << '\n';
- #endif // DEBUG
- ////-------------------------------------------------------------
- //// Обмен результатами вычислений
- MPI_Reduce(&local_res
- , &integral_val
- , sizeof(local_res)/sizeof(double)
- , MPI_DOUBLE
- , MPI_SUM
- , IO_PROC_RANK
- , MPI_COMM_WORLD);
- if(current_rank == IO_PROC_RANK){
- #ifdef DEBUG
- std::cout << "Результат: " << integral_val << '\n';
- std::cout << "Образец: " << (primal(sup, param) - primal(inf, param)) << '\n';
- #endif // DEBUG
- double exact_val = primal(sup, param) - primal(inf, param);
- double err = fabsl(integral_val - exact_val) / fabsl(integral_val);
- double difftime = MPI_Wtime() - start;
- integral_list.push_back(std::make_tuple(interval_count, err, difftime, out_flag));
- }
- ////-------------------------------------------------------------
- }
- //// Вывод результатов
- if(current_rank == IO_PROC_RANK)
- print_table_2(integral_list);
- ////-------------------------------------------------------------
-
- MPI_Finalize();
- //-------------------------------------------------------------
- return 0;
- }
- Interval_t get_local_interval(double inf, double sup, size_t interval_count, size_t current_rank, size_t proc_count){
- Interval_t res;
- double increase = (sup - inf) / (double) interval_count;
- size_t base = interval_count / proc_count;
- size_t residue = interval_count % proc_count;
- res.increase_count = base + (residue > current_rank ? 1 : 0);
- res.inf = inf + increase *
- (base * current_rank + (residue > current_rank ? current_rank : residue));
- res.sup = res.inf + increase * res.increase_count;
-
- return res;
- }
|