GCC Code Coverage Report


Directory: ./
File: tasks/kosolapov_v_gauss_method_tape_hor_scheme/mpi/src/ops_mpi.cpp
Date: 2026-01-10 02:40:41
Exec Total Coverage
Lines: 153 162 94.4%
Functions: 10 13 76.9%
Branches: 105 162 64.8%

Line Branch Exec Source
1 #include "kosolapov_v_gauss_method_tape_hor_scheme/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <algorithm>
6 #include <cmath>
7 #include <cstddef>
8 #include <vector>
9
10 #include "kosolapov_v_gauss_method_tape_hor_scheme/common/include/common.hpp"
11
12 namespace kosolapov_v_gauss_method_tape_hor_scheme {
13
14
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 KosolapovVGaussMethodTapeHorSchemeMPI::KosolapovVGaussMethodTapeHorSchemeMPI(const InType &in) {
15 SetTypeOfTask(GetStaticTypeOfTask());
16
3/6
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 18 times.
✗ Branch 9 not taken.
18 GetInput() = InType(in);
17 GetOutput() = {};
18 18 }
19
20 18 bool KosolapovVGaussMethodTapeHorSchemeMPI::ValidationImpl() {
21 18 int rank = 0;
22 18 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
23
24
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 if (rank == 0) {
25 const auto &input = GetInput();
26
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (input.matrix.empty()) {
27 return false;
28 }
29
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 9 times.
49 for (size_t i = 0; i < input.matrix.size(); ++i) {
30
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (input.matrix[i].size() != input.matrix.size()) {
31 return false;
32 }
33 }
34
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (input.r_side.size() != static_cast<size_t>(input.matrix.size())) {
35 return false;
36 }
37 }
38 return true;
39 }
40
41 18 bool KosolapovVGaussMethodTapeHorSchemeMPI::PreProcessingImpl() {
42 18 int rank = 0;
43 18 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
44
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 if (rank == 0) {
45 const auto &input = GetInput();
46 18 GetOutput() = std::vector<double>(input.matrix.size(), 0.0);
47 } else {
48 9 GetOutput() = std::vector<double>();
49 }
50 18 return true;
51 }
52
53 18 bool KosolapovVGaussMethodTapeHorSchemeMPI::RunImpl() {
54 18 int processes_count = 0;
55 18 int rank = 0;
56 18 MPI_Comm_size(MPI_COMM_WORLD, &processes_count);
57 18 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
58 18 int rows = 0;
59
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 if (rank == 0) {
60 const auto &input = GetInput();
61 9 rows = static_cast<int>(input.matrix.size());
62 }
63 18 MPI_Bcast(&rows, 1, MPI_INT, 0, MPI_COMM_WORLD);
64
65 18 int rows_per_process = rows / processes_count;
66 18 int remainder = rows % processes_count;
67
68
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
18 int start_row = (rank * rows_per_process) + std::min(rank, remainder);
69
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
18 int end_row = start_row + rows_per_process + (rank < remainder ? 1 : 0) - 1;
70 18 int local_rows = end_row - start_row + 1;
71 18 std::vector<std::vector<double>> local_matrix;
72 18 std::vector<double> local_rsd;
73 18 std::vector<int> local_row_indices;
74
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 if (rank == 0) {
75
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 DistributeDataFromRoot(local_matrix, local_rsd, local_row_indices, start_row, local_rows, rows, processes_count,
76 rows_per_process, remainder);
77 } else {
78
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 local_matrix.resize(local_rows);
79
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 local_rsd.resize(local_rows);
80
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 local_row_indices.resize(local_rows);
81
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 9 times.
26 for (int i = 0; i < local_rows; i++) {
82
1/2
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
17 local_matrix[i].resize(rows);
83
1/2
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
17 MPI_Recv(&local_row_indices[i], 1, MPI_INT, 0, i, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
84
1/2
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
17 MPI_Recv(local_matrix[i].data(), rows, MPI_DOUBLE, 0, i, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
85
1/2
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
17 MPI_Recv(&local_rsd[i], 1, MPI_DOUBLE, 0, i, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
86 }
87 }
88
1/4
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
18 std::vector<int> col_order(rows);
89
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 18 times.
98 for (int i = 0; i < rows; ++i) {
90 80 col_order[i] = i;
91 }
92 // Прямой ход метода Гаусса
93
2/4
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
18 if (!ForwardElimination(rank, rows, start_row, end_row, local_rows, local_matrix, col_order, local_rsd,
94 local_row_indices)) {
95 return false;
96 }
97 // ОБРАТНЫЙ ХОД МЕТОДА ГАУССА
98 std::vector<double> global_solution =
99
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 BackwardSubstitution(rows, start_row, end_row, rank, local_rows, local_matrix, local_rsd);
100
1/4
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
18 std::vector<double> final_solution(rows);
101
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 18 times.
98 for (int i = 0; i < rows; i++) {
102 80 final_solution[col_order[i]] = global_solution[i];
103 }
104
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 MPI_Bcast(final_solution.data(), rows, MPI_DOUBLE, 0, MPI_COMM_WORLD);
105
106
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 GetOutput() = final_solution;
107
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 MPI_Barrier(MPI_COMM_WORLD);
108 return true;
109 18 }
110
111 18 bool KosolapovVGaussMethodTapeHorSchemeMPI::PostProcessingImpl() {
112 18 return true;
113 }
114
115 9 void KosolapovVGaussMethodTapeHorSchemeMPI::DistributeDataFromRoot(std::vector<std::vector<double>> &local_matrix,
116 std::vector<double> &local_rsd,
117 std::vector<int> &local_row_indices, int start,
118 int local_rows, int columns, int processes_count,
119 int rows_per_proc, int remainder) {
120 const auto &input = GetInput();
121 9 local_matrix.resize(local_rows);
122 9 local_rsd.resize(local_rows);
123 9 local_row_indices.resize(local_rows);
124
125
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 9 times.
32 for (int i = 0; i < local_rows; i++) {
126 23 local_row_indices[i] = start + i;
127 23 local_matrix[i] = input.matrix[start + i];
128 23 local_rsd[i] = input.r_side[start + i];
129 }
130
131
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 for (int proc = 1; proc < processes_count; proc++) {
132
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 const int proc_start = (proc * rows_per_proc) + std::min(proc, remainder);
133
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 const int proc_end = proc_start + rows_per_proc + (proc < remainder ? 1 : 0);
134 9 const int proc_rows_count = proc_end - proc_start;
135
136
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 9 times.
26 for (int i = 0; i < proc_rows_count; i++) {
137 17 int idx = proc_start + i;
138 17 MPI_Send(&idx, 1, MPI_INT, proc, i, MPI_COMM_WORLD);
139 17 MPI_Send(input.matrix[proc_start + i].data(), columns, MPI_DOUBLE, proc, i, MPI_COMM_WORLD);
140 17 MPI_Send(&input.r_side[proc_start + i], 1, MPI_DOUBLE, proc, i, MPI_COMM_WORLD);
141 }
142 }
143 9 }
144 18 bool KosolapovVGaussMethodTapeHorSchemeMPI::ForwardElimination(
145 int rank, int rows, int start_row, int end_row, int local_rows, std::vector<std::vector<double>> &local_matrix,
146 std::vector<int> &col_order, std::vector<double> &local_rsd, std::vector<int> &local_row_indices) {
147
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 18 times.
98 for (int step = 0; step < rows; step++) {
148 80 int owner_process = -1;
149
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 40 times.
80 if (step >= start_row && step <= end_row) {
150 40 owner_process = rank;
151 }
152 80 int global_owner = 0;
153 80 MPI_Allreduce(&owner_process, &global_owner, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD);
154 80 int pivot_row_local_idx = -1;
155 80 double pivot_value = 0.0;
156 80 int pivot_col = step;
157 80 SelectPivot(rank, owner_process, step, start_row, local_rows, rows, local_matrix, pivot_value, pivot_col,
158 pivot_row_local_idx);
159 80 MPI_Bcast(&pivot_col, 1, MPI_INT, global_owner, MPI_COMM_WORLD);
160 80 MPI_Bcast(&pivot_value, 1, MPI_DOUBLE, global_owner, MPI_COMM_WORLD);
161 80 MPI_Bcast(&pivot_row_local_idx, 1, MPI_INT, global_owner, MPI_COMM_WORLD);
162
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (std::abs(pivot_value) < 1e-12) {
163 GetOutput() = std::vector<double>(rows, 0.0);
164 MPI_Barrier(MPI_COMM_WORLD);
165 return false;
166 }
167 80 SwapColumns(pivot_col, step, local_rows, local_matrix, col_order);
168 80 NormalizePivot(rank, owner_process, pivot_row_local_idx, step, rows, pivot_value, local_matrix, local_rsd);
169 80 std::vector<double> pivot_row(rows - step, 0.0);
170 80 double pivot_rhs = 0.0;
171 80 PriparePivot(rank, owner_process, pivot_row_local_idx, step, rows, pivot_row, pivot_rhs, local_matrix, local_rsd);
172
1/2
✓ Branch 1 taken 80 times.
✗ Branch 2 not taken.
80 MPI_Bcast(pivot_row.data(), rows - step, MPI_DOUBLE, global_owner, MPI_COMM_WORLD);
173
1/2
✓ Branch 1 taken 80 times.
✗ Branch 2 not taken.
80 MPI_Bcast(&pivot_rhs, 1, MPI_DOUBLE, global_owner, MPI_COMM_WORLD);
174 80 RowSub(local_rows, step, rows, local_matrix, local_rsd, local_row_indices, pivot_row, pivot_rhs);
175
1/2
✓ Branch 1 taken 80 times.
✗ Branch 2 not taken.
80 MPI_Barrier(MPI_COMM_WORLD);
176 }
177 return true;
178 }
179 18 std::vector<double> KosolapovVGaussMethodTapeHorSchemeMPI::BackwardSubstitution(
180 int rows, int start_row, int end_row, int rank, int local_rows, std::vector<std::vector<double>> &local_matrix,
181 std::vector<double> &local_rsd) {
182 18 std::vector<double> global_solution(rows, 0.0);
183
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 18 times.
98 for (int step = rows - 1; step >= 0; step--) {
184 80 int owner_process = -1;
185
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 40 times.
80 if (step >= start_row && step <= end_row) {
186 40 owner_process = rank;
187 }
188 80 int global_owner = 0;
189
1/2
✓ Branch 1 taken 80 times.
✗ Branch 2 not taken.
80 MPI_Allreduce(&owner_process, &global_owner, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD);
190 80 double x_value = 0.0;
191
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 40 times.
80 if (rank == owner_process) {
192 40 int local_idx = step - start_row;
193
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 if (local_idx >= 0 && local_idx < local_rows) {
194 40 x_value = local_rsd[local_idx];
195
2/2
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 40 times.
119 for (int col = step + 1; col < rows; col++) {
196 79 x_value -= local_matrix[local_idx][col] * global_solution[col];
197 }
198 }
199 }
200
1/2
✓ Branch 1 taken 80 times.
✗ Branch 2 not taken.
80 MPI_Bcast(&x_value, 1, MPI_DOUBLE, global_owner, MPI_COMM_WORLD);
201
1/2
✓ Branch 1 taken 80 times.
✗ Branch 2 not taken.
80 global_solution[step] = x_value;
202
1/2
✓ Branch 1 taken 80 times.
✗ Branch 2 not taken.
80 MPI_Barrier(MPI_COMM_WORLD);
203 }
204 18 return global_solution;
205 }
206 void KosolapovVGaussMethodTapeHorSchemeMPI::SelectPivot(int rank, int owner_process, int step, int start_row,
207 int local_rows, int rows,
208 const std::vector<std::vector<double>> &local_matrix,
209 double &pivot_value, int &pivot_col, int &pivot_row_local_idx) {
210
2/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 40 times.
80 if (rank == owner_process) {
211 40 int local_idx = step - start_row;
212
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✗ Branch 3 not taken.
40 if (local_idx >= 0 && local_idx < local_rows) {
213 double max_val = 0.0;
214 int max_col = step;
215
2/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 119 times.
✓ Branch 3 taken 40 times.
159 for (int col = step; col < rows; col++) {
216
2/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 47 times.
✓ Branch 3 taken 72 times.
119 double val = std::abs(local_matrix[local_idx][col]);
217
2/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 47 times.
✓ Branch 3 taken 72 times.
119 if (val > std::abs(max_val)) {
218 max_val = local_matrix[local_idx][col];
219 max_col = col;
220 }
221 }
222 40 pivot_value = max_val;
223 40 pivot_col = max_col;
224 40 pivot_row_local_idx = local_idx;
225 }
226 }
227 }
228 80 void KosolapovVGaussMethodTapeHorSchemeMPI::RowSub(int local_rows, int step, int rows,
229 std::vector<std::vector<double>> &local_matrix,
230 std::vector<double> &local_rsd,
231 const std::vector<int> &local_row_indices,
232 const std::vector<double> &pivot_row, double pivot_rhs) {
233
2/2
✓ Branch 0 taken 198 times.
✓ Branch 1 taken 80 times.
278 for (int i = 0; i < local_rows; i++) {
234
2/2
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 119 times.
198 int global_row = local_row_indices[i];
235
2/2
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 119 times.
198 if (global_row > step) {
236
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 22 times.
79 double coef = local_matrix[i][step];
237
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 22 times.
79 if (std::abs(coef) > 1e-12) {
238
2/2
✓ Branch 0 taken 240 times.
✓ Branch 1 taken 57 times.
297 for (int j = step; j < rows; ++j) {
239 240 local_matrix[i][j] -= coef * pivot_row[j - step];
240 }
241 57 local_rsd[i] -= coef * pivot_rhs;
242 }
243 }
244 }
245 80 }
246 80 void KosolapovVGaussMethodTapeHorSchemeMPI::SwapColumns(int pivot_col, int step, int local_rows,
247 std::vector<std::vector<double>> &local_matrix,
248 std::vector<int> &col_order) {
249
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 68 times.
80 if (pivot_col != step) {
250
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 12 times.
35 for (int i = 0; i < local_rows; i++) {
251 23 std::swap(local_matrix[i][step], local_matrix[i][pivot_col]);
252 }
253 12 std::swap(col_order[step], col_order[pivot_col]);
254 }
255 80 }
256 void KosolapovVGaussMethodTapeHorSchemeMPI::NormalizePivot(int rank, int owner_process, int pivot_row_local_idx,
257 int step, int rows, double pivot_value,
258 std::vector<std::vector<double>> &local_matrix,
259 std::vector<double> &local_rsd) {
260
2/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 40 times.
80 if (rank == owner_process && pivot_row_local_idx >= 0) {
261
2/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 119 times.
✓ Branch 3 taken 40 times.
159 for (int j = step; j < rows; j++) {
262 119 local_matrix[pivot_row_local_idx][j] /= pivot_value;
263 }
264 40 local_rsd[pivot_row_local_idx] /= pivot_value;
265 }
266 }
267 void KosolapovVGaussMethodTapeHorSchemeMPI::PriparePivot(int rank, int owner_process, int pivot_row_local_idx, int step,
268 int rows, std::vector<double> &pivot_row, double &pivot_rhs,
269 const std::vector<std::vector<double>> &local_matrix,
270 const std::vector<double> &local_rsd) {
271
2/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 40 times.
80 if (rank == owner_process && pivot_row_local_idx >= 0) {
272
2/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 119 times.
✓ Branch 3 taken 40 times.
159 for (int j = step; j < rows; j++) {
273 119 pivot_row[j - step] = local_matrix[pivot_row_local_idx][j];
274 }
275 40 pivot_rhs = local_rsd[pivot_row_local_idx];
276 }
277 }
278 } // namespace kosolapov_v_gauss_method_tape_hor_scheme
279