GCC Code Coverage Report


Directory: ./
File: tasks/krykov_e_simple_iterations/mpi/src/ops_mpi.cpp
Date: 2026-01-10 02:40:41
Exec Total Coverage
Lines: 80 80 100.0%
Functions: 8 8 100.0%
Branches: 64 118 54.2%

Line Branch Exec Source
1 #include "krykov_e_simple_iterations/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <cctype>
6 #include <cmath>
7 #include <cstddef>
8 #include <ranges>
9 #include <utility>
10 #include <vector>
11
12 #include "krykov_e_simple_iterations/common/include/common.hpp"
13
14 namespace krykov_e_simple_iterations {
15 namespace {
16
17 constexpr double kEps = 1e-5;
18 constexpr int kMaxIter = 10000;
19
20 92 void CalculateLocalXNew(int start, int count, size_t n, const std::vector<double> &local_a,
21 const std::vector<double> &local_b, const std::vector<double> &x,
22 std::vector<double> &local_x_new) {
23
2/2
✓ Branch 0 taken 123 times.
✓ Branch 1 taken 92 times.
215 for (int i = 0; i < count; ++i) {
24 123 int global_i = start + i;
25 double sum = 0.0;
26
2/2
✓ Branch 0 taken 367 times.
✓ Branch 1 taken 123 times.
490 for (size_t j = 0; j < n; ++j) {
27 if (std::cmp_not_equal(j, global_i)) {
28 244 sum += local_a[(i * n) + j] * x[j];
29 }
30 }
31 123 local_x_new[i] = (local_b[i] - sum) / local_a[(i * n) + global_i];
32 }
33 92 }
34
35 double CalculateLocalNorm(int start, int count, const std::vector<double> &x_new, const std::vector<double> &x) {
36 double local_norm = 0.0;
37
2/2
✓ Branch 0 taken 123 times.
✓ Branch 1 taken 92 times.
215 for (int i = 0; i < count; ++i) {
38 123 int gi = start + i;
39 123 double diff = x_new[gi] - x[gi];
40 123 local_norm += diff * diff;
41 }
42 return local_norm;
43 }
44
45
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 void CalculateChunkSizesAndDispls(int size, int n, std::vector<int> &chunk_sizes, std::vector<int> &displs) {
46
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 if (displs.empty()) {
47 return;
48 }
49 20 int base = n / size;
50 20 int rem = n % size;
51
52 20 displs[0] = 0;
53
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 20 times.
60 for (int i = 0; i < size; ++i) {
54
4/4
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 20 times.
72 chunk_sizes[i] = base + (i < rem ? 1 : 0);
55
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 20 times.
40 if (i > 0) {
56 20 displs[i] = displs[i - 1] + chunk_sizes[i - 1];
57 }
58 }
59 }
60
61
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 void CalculateMatrixChunkSizesAndDispls(int size, int n, std::vector<int> &matrix_chunk_sizes,
62 std::vector<int> &matrix_displs) {
63
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (matrix_displs.empty()) {
64 return;
65 }
66 10 int base = n / size;
67 10 int rem = n % size;
68
69 10 matrix_displs[0] = 0;
70
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
30 for (int i = 0; i < size; ++i) {
71
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 int rows = base + (i < rem ? 1 : 0);
72
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 matrix_chunk_sizes[i] = rows * n;
73
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (i > 0) {
74 10 matrix_displs[i] = matrix_displs[i - 1] + matrix_chunk_sizes[i - 1];
75 }
76 }
77 }
78
79 } // namespace
80
81
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 KrykovESimpleIterationsMPI::KrykovESimpleIterationsMPI(const InType &in) {
82 SetTypeOfTask(GetStaticTypeOfTask());
83 GetInput() = in;
84 10 }
85
86 10 bool KrykovESimpleIterationsMPI::ValidationImpl() {
87 const auto &[n, a, b] = GetInput();
88
3/6
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 10 times.
10 return n > 0 && a.size() == n * n && b.size() == n;
89 }
90
91 10 bool KrykovESimpleIterationsMPI::PreProcessingImpl() {
92 10 return true;
93 }
94
95 10 bool KrykovESimpleIterationsMPI::RunImpl() {
96 10 int size = 0;
97 10 int rank = 0;
98 10 MPI_Comm_size(MPI_COMM_WORLD, &size);
99 10 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
100
101 10 size_t n = 0;
102 10 std::vector<double> a;
103 10 std::vector<double> b;
104
105
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 if (rank == 0) {
106 const auto &input = GetInput();
107
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 n = std::get<0>(input);
108
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 a = std::get<1>(input);
109
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 b = std::get<2>(input);
110 }
111
112
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 MPI_Bcast(&n, 1, MPI_UNSIGNED_LONG, 0, MPI_COMM_WORLD);
113
114
1/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
10 std::vector<int> chunk_sizes(size);
115
1/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
10 std::vector<int> displs(size);
116 10 CalculateChunkSizesAndDispls(size, static_cast<int>(n), chunk_sizes, displs);
117
118
1/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
10 std::vector<int> matrix_chunk_sizes(size);
119
1/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
10 std::vector<int> matrix_displs(size);
120 10 CalculateMatrixChunkSizesAndDispls(size, static_cast<int>(n), matrix_chunk_sizes, matrix_displs);
121
122
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 int local_rows = chunk_sizes[rank];
123 10 int local_matrix_size = matrix_chunk_sizes[rank];
124
125
1/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
10 std::vector<double> local_a(local_matrix_size);
126
3/6
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
10 std::vector<double> local_b(local_rows);
127
128
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
15 MPI_Scatterv(rank == 0 ? a.data() : nullptr, matrix_chunk_sizes.data(), matrix_displs.data(), MPI_DOUBLE,
129 local_a.data(), local_matrix_size, MPI_DOUBLE, 0, MPI_COMM_WORLD);
130
131
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
15 MPI_Scatterv(rank == 0 ? b.data() : nullptr, chunk_sizes.data(), displs.data(), MPI_DOUBLE, local_b.data(),
132 local_rows, MPI_DOUBLE, 0, MPI_COMM_WORLD);
133
134
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 int start = displs[rank];
135 int count = local_rows;
136
137
1/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
10 std::vector<double> x(n, 0.0);
138
1/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
10 std::vector<double> x_new(n, 0.0);
139
1/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
10 std::vector<double> local_x_new(count, 0.0);
140
141
1/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
10 std::vector<int> recv_counts(size);
142
1/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
10 std::vector<int> allgather_displs(size);
143 10 CalculateChunkSizesAndDispls(size, static_cast<int>(n), recv_counts, allgather_displs);
144
145
1/2
✓ Branch 0 taken 92 times.
✗ Branch 1 not taken.
92 for (int iter = 0; iter < kMaxIter; ++iter) {
146 92 CalculateLocalXNew(start, count, n, local_a, local_b, x, local_x_new);
147
148
1/2
✓ Branch 1 taken 92 times.
✗ Branch 2 not taken.
92 MPI_Allgatherv(local_x_new.data(), count, MPI_DOUBLE, x_new.data(), recv_counts.data(), allgather_displs.data(),
149 MPI_DOUBLE, MPI_COMM_WORLD);
150
151 92 double local_norm = CalculateLocalNorm(start, count, x_new, x);
152 92 double global_norm = 0.0;
153
1/2
✓ Branch 1 taken 92 times.
✗ Branch 2 not taken.
92 MPI_Allreduce(&local_norm, &global_norm, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
154
155
1/2
✓ Branch 1 taken 92 times.
✗ Branch 2 not taken.
92 x = x_new;
156
157
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 10 times.
92 if (std::sqrt(global_norm) < kEps) {
158 break;
159 }
160 }
161
162
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 GetOutput() = x;
163
164 10 return true;
165 }
166
167 10 bool KrykovESimpleIterationsMPI::PostProcessingImpl() {
168 10 return true;
169 }
170
171 } // namespace krykov_e_simple_iterations
172