GCC Code Coverage Report


Directory: ./
File: tasks/shilin_n_gauss_band_horizontal_scheme/mpi/src/ops_mpi.cpp
Date: 2026-01-27 01:59:34
Exec Total Coverage
Lines: 101 102 99.0%
Functions: 10 11 90.9%
Branches: 79 118 66.9%

Line Branch Exec Source
1 #include "shilin_n_gauss_band_horizontal_scheme/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <cmath>
6 #include <cstddef>
7 #include <vector>
8
9 #include "shilin_n_gauss_band_horizontal_scheme/common/include/common.hpp"
10
11 namespace shilin_n_gauss_band_horizontal_scheme {
12
13
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 ShilinNGaussBandHorizontalSchemeMPI::ShilinNGaussBandHorizontalSchemeMPI(const InType &in) {
14 SetTypeOfTask(GetStaticTypeOfTask());
15 12 int rank = 0;
16
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
17
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (rank == 0) {
18 InType &input_ref = GetInput();
19 input_ref.clear();
20
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 input_ref.reserve(in.size());
21
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 6 times.
42 for (const auto &row : in) {
22
1/2
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
36 input_ref.push_back(row);
23 }
24 }
25 12 GetOutput() = std::vector<double>();
26 12 }
27
28 12 bool ShilinNGaussBandHorizontalSchemeMPI::ValidationImpl() {
29 12 int rank = 0;
30 12 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
31
32 12 int validation_result = 1;
33
34
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (rank == 0) {
35 const InType &input = GetInput();
36 6 validation_result = ValidateInput(input);
37 }
38
39 12 MPI_Bcast(&validation_result, 1, MPI_INT, 0, MPI_COMM_WORLD);
40
41 12 return validation_result != 0;
42 }
43
44
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 int ShilinNGaussBandHorizontalSchemeMPI::ValidateInput(const InType &input) {
45
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (input.empty()) {
46 return 0;
47 }
48
49 size_t n = input.size();
50
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (n == 0) {
51 return 0;
52 }
53
54 size_t cols = input[0].size();
55
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (cols < n + 1) {
56 return 0;
57 }
58
59
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 6 times.
36 for (size_t i = 1; i < n; ++i) {
60
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (input[i].size() != cols) {
61 return 0;
62 }
63 }
64
65 return 1;
66 }
67
68 12 bool ShilinNGaussBandHorizontalSchemeMPI::PreProcessingImpl() {
69 12 GetOutput() = std::vector<double>();
70 12 return true;
71 }
72
73 12 bool ShilinNGaussBandHorizontalSchemeMPI::RunImpl() {
74 12 int rank = 0;
75 12 int size = 0;
76 12 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
77 12 MPI_Comm_size(MPI_COMM_WORLD, &size);
78
79 12 InType augmented_matrix;
80 size_t n = 0;
81 size_t cols = 0;
82
83
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (rank == 0) {
84
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 augmented_matrix = GetInput();
85 n = augmented_matrix.size();
86
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 cols = (n > 0) ? augmented_matrix[0].size() : 0;
87 }
88
89 12 int n_int = static_cast<int>(n);
90 12 int cols_int = static_cast<int>(cols);
91
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Bcast(&n_int, 1, MPI_INT, 0, MPI_COMM_WORLD);
92
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Bcast(&cols_int, 1, MPI_INT, 0, MPI_COMM_WORLD);
93 12 n = static_cast<size_t>(n_int);
94 12 cols = static_cast<size_t>(cols_int);
95
96
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 if (n == 0 || cols < n + 1) {
97 return false;
98 }
99
100 12 InType local_matrix;
101
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 std::vector<int> global_to_local(n, -1);
102
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 DistributeRows(augmented_matrix, n, cols, rank, size, local_matrix, global_to_local);
103
104
2/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
12 if (!ForwardEliminationMPI(local_matrix, global_to_local, n, cols, rank, size)) {
105 return false;
106 }
107
108
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 std::vector<double> x = BackSubstitutionMPI(local_matrix, global_to_local, n, cols, rank, size);
109
110
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 GetOutput() = x;
111
112 return true;
113 12 }
114
115 12 void ShilinNGaussBandHorizontalSchemeMPI::DistributeRows(const InType &augmented_matrix, size_t n, size_t cols,
116 int rank, int size, InType &local_matrix,
117 std::vector<int> &global_to_local) {
118 // распределение строк по round-robin: строка i -> процесс i % size
119 int local_rows = 0;
120
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 12 times.
84 for (size_t i = 0; i < n; ++i) {
121
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 36 times.
72 if (static_cast<int>(i) % size == rank) {
122 36 local_rows++;
123 }
124 }
125
126
1/2
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 local_matrix = InType(local_rows, std::vector<double>(cols));
127 // маппинг глобальных индексов строк на локальные индексы
128 int local_idx = 0;
129
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 12 times.
84 for (size_t i = 0; i < n; ++i) {
130
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 36 times.
72 if (static_cast<int>(i) % size == rank) {
131 36 global_to_local[i] = local_idx;
132
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 17 times.
36 if (rank == 0) {
133 19 local_matrix[local_idx] = augmented_matrix[i];
134 } else {
135 17 MPI_Recv(local_matrix[local_idx].data(), static_cast<int>(cols), MPI_DOUBLE, 0, static_cast<int>(i),
136 MPI_COMM_WORLD, MPI_STATUS_IGNORE);
137 }
138 36 local_idx++;
139
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 17 times.
36 } else if (rank == 0) {
140 17 MPI_Send(augmented_matrix[i].data(), static_cast<int>(cols), MPI_DOUBLE, static_cast<int>(i) % size,
141 static_cast<int>(i), MPI_COMM_WORLD);
142 }
143 }
144 12 }
145
146 12 bool ShilinNGaussBandHorizontalSchemeMPI::ForwardEliminationMPI(InType &local_matrix,
147 const std::vector<int> &global_to_local, size_t n,
148 size_t cols, int rank, int size) {
149
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 12 times.
84 for (size_t k = 0; k < n; ++k) {
150 // определение процесса-владельца ведущей строки
151 72 int owner_process = static_cast<int>(k) % size;
152
153 72 std::vector<double> pivot_row(cols);
154
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 36 times.
72 if (rank == owner_process) {
155 36 int local_k = global_to_local[k];
156
2/4
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
36 if (local_k >= 0 && static_cast<size_t>(local_k) < local_matrix.size()) {
157
1/2
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
36 pivot_row = local_matrix[static_cast<size_t>(local_k)];
158 }
159 }
160
161 // рассылка ведущей строки всем процессам для исключения
162
1/2
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
72 MPI_Bcast(pivot_row.data(), static_cast<int>(cols), MPI_DOUBLE, owner_process, MPI_COMM_WORLD);
163
164
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if (std::abs(pivot_row[k]) < 1e-10) {
165 return false;
166 }
167
168 72 EliminateColumnMPI(local_matrix, global_to_local, k, n, cols, pivot_row);
169 }
170 return true;
171 }
172
173 72 void ShilinNGaussBandHorizontalSchemeMPI::EliminateColumnMPI(InType &local_matrix,
174 const std::vector<int> &global_to_local, size_t k,
175 size_t n, size_t cols,
176 const std::vector<double> &pivot_row) {
177 // исключение элементов в локальных строках
178
2/2
✓ Branch 0 taken 250 times.
✓ Branch 1 taken 72 times.
322 for (size_t i = 0; i < local_matrix.size(); ++i) {
179 size_t global_i = GetGlobalIndex(global_to_local, i, n);
180
181
4/4
✓ Branch 0 taken 107 times.
✓ Branch 1 taken 143 times.
✓ Branch 2 taken 63 times.
✓ Branch 3 taken 44 times.
250 if (global_i > k && std::abs(local_matrix[i][k]) > 1e-10) {
182 63 double factor = local_matrix[i][k] / pivot_row[k];
183
2/2
✓ Branch 0 taken 394 times.
✓ Branch 1 taken 63 times.
457 for (size_t j = k; j < cols; ++j) {
184 394 local_matrix[i][j] -= factor * pivot_row[j];
185 }
186 }
187 }
188 72 }
189
190 size_t ShilinNGaussBandHorizontalSchemeMPI::GetGlobalIndex(const std::vector<int> &global_to_local, size_t local_idx,
191 size_t n) {
192 // восстановление глобального индекса из локального
193 250 const int local_idx_int = static_cast<int>(local_idx);
194
1/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 1097 times.
✗ Branch 3 not taken.
1097 for (size_t gi = 0; gi < n; ++gi) {
195
4/8
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 613 times.
✓ Branch 5 taken 484 times.
✓ Branch 6 taken 363 times.
✓ Branch 7 taken 250 times.
1097 if (global_to_local[gi] >= 0 && global_to_local[gi] == local_idx_int) {
196 return gi;
197 }
198 }
199 return 0;
200 }
201
202 12 std::vector<double> ShilinNGaussBandHorizontalSchemeMPI::BackSubstitutionMPI(const InType &local_matrix,
203 const std::vector<int> &global_to_local,
204 size_t n, size_t cols, int rank,
205 int size) {
206 // обратный ход с синхронизацией между процессами
207 12 std::vector<double> x(n, 0.0);
208
209
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 12 times.
84 for (int i = static_cast<int>(n) - 1; i >= 0; --i) {
210 double sum = 0.0;
211 72 int owner_process = i % size;
212
213
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 36 times.
72 if (rank == owner_process) {
214
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
36 int local_i = global_to_local[static_cast<size_t>(i)];
215
2/4
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
36 if (local_i >= 0 && static_cast<size_t>(local_i) < local_matrix.size()) {
216
2/2
✓ Branch 0 taken 107 times.
✓ Branch 1 taken 36 times.
143 for (size_t j = static_cast<size_t>(i) + 1; j < n; ++j) {
217 107 sum += local_matrix[static_cast<size_t>(local_i)][j] * x[j];
218 }
219 36 x[static_cast<size_t>(i)] = (local_matrix[static_cast<size_t>(local_i)][cols - 1] - sum) /
220 local_matrix[static_cast<size_t>(local_i)][static_cast<size_t>(i)];
221 }
222 }
223
224 // рассылка вычисленного значения для использования в следующих итерациях
225
1/2
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
72 MPI_Bcast(&x[static_cast<size_t>(i)], 1, MPI_DOUBLE, owner_process, MPI_COMM_WORLD);
226 }
227
228 12 return x;
229 }
230
231 12 bool ShilinNGaussBandHorizontalSchemeMPI::PostProcessingImpl() {
232 12 int rank = 0;
233 12 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
234
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
12 return (rank == 0) ? !GetOutput().empty() : true;
235 }
236
237 } // namespace shilin_n_gauss_band_horizontal_scheme
238