GCC Code Coverage Report


Directory: ./
File: tasks/makoveeva_s_simple_iteration/mpi/src/ops_mpi.cpp
Date: 2026-01-27 01:59:34
Exec Total Coverage
Lines: 102 102 100.0%
Functions: 9 9 100.0%
Branches: 55 88 62.5%

Line Branch Exec Source
1 #include "makoveeva_s_simple_iteration/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <cmath>
6 #include <cstddef>
7 #include <cstdlib>
8 #include <vector>
9
10 #include "makoveeva_s_simple_iteration/common/include/common.hpp"
11
12 namespace makoveeva_s_simple_iteration {
13
14 namespace {
15 constexpr double kRelaxationFactor = 0.5;
16 constexpr double kEpsilon = 1e-6;
17 constexpr int kMaxIterations = 1000;
18
19 20 void CalculateRowsDistribution(int n, int size, std::vector<int> &row_counts, std::vector<int> &row_displs,
20 std::vector<int> &matrix_counts, std::vector<int> &matrix_displs) {
21 int row_offset = 0;
22 int matrix_offset = 0;
23
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 20 times.
60 for (int proc = 0; proc < size; ++proc) {
24 40 int base_rows = n / size;
25
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 10 times.
40 int extra = (proc < (n % size)) ? 1 : 0;
26 40 int proc_rows = base_rows + extra;
27
28 40 row_counts[proc] = proc_rows;
29 40 row_displs[proc] = row_offset;
30 40 matrix_counts[proc] = proc_rows * n;
31 40 matrix_displs[proc] = matrix_offset;
32
33 40 row_offset += proc_rows;
34 40 matrix_offset += proc_rows * n;
35 }
36 20 }
37
38 10 void InitializeMatrixAndVector(std::vector<double> &flat_matrix, std::vector<double> &b, int n) {
39 10 const auto matrix_size = static_cast<size_t>(n) * static_cast<size_t>(n);
40 10 flat_matrix.resize(matrix_size, 0.0);
41 10 b.resize(static_cast<size_t>(n), 0.0);
42
43
2/2
✓ Branch 0 taken 143 times.
✓ Branch 1 taken 10 times.
153 for (int i = 0; i < n; ++i) {
44 143 const auto i_idx = static_cast<size_t>(i);
45 const auto n_idx = static_cast<size_t>(n);
46
47 143 flat_matrix[(i_idx * n_idx) + i_idx] = static_cast<double>(n) + 5.0;
48
49
2/2
✓ Branch 0 taken 4213 times.
✓ Branch 1 taken 143 times.
4356 for (int j = 0; j < n; ++j) {
50
2/2
✓ Branch 0 taken 4070 times.
✓ Branch 1 taken 143 times.
4213 if (i != j) {
51 4070 const auto j_idx = static_cast<size_t>(j);
52 4070 flat_matrix[(i_idx * n_idx) + j_idx] = 1.0 / (static_cast<double>(std::abs(i - j)) + 1.0);
53 }
54 }
55
56
2/2
✓ Branch 0 taken 4213 times.
✓ Branch 1 taken 143 times.
4356 for (int j = 0; j < n; ++j) {
57 4213 const auto j_idx = static_cast<size_t>(j);
58 4213 b[i_idx] += flat_matrix[(i_idx * n_idx) + j_idx] * static_cast<double>(j + 1);
59 }
60 }
61 10 }
62
63 460 double ComputeLocalProduct(const std::vector<double> &local_matrix, const std::vector<double> &x,
64 const std::vector<double> &local_b, std::vector<double> &local_x_new, int local_rows,
65 int start_row, int n) {
66 double local_diff = 0.0;
67
68
2/2
✓ Branch 0 taken 3506 times.
✓ Branch 1 taken 460 times.
3966 for (int i = 0; i < local_rows; ++i) {
69 3506 const auto i_idx = static_cast<size_t>(i);
70 3506 const auto n_idx = static_cast<size_t>(n);
71
72 double sum = 0.0;
73
2/2
✓ Branch 0 taken 106558 times.
✓ Branch 1 taken 3506 times.
110064 for (int j = 0; j < n; ++j) {
74 106558 const auto j_idx = static_cast<size_t>(j);
75 106558 sum += local_matrix[(i_idx * n_idx) + j_idx] * x[j_idx];
76 }
77
78 3506 const int global_i = start_row + i;
79 3506 const auto global_idx = static_cast<size_t>(global_i);
80
81 3506 local_x_new[i_idx] =
82 3506 x[global_idx] + (kRelaxationFactor * (local_b[i_idx] - sum) / local_matrix[(i_idx * n_idx) + global_idx]);
83
84 3506 double diff = local_x_new[i_idx] - x[global_idx];
85 3506 local_diff += diff * diff;
86 }
87
88 460 return local_diff;
89 }
90
91 10 int ComputeFinalResult(const std::vector<double> &x, int n) {
92 double sum = 0.0;
93
2/2
✓ Branch 0 taken 143 times.
✓ Branch 1 taken 10 times.
153 for (int i = 0; i < n; ++i) {
94 143 sum += x[static_cast<size_t>(i)];
95 }
96 10 return static_cast<int>(std::round(sum));
97 }
98
99 } // namespace
100
101 20 MakoveevaSSimpleIterationMPI::MakoveevaSSimpleIterationMPI(const InType &in) {
102 SetTypeOfTask(GetStaticTypeOfTask());
103 20 GetInput() = in;
104 GetOutput() = 0;
105 20 }
106
107 20 bool MakoveevaSSimpleIterationMPI::ValidationImpl() {
108 20 int rank = 0;
109 20 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
110
111 20 int n = GetInput();
112 20 MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);
113
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (rank != 0) {
114 10 GetInput() = n;
115 }
116
117 20 int is_valid = 0;
118
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (rank == 0) {
119
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 is_valid = (GetInput() > 0) ? 1 : 0;
120 }
121 20 MPI_Bcast(&is_valid, 1, MPI_INT, 0, MPI_COMM_WORLD);
122 20 return is_valid != 0;
123 }
124
125 20 bool MakoveevaSSimpleIterationMPI::PreProcessingImpl() {
126 20 return true;
127 }
128
129 20 bool MakoveevaSSimpleIterationMPI::RunImpl() {
130 20 int rank = 0;
131 20 int size = 0;
132 20 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
133 20 MPI_Comm_size(MPI_COMM_WORLD, &size);
134
135 20 int n = GetInput();
136 20 MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);
137
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (rank != 0) {
138 10 GetInput() = n;
139 }
140
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 if (n <= 0) {
141 return false;
142 }
143
144 20 std::vector<int> row_counts(static_cast<size_t>(size));
145
1/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
20 std::vector<int> row_displs(static_cast<size_t>(size));
146
1/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
20 std::vector<int> matrix_counts(static_cast<size_t>(size));
147
1/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
20 std::vector<int> matrix_displs(static_cast<size_t>(size));
148
149 20 CalculateRowsDistribution(n, size, row_counts, row_displs, matrix_counts, matrix_displs);
150
151
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 const int local_rows = row_counts[rank];
152 20 const int start_row = row_displs[rank];
153
154 20 std::vector<double> flat_matrix;
155 20 std::vector<double> b;
156
157
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (rank == 0) {
158
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 InitializeMatrixAndVector(flat_matrix, b, n);
159 }
160
161
1/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
20 std::vector<double> local_matrix(static_cast<size_t>(local_rows) * static_cast<size_t>(n));
162
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
30 MPI_Scatterv(rank == 0 ? flat_matrix.data() : nullptr, matrix_counts.data(), matrix_displs.data(), MPI_DOUBLE,
163 local_matrix.data(), local_rows * n, MPI_DOUBLE, 0, MPI_COMM_WORLD);
164
165
3/6
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
20 std::vector<double> local_b(static_cast<size_t>(local_rows));
166
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
30 MPI_Scatterv(rank == 0 ? b.data() : nullptr, row_counts.data(), row_displs.data(), MPI_DOUBLE, local_b.data(),
167 local_rows, MPI_DOUBLE, 0, MPI_COMM_WORLD);
168
169
1/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
20 std::vector<double> x(static_cast<size_t>(n), 0.0);
170
1/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
20 std::vector<double> x_new(static_cast<size_t>(n), 0.0);
171
1/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
20 std::vector<double> local_x_new(static_cast<size_t>(local_rows), 0.0);
172
173 bool converged = false;
174
175
2/2
✓ Branch 0 taken 460 times.
✓ Branch 1 taken 20 times.
480 for (int iteration = 0; iteration < kMaxIterations && !converged; ++iteration) {
176
1/2
✓ Branch 2 taken 460 times.
✗ Branch 3 not taken.
460 const double local_diff = ComputeLocalProduct(local_matrix, x, local_b, local_x_new, local_rows, start_row, n);
177
178
1/2
✓ Branch 1 taken 460 times.
✗ Branch 2 not taken.
460 MPI_Allgatherv(local_x_new.data(), local_rows, MPI_DOUBLE, x_new.data(), row_counts.data(), row_displs.data(),
179 MPI_DOUBLE, MPI_COMM_WORLD);
180
181 460 double global_diff_sq = 0.0;
182
1/2
✓ Branch 1 taken 460 times.
✗ Branch 2 not taken.
460 MPI_Allreduce(&local_diff, &global_diff_sq, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
183
184 460 const double global_diff = std::sqrt(global_diff_sq);
185 460 converged = (global_diff < kEpsilon);
186
187 x.swap(x_new);
188 }
189
190
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (rank == 0) {
191 10 GetOutput() = ComputeFinalResult(x, n);
192 }
193
194
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 MPI_Bcast(&GetOutput(), 1, MPI_INT, 0, MPI_COMM_WORLD);
195 return true;
196 }
197
198 20 bool MakoveevaSSimpleIterationMPI::PostProcessingImpl() {
199 20 return GetOutput() > 0;
200 }
201
202 } // namespace makoveeva_s_simple_iteration
203