GCC Code Coverage Report


Directory: ./
File: tasks/samoylenko_i_simple_iter_method/mpi/src/ops_mpi.cpp
Date: 2026-01-27 01:59:34
Exec Total Coverage
Lines: 77 77 100.0%
Functions: 7 7 100.0%
Branches: 45 68 66.2%

Line Branch Exec Source
1 #include "samoylenko_i_simple_iter_method/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 "samoylenko_i_simple_iter_method/common/include/common.hpp"
11
12 namespace samoylenko_i_simple_iter_method {
13
14 20 SamoylenkoISimpleIterMethodMPI::SamoylenkoISimpleIterMethodMPI(const InType &in) {
15 SetTypeOfTask(GetStaticTypeOfTask());
16 20 GetInput() = in;
17 GetOutput().clear();
18 20 }
19
20 20 bool SamoylenkoISimpleIterMethodMPI::ValidationImpl() {
21 20 int world_rank = 0;
22 20 MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
23
24 20 int valid = 0;
25
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (world_rank == 0) {
26
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
10 valid = (GetInput() > 0 && GetOutput().empty()) ? 1 : 0;
27 }
28
29 20 MPI_Bcast(&valid, 1, MPI_INT, 0, MPI_COMM_WORLD);
30 20 return valid == 1;
31 }
32
33 20 bool SamoylenkoISimpleIterMethodMPI::PreProcessingImpl() {
34 20 int world_rank = 0;
35 20 MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
36
37
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (world_rank == 0) {
38 GetOutput().clear();
39 }
40
41 20 return true;
42 }
43
44 namespace {
45
46 void CalculateDistribution(int n, int world_size, std::vector<int> &row_counts, std::vector<int> &row_displs) {
47 20 int proc_rows = n / world_size;
48 20 int extra_rows = n % world_size;
49 int disp = 0;
50
51
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 20 times.
60 for (int proc = 0; proc < world_size; ++proc) {
52
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 10 times.
70 row_counts[proc] = proc_rows + (proc < extra_rows ? 1 : 0);
53 40 row_displs[proc] = disp;
54 40 disp += row_counts[proc];
55 }
56 }
57
58 20 std::vector<double> BuildLocalMatrix(int n, int local_rows, int local_start) {
59 20 auto size = static_cast<size_t>(n);
60 20 std::vector<double> local_matrix(static_cast<size_t>(local_rows) * size, 0.0);
61
62
2/2
✓ Branch 0 taken 143 times.
✓ Branch 1 taken 20 times.
163 for (int i = 0; i < local_rows; ++i) {
63 143 int global_row = local_start + i;
64
2/2
✓ Branch 0 taken 133 times.
✓ Branch 1 taken 10 times.
143 local_matrix[(static_cast<size_t>(i) * size) + global_row] = 4.0;
65
66
2/2
✓ Branch 0 taken 133 times.
✓ Branch 1 taken 10 times.
143 if (global_row > 0) {
67 133 local_matrix[(static_cast<size_t>(i) * size) + (global_row - 1)] = 1.0;
68 }
69
2/2
✓ Branch 0 taken 133 times.
✓ Branch 1 taken 10 times.
143 if (global_row + 1 < n) {
70 133 local_matrix[(static_cast<size_t>(i) * size) + (global_row + 1)] = 1.0;
71 }
72 }
73
74 20 return local_matrix;
75 }
76
77 20 void PerformIterations(int n, int local_rows, int local_start, const std::vector<double> &local_matrix,
78 const std::vector<double> &local_vector, const std::vector<int> &row_counts,
79 const std::vector<int> &row_displs, std::vector<double> &x) {
80 20 auto size = static_cast<size_t>(n);
81 const double tau = 0.2;
82 const double eps = 1e-7;
83 const int iters = 2000;
84
85 20 std::vector<double> x_old(size);
86
1/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
20 std::vector<double> local_x_new(local_rows);
87
88
1/2
✓ Branch 0 taken 360 times.
✗ Branch 1 not taken.
360 for (int it = 0; it < iters; ++it) {
89
1/2
✓ Branch 1 taken 360 times.
✗ Branch 2 not taken.
360 x_old = x;
90
2/2
✓ Branch 0 taken 2951 times.
✓ Branch 1 taken 360 times.
3311 for (int i = 0; i < local_rows; ++i) {
91 double ax_i = 0.0;
92
2/2
✓ Branch 0 taken 88343 times.
✓ Branch 1 taken 2951 times.
91294 for (size_t j = 0; j < size; ++j) {
93 88343 ax_i += local_matrix[(static_cast<size_t>(i) * size) + j] * x[j];
94 }
95
96 2951 local_x_new[i] = x[local_start + i] - (tau * (ax_i - local_vector[i]));
97 }
98
99
1/2
✓ Branch 1 taken 360 times.
✗ Branch 2 not taken.
360 MPI_Allgatherv(local_x_new.data(), local_rows, MPI_DOUBLE, x.data(), row_counts.data(), row_displs.data(),
100 MPI_DOUBLE, MPI_COMM_WORLD);
101
102 360 double local_max = 0.0;
103
2/2
✓ Branch 0 taken 2951 times.
✓ Branch 1 taken 360 times.
3311 for (int i = 0; i < local_rows; ++i) {
104 2951 local_max = std::max(local_max, std::fabs(x[local_start + i] - x_old[local_start + i]));
105 }
106
107 360 double global_max = 0.0;
108
1/2
✓ Branch 1 taken 360 times.
✗ Branch 2 not taken.
360 MPI_Allreduce(&local_max, &global_max, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
109
110
2/2
✓ Branch 0 taken 340 times.
✓ Branch 1 taken 20 times.
360 if (global_max < eps) {
111 break;
112 }
113 }
114 20 }
115
116 } // namespace
117
118 20 bool SamoylenkoISimpleIterMethodMPI::RunImpl() {
119 20 int world_rank = 0;
120 20 int world_size = 0;
121 20 MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
122 20 MPI_Comm_size(MPI_COMM_WORLD, &world_size);
123
124 20 int n = 0;
125
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (world_rank == 0) {
126 10 n = GetInput();
127 }
128
129 20 MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);
130
131
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 if (n <= 0) {
132 return false;
133 }
134
135 20 std::vector<int> row_counts(world_size);
136
1/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
20 std::vector<int> row_displs(world_size);
137 20 CalculateDistribution(n, world_size, row_counts, row_displs);
138
139
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 int local_rows = row_counts[world_rank];
140 20 int local_start = row_displs[world_rank];
141
142
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 std::vector<double> local_matrix = BuildLocalMatrix(n, local_rows, local_start);
143
1/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
20 std::vector<double> local_vector(local_rows, 1.0);
144
1/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
20 std::vector<double> x(static_cast<size_t>(n), 0.0);
145
146
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 PerformIterations(n, local_rows, local_start, local_matrix, local_vector, row_counts, row_displs, x);
147
148
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (world_rank == 0) {
149
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 GetOutput() = x;
150 }
151
152 return true;
153 }
154
155 20 bool SamoylenkoISimpleIterMethodMPI::PostProcessingImpl() {
156 20 int world_rank = 0;
157 20 MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
158
159
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 if (world_rank == 0) {
160 10 return !GetOutput().empty();
161 }
162
163 return true;
164 }
165
166 } // namespace samoylenko_i_simple_iter_method
167