GCC Code Coverage Report


Directory: ./
File: tasks/chyokotov_a_seidel_method/mpi/src/ops_mpi.cpp
Date: 2026-01-10 02:40:41
Exec Total Coverage
Lines: 99 100 99.0%
Functions: 9 9 100.0%
Branches: 61 78 78.2%

Line Branch Exec Source
1 #include "chyokotov_a_seidel_method/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <algorithm>
6 #include <climits>
7 #include <cmath>
8 #include <cstddef>
9 #include <utility>
10 #include <vector>
11
12 #include "chyokotov_a_seidel_method/common/include/common.hpp"
13
14 namespace chyokotov_a_seidel_method {
15
16
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 ChyokotovASeidelMethodMPI::ChyokotovASeidelMethodMPI(const InType &in) {
17 SetTypeOfTask(GetStaticTypeOfTask());
18 GetInput().first.clear();
19
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 GetInput().first.reserve(in.first.size());
20
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
30 for (const auto &row : in.first) {
21
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 GetInput().first.push_back(row);
22 }
23 GetInput().second.clear();
24
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 GetInput().second = in.second;
25 GetOutput().clear();
26 10 }
27
28 4 bool ChyokotovASeidelMethodMPI::CheckMatrix() {
29 const auto &matrix = GetInput().first;
30 size_t n = matrix[0].size();
31
32
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 4 times.
14 for (const auto &row : matrix) {
33
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (row.size() != n) {
34 return false;
35 }
36 }
37
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 4 times.
14 for (size_t i = 0; i < n; ++i) {
38 double sum = 0.0;
39
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 10 times.
40 for (size_t j = 0; j < n; ++j) {
40
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
30 if (i != j) {
41 20 sum += std::abs(matrix[i][j]);
42 }
43 }
44
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (std::abs(matrix[i][i]) <= sum) {
45 return false;
46 }
47 }
48 return true;
49 }
50
51 10 bool ChyokotovASeidelMethodMPI::ValidationImpl() {
52 10 int rank{};
53
54 10 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
55
56 10 int is_valid = 1;
57
58
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 if (rank == 0) {
59 const auto &matrix = GetInput().first;
60 const auto &vec = GetInput().second;
61
62
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 if (!matrix.empty()) {
63
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 if (vec.size() != matrix.size() || !CheckMatrix()) {
64 is_valid = 0;
65 }
66 }
67 }
68
69 10 MPI_Bcast(&is_valid, 1, MPI_INT, 0, MPI_COMM_WORLD);
70
71 10 return (is_valid == 1);
72 }
73
74 10 bool ChyokotovASeidelMethodMPI::PreProcessingImpl() {
75 10 GetOutput().resize(GetInput().first.size(), 0.0);
76 if (GetInput().first.empty()) {
77 return true;
78 }
79 return true;
80 }
81
82 10 void ChyokotovASeidelMethodMPI::ExchangeMatrixData(int rank, int size, int n, std::vector<std::vector<double>> &a,
83 std::vector<double> &b, const std::vector<int> &displs,
84 int local_rows) {
85
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 if (rank == 0) {
86 const auto &matrix = GetInput().first;
87 const auto &vector = GetInput().second;
88
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5 times.
11 for (int i = 0; i < local_rows; i++) {
89 6 a[i] = matrix[i];
90 6 b[i] = vector[i];
91 }
92
93 5 int base = n / size;
94 5 int rem = n % size;
95
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 for (int proc = 1; proc < size; proc++) {
96
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 int proc_rows = base + (proc < rem ? 1 : 0);
97 5 int proc_start = displs[proc];
98
99
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 5 times.
9 for (int i = 0; i < proc_rows; i++) {
100 4 int row_idx = proc_start + i;
101 4 MPI_Send(matrix[row_idx].data(), n, MPI_DOUBLE, proc, 0, MPI_COMM_WORLD);
102 4 MPI_Send(&vector[row_idx], 1, MPI_DOUBLE, proc, 1, MPI_COMM_WORLD);
103 }
104 }
105 } else {
106
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 5 times.
9 for (int i = 0; i < local_rows; i++) {
107 4 MPI_Recv(a[i].data(), n, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
108 4 MPI_Recv(&b[i], 1, MPI_DOUBLE, 0, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
109 }
110 }
111 10 }
112
113 10 std::pair<int, int> ChyokotovASeidelMethodMPI::DistributeMatrixData(int rank, int size, int n,
114 std::vector<std::vector<double>> &a,
115 std::vector<double> &b, std::vector<int> &displs,
116 std::vector<int> &counts) {
117 10 int base = n / size;
118 10 int rem = n % size;
119
120
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 int local_rows = base + (rank < rem ? 1 : 0);
121 10 int local_start = (rank * base) + std::min(rank, rem);
122
123 10 a.resize(local_rows);
124
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 for (auto &row : a) {
125 10 row.resize(n);
126 }
127 10 b.resize(local_rows);
128
129
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
30 for (int i = 0; i < size; i++) {
130
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 10 times.
36 counts[i] = base + (i < rem ? 1 : 0);
131
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 displs[i] = (i == 0) ? 0 : displs[i - 1] + counts[i - 1];
132 }
133
134 10 ExchangeMatrixData(rank, size, n, a, b, displs, local_rows);
135
136 10 return std::make_pair(local_rows, local_start);
137 }
138
139 10 void ChyokotovASeidelMethodMPI::Iteration(int n, int local_rows, int local_start,
140 std::vector<std::vector<double>> &my_a, std::vector<double> &my_b,
141 std::vector<int> &displs, std::vector<int> &counts) {
142 10 std::vector<double> my_x(local_rows);
143 std::vector<double> &x = GetOutput();
144
145
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
60 for (int iter = 0; iter < 1000; iter++) {
146 60 double local_max_diff = 0.0;
147
148
2/2
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 60 times.
139 for (int i = 0; i < local_rows; i++) {
149 79 int global_i = local_start + i;
150 79 double sum = my_b[i];
151
152
2/2
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 79 times.
158 for (int j = 0; j < global_i; j++) {
153 79 sum -= my_a[i][j] * x[j];
154 }
155
2/2
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 79 times.
158 for (int j = global_i + 1; j < n; j++) {
156 79 sum -= my_a[i][j] * x[j];
157 }
158
159 79 double new_xi = sum / my_a[i][global_i];
160 79 double diff = std::abs(new_xi - x[global_i]);
161
162 79 local_max_diff = std::max(local_max_diff, diff);
163
164 79 my_x[i] = new_xi;
165 79 x[global_i] = new_xi;
166 }
167
168
1/2
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
60 MPI_Allgatherv(MPI_IN_PLACE, 0, MPI_DATATYPE_NULL, x.data(), counts.data(), displs.data(), MPI_DOUBLE,
169 MPI_COMM_WORLD);
170
171 60 double global_diff{};
172
1/2
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
60 MPI_Allreduce(&local_max_diff, &global_diff, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
173
174
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 10 times.
60 if (global_diff < 0.00001) {
175 break;
176 }
177 }
178 10 }
179
180 10 bool ChyokotovASeidelMethodMPI::RunImpl() {
181 10 int rank{};
182 10 int size{};
183
184 10 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
185 10 MPI_Comm_size(MPI_COMM_WORLD, &size);
186
187 10 int n{};
188
189
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 if (rank == 0) {
190 auto &matrix = GetInput().first;
191 5 n = static_cast<int>(matrix.size());
192 }
193
194 10 MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);
195
196 10 std::vector<int> displs(size);
197
1/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
10 std::vector<int> counts(size);
198
199 10 std::vector<std::vector<double>> my_a;
200 10 std::vector<double> my_b;
201
202
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 std::pair<int, int> p = DistributeMatrixData(rank, size, n, my_a, my_b, displs, counts);
203 10 int local_rows = p.first;
204 10 int local_start = p.second;
205
206
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 Iteration(n, local_rows, local_start, my_a, my_b, displs, counts);
207
208 10 return true;
209 10 }
210
211 10 bool ChyokotovASeidelMethodMPI::PostProcessingImpl() {
212 10 return true;
213 }
214
215 } // namespace chyokotov_a_seidel_method
216