GCC Code Coverage Report


Directory: ./
File: tasks/kiselev_i_gauss_method_horizontal_tape_scheme/mpi/src/ops_mpi.cpp
Date: 2026-01-10 02:40:41
Exec Total Coverage
Lines: 120 122 98.4%
Functions: 10 10 100.0%
Branches: 77 124 62.1%

Line Branch Exec Source
1 #include "kiselev_i_gauss_method_horizontal_tape_scheme/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <algorithm>
6 #include <cmath>
7 #include <cstddef>
8 #include <tuple>
9 #include <utility>
10 #include <vector>
11
12 #include "kiselev_i_gauss_method_horizontal_tape_scheme/common/include/common.hpp"
13
14 namespace kiselev_i_gauss_method_horizontal_tape_scheme {
15
16
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 KiselevITestTaskMPI::KiselevITestTaskMPI(const InType &in) {
17 SetTypeOfTask(GetStaticTypeOfTask());
18 auto &buf = GetInput();
19 InType tmp(in);
20 buf.swap(tmp);
21 GetOutput().clear();
22 28 }
23
24
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 bool KiselevITestTaskMPI::ValidationImpl() {
25 const auto &a_vector = std::get<0>(GetInput());
26 const auto &b_vector = std::get<1>(GetInput());
27
3/6
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 28 times.
28 return !a_vector.empty() && a_vector.size() == b_vector.size() && GetOutput().empty();
28 }
29
30
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 bool KiselevITestTaskMPI::PreProcessingImpl() {
31 GetOutput().clear();
32 28 return true;
33 }
34
35 namespace {
36
37 28 void MakePartition(int proc, int num, std::vector<int> &cnt, std::vector<int> &disp) {
38 28 cnt.assign(proc, 0);
39 28 disp.assign(proc, 0);
40
41 28 const int q_coef = num / proc;
42 28 const int r_coef = num % proc;
43 int pos = 0;
44
45
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 28 times.
84 for (int index = 0; index < proc; ++index) {
46
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 18 times.
94 cnt[index] = q_coef + (index < r_coef ? 1 : 0);
47 56 disp[index] = pos;
48 56 pos += cnt[index];
49 }
50 28 }
51
52 int OwnerOf(int row, const std::vector<int> &cnt, const std::vector<int> &disp) {
53
2/4
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 144 times.
✗ Branch 3 not taken.
288 for (std::size_t proc = 0; proc < cnt.size(); ++proc) {
54
6/8
✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 102 times.
✓ Branch 3 taken 42 times.
✓ Branch 4 taken 144 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 102 times.
✓ Branch 7 taken 42 times.
288 if (row >= disp[proc] && row < disp[proc] + cnt[proc]) {
55 204 return static_cast<int>(proc);
56 }
57 }
58 return 0;
59 }
60
61 102 bool BuildPivotRow(int k_index, int band, int w_coef, int rank, int owner, int row0,
62 const std::vector<double> &a_vector, const std::vector<double> &b_vector, std::vector<double> &pivot,
63 double &rhs_pivot) {
64
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 51 times.
102 if (rank != owner) {
65 return true;
66 }
67
68 51 const int local_k = k_index - row0;
69
1/2
✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
51 const auto row_offset = static_cast<std::size_t>(local_k) * static_cast<std::size_t>(w_coef);
70 const double *row = &a_vector[row_offset];
71
72 51 const double diag = row[band];
73
1/2
✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
51 if (diag == 0.0) {
74 return false;
75 }
76
77 51 const int right = static_cast<int>(pivot.size()) - 1 + k_index;
78
2/2
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 51 times.
139 for (int j = k_index; j <= right; ++j) {
79 88 pivot[j - k_index] = row[j - (k_index - band)];
80 }
81
82 51 rhs_pivot = b_vector[static_cast<std::size_t>(local_k)];
83 51 return true;
84 }
85
86
1/2
✓ Branch 0 taken 102 times.
✗ Branch 1 not taken.
102 bool ApplyElimination(int k_index, int band, int w_coef, int row0, int local_rows, const std::vector<double> &pivot,
87 double rhs_pivot, std::vector<double> &a_vector, std::vector<double> &b_vector) {
88 102 const double diag = pivot[0];
89
1/2
✓ Branch 0 taken 102 times.
✗ Branch 1 not taken.
102 if (diag == 0.0) {
90 return false;
91 }
92
93 102 const int right = k_index + static_cast<int>(pivot.size()) - 1;
94 102 const int row_begin = std::max(row0, k_index + 1);
95 102 const int row_end = std::min(row0 + local_rows - 1, k_index + band);
96
97
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 102 times.
139 for (int index = row_begin; index <= row_end; ++index) {
98 37 const int local_i = index - row0;
99
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 const auto row_offset = static_cast<std::size_t>(local_i) * static_cast<std::size_t>(w_coef);
100 double *row = &a_vector[row_offset];
101
102 37 const int col = k_index - (index - band);
103
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 if (col < 0 || col >= w_coef) {
104 continue;
105 }
106
107 37 const double multiplier = row[col] / diag;
108 37 row[col] = 0.0;
109
110
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 37 times.
92 for (int j = k_index + 1; j <= right; ++j) {
111 55 const int idx = j - (index - band);
112
1/2
✓ Branch 0 taken 55 times.
✗ Branch 1 not taken.
55 if (idx >= 0 && idx < w_coef) {
113 55 row[idx] -= multiplier * pivot[j - k_index];
114 }
115 }
116
117 37 b_vector[static_cast<std::size_t>(local_i)] -= multiplier * rhs_pivot;
118 }
119
120 return true;
121 }
122
123 28 bool EliminateForward(int num, int band, int w_coef, int rank, int row0, int local_rows, const std::vector<int> &cnt,
124 const std::vector<int> &disp, std::vector<double> &a_vector, std::vector<double> &b_vector) {
125
2/2
✓ Branch 0 taken 102 times.
✓ Branch 1 taken 28 times.
130 for (int k_index = 0; k_index < num; ++k_index) {
126 const int owner = OwnerOf(k_index, cnt, disp);
127 102 const int right = std::min(num - 1, k_index + band);
128 102 const int length = right - k_index + 1;
129
130 102 std::vector<double> pivot(static_cast<std::size_t>(length), 0.0);
131 102 double rhs_pivot = 0.0;
132
133
1/2
✓ Branch 1 taken 102 times.
✗ Branch 2 not taken.
102 if (!BuildPivotRow(k_index, band, w_coef, rank, owner, row0, a_vector, b_vector, pivot, rhs_pivot)) {
134 return false;
135 }
136
137
1/2
✓ Branch 1 taken 102 times.
✗ Branch 2 not taken.
102 MPI_Bcast(pivot.data(), length, MPI_DOUBLE, owner, MPI_COMM_WORLD);
138
1/2
✓ Branch 1 taken 102 times.
✗ Branch 2 not taken.
102 MPI_Bcast(&rhs_pivot, 1, MPI_DOUBLE, owner, MPI_COMM_WORLD);
139
140
1/2
✓ Branch 1 taken 102 times.
✗ Branch 2 not taken.
102 if (!ApplyElimination(k_index, band, w_coef, row0, local_rows, pivot, rhs_pivot, a_vector, b_vector)) {
141 return false;
142 }
143 }
144
145 return true;
146 }
147
148 28 bool EliminateBackward(int num, int band, int w_coef, int rank, int row0, const std::vector<int> &cnt,
149 const std::vector<int> &disp, const std::vector<double> &a_vector,
150 const std::vector<double> &b_vector, std::vector<double> &x_vector) {
151 28 x_vector.assign(num, 0.0);
152
153
2/2
✓ Branch 0 taken 102 times.
✓ Branch 1 taken 28 times.
130 for (int k_index = num - 1; k_index >= 0; --k_index) {
154 const int owner = OwnerOf(k_index, cnt, disp);
155
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 51 times.
102 const int right = std::min(num - 1, k_index + band);
156
157 102 double val = 0.0;
158
159
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 51 times.
102 if (rank == owner) {
160 51 const int local_k = k_index - row0;
161 51 const double *row = &a_vector[static_cast<std::size_t>(local_k) * static_cast<std::size_t>(w_coef)];
162
163 double sum = 0.0;
164
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 51 times.
88 for (int j_index = k_index + 1; j_index <= right; ++j_index) {
165 37 const int idx = j_index - (k_index - band);
166
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 if (idx >= 0 && idx < w_coef) {
167 37 sum += row[idx] * x_vector[j_index];
168 }
169 }
170
171 51 const double diag = row[band];
172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 if (diag == 0.0) {
173 return false;
174 }
175
176 51 val = (b_vector[static_cast<std::size_t>(local_k)] - sum) / diag;
177 }
178
179 102 MPI_Bcast(&val, 1, MPI_DOUBLE, owner, MPI_COMM_WORLD);
180 102 x_vector[k_index] = val;
181 }
182
183 return true;
184 }
185
186 } // namespace
187
188 28 bool KiselevITestTaskMPI::RunImpl() {
189 const auto &[a_in, b_in, band_in] = GetInput();
190
191 28 int rank = 0;
192 28 int size = 1;
193 28 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
194 28 MPI_Comm_size(MPI_COMM_WORLD, &size);
195
196 28 int num = 0;
197 28 int band = 0;
198
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
28 if (rank == 0) {
199 14 num = static_cast<int>(a_in.size());
200 14 band = static_cast<int>(band_in);
201 }
202
203 28 MPI_Bcast(&num, 1, MPI_INT, 0, MPI_COMM_WORLD);
204 28 MPI_Bcast(&band, 1, MPI_INT, 0, MPI_COMM_WORLD);
205
206 28 const int w_coef = (2 * band) + 1;
207
208 28 std::vector<int> cnt;
209 28 std::vector<int> disp;
210
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 MakePartition(size, num, cnt, disp);
211
212
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 const int local_rows = cnt[rank];
213 28 const int row0 = disp[rank];
214
215
1/4
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
28 std::vector<double> a_loc(static_cast<std::size_t>(local_rows) * static_cast<std::size_t>(w_coef), 0.0);
216
1/4
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
28 std::vector<double> b_loc(static_cast<std::size_t>(local_rows), 0.0);
217
218
1/4
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
28 std::vector<int> cnt_a(size);
219
1/4
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
28 std::vector<int> disp_a(size);
220
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 28 times.
84 for (int index = 0; index < size; ++index) {
221 56 cnt_a[index] = cnt[index] * w_coef;
222 56 disp_a[index] = disp[index] * w_coef;
223 }
224
225 28 std::vector<double> send_a;
226 28 std::vector<double> send_b;
227
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
28 if (rank == 0) {
228
1/4
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
14 send_a.assign(static_cast<std::size_t>(num) * static_cast<std::size_t>(w_coef), 0.0);
229
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 send_b = b_in;
230
231
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 14 times.
65 for (int index = 0; index < num; ++index) {
232
2/2
✓ Branch 0 taken 125 times.
✓ Branch 1 taken 51 times.
176 for (int j_index = std::max(0, index - band); j_index <= std::min(num - 1, index + band); ++j_index) {
233 125 const auto row_index = static_cast<std::size_t>(index);
234 125 const auto col_index = static_cast<std::size_t>(j_index);
235 125 const auto band_offset = static_cast<std::size_t>(j_index - (index - band));
236 125 const auto linear_index = (row_index * static_cast<std::size_t>(w_coef)) + band_offset;
237
238 125 send_a[linear_index] = a_in[row_index][col_index];
239 }
240 }
241 }
242
243
3/4
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
✓ Branch 3 taken 28 times.
✗ Branch 4 not taken.
42 MPI_Scatterv(rank == 0 ? send_a.data() : nullptr, cnt_a.data(), disp_a.data(), MPI_DOUBLE, a_loc.data(), cnt_a[rank],
244 MPI_DOUBLE, 0, MPI_COMM_WORLD);
245
246
3/4
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
✓ Branch 3 taken 28 times.
✗ Branch 4 not taken.
42 MPI_Scatterv(rank == 0 ? send_b.data() : nullptr, cnt.data(), disp.data(), MPI_DOUBLE, b_loc.data(), local_rows,
247 MPI_DOUBLE, 0, MPI_COMM_WORLD);
248
249
2/4
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
✗ Branch 4 not taken.
28 if (!EliminateForward(num, band, w_coef, rank, row0, local_rows, cnt, disp, a_loc, b_loc)) {
250 return false;
251 }
252
253 28 std::vector<double> x_vector;
254
2/4
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
✗ Branch 4 not taken.
28 if (!EliminateBackward(num, band, w_coef, rank, row0, cnt, disp, a_loc, b_loc, x_vector)) {
255 return false;
256 }
257
258 GetOutput().swap(x_vector);
259 28 return true;
260 }
261
262 28 bool KiselevITestTaskMPI::PostProcessingImpl() {
263 28 return !GetOutput().empty();
264 }
265
266 } // namespace kiselev_i_gauss_method_horizontal_tape_scheme
267