GCC Code Coverage Report


Directory: ./
File: tasks/Rastvorov_K_Simple_iteration_method/mpi/src/ops_mpi.cpp
Date: 2026-01-27 01:59:34
Exec Total Coverage
Lines: 0 65 0.0%
Functions: 0 6 0.0%
Branches: 0 52 0.0%

Line Branch Exec Source
1 #include "Rastvorov_K_Simple_iteration_method/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <algorithm>
6 #include <cmath>
7 #include <cstddef>
8 #include <utility>
9 #include <vector>
10
11 #include "Rastvorov_K_Simple_iteration_method/common/include/common.hpp"
12
13 namespace rastvorov_k_simple_iteration_method {
14
15 namespace {
16
17 inline void ComputeRange(std::size_t rank, std::size_t size, std::size_t total, std::size_t &begin, std::size_t &end) {
18 const std::size_t base = total / size;
19 const std::size_t rem = total % size;
20
21 if (rank < rem) {
22 begin = rank * (base + 1);
23 end = begin + base + 1;
24 } else {
25 begin = (rem * (base + 1)) + ((rank - rem) * base);
26 end = begin + base;
27 }
28 }
29
30 inline std::vector<double> RunIterations(int n, std::size_t local_n, std::vector<double> x_local) {
31 constexpr double kEps = 1e-9;
32 constexpr int kMaxIter = 2000;
33
34 std::vector<double> x_new_local(local_n, 0.0);
35 const auto denom = static_cast<double>(2 * n);
36
37 for (int iter = 0; iter < kMaxIter; ++iter) {
38 double local_sum = 0.0;
39 for (double v : x_local) {
40 local_sum += v;
41 }
42
43 double global_sum = 0.0;
44 MPI_Allreduce(&local_sum, &global_sum, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
45
46 double local_max_diff = 0.0;
47 for (std::size_t idx = 0; idx < local_n; ++idx) {
48 const double old = x_local[idx];
49 const double xnew = (1.0 - global_sum + old) / denom;
50 x_new_local[idx] = xnew;
51 local_max_diff = std::max(local_max_diff, std::abs(xnew - old));
52 }
53
54 x_local.swap(x_new_local);
55
56 double global_max_diff = 0.0;
57 MPI_Allreduce(&local_max_diff, &global_max_diff, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
58
59 if (global_max_diff < kEps) {
60 break;
61 }
62 }
63
64 return x_local;
65 }
66
67 } // namespace
68
69 RastvorovKSimpleIterationMethodMPI::RastvorovKSimpleIterationMethodMPI(const InType &in) {
70 SetTypeOfTask(GetStaticTypeOfTask());
71 GetInput() = in;
72 GetOutput().clear();
73 }
74
75 bool RastvorovKSimpleIterationMethodMPI::ValidationImpl() {
76 return GetInput() > 0;
77 }
78
79 bool RastvorovKSimpleIterationMethodMPI::PreProcessingImpl() {
80 GetOutput().assign(static_cast<std::size_t>(std::max(GetInput(), 0)), 0.0);
81 return true;
82 }
83
84 bool RastvorovKSimpleIterationMethodMPI::RunImpl() {
85 int rank = 0;
86 int size = 1;
87 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
88 MPI_Comm_size(MPI_COMM_WORLD, &size);
89
90 const int n = GetInput();
91 if (n <= 0) {
92 if (rank == 0) {
93 GetOutput().clear();
94 }
95 return false;
96 }
97
98 const auto total = static_cast<std::size_t>(n);
99
100 std::size_t begin = 0;
101 std::size_t end = 0;
102 ComputeRange(static_cast<std::size_t>(rank), static_cast<std::size_t>(size), total, begin, end);
103 const std::size_t local_n = (end > begin) ? (end - begin) : 0;
104
105 std::vector<double> x_local(local_n, 0.0);
106 x_local = RunIterations(n, local_n, std::move(x_local));
107
108 std::vector<int> recvcounts;
109 std::vector<int> displs;
110 std::vector<double> x_full;
111
112 if (rank == 0) {
113 recvcounts.resize(static_cast<std::size_t>(size));
114 displs.resize(static_cast<std::size_t>(size));
115
116 for (int proc = 0; proc < size; ++proc) {
117 std::size_t b = 0;
118 std::size_t e = 0;
119 ComputeRange(static_cast<std::size_t>(proc), static_cast<std::size_t>(size), total, b, e);
120 recvcounts[static_cast<std::size_t>(proc)] = static_cast<int>(e - b);
121 displs[static_cast<std::size_t>(proc)] = static_cast<int>(b);
122 }
123
124 x_full.assign(total, 0.0);
125 }
126
127 MPI_Gatherv(x_local.data(), static_cast<int>(local_n), MPI_DOUBLE, rank == 0 ? x_full.data() : nullptr,
128 rank == 0 ? recvcounts.data() : nullptr, rank == 0 ? displs.data() : nullptr, MPI_DOUBLE, 0,
129 MPI_COMM_WORLD);
130
131 if (rank == 0) {
132 GetOutput() = x_full;
133 }
134
135 return true;
136 }
137
138 bool RastvorovKSimpleIterationMethodMPI::PostProcessingImpl() {
139 return true;
140 }
141
142 } // namespace rastvorov_k_simple_iteration_method
143