GCC Code Coverage Report


Directory: ./
File: tasks/gonozov_l_simple_iteration_method/mpi/src/ops_mpi.cpp
Date: 2026-01-10 02:40:41
Exec Total Coverage
Lines: 84 84 100.0%
Functions: 6 6 100.0%
Branches: 72 128 56.2%

Line Branch Exec Source
1 #include "gonozov_l_simple_iteration_method/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <cmath>
6 #include <cstddef>
7 #include <vector>
8
9 #include "gonozov_l_simple_iteration_method/common/include/common.hpp"
10 // #include "util/include/util.hpp"
11
12 namespace gonozov_l_simple_iteration_method {
13
14
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 GonozovLSimpleIterationMethodMPI::GonozovLSimpleIterationMethodMPI(const InType &in)
15
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 : number_unknowns_(static_cast<int>(std::get<0>(in))) {
16 SetTypeOfTask(GetStaticTypeOfTask());
17 GetInput() = in;
18 6 GetOutput() = OutType();
19 6 }
20
21 6 bool GonozovLSimpleIterationMethodMPI::ValidationImpl() {
22 // д.б. |a11| > |a12|+|a13|, |a22| > |a21|+|a23|, |a33| > |a31|+|a32|
23
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 6 times.
30 for (int i = 0; i < number_unknowns_; i++) {
24 double sum = 0.0;
25
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 24 times.
124 for (int j = 0; j < number_unknowns_; j++) {
26
2/2
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 24 times.
100 if (j != i) {
27 76 sum += std::get<1>(GetInput())[(i * number_unknowns_) + j];
28 }
29 }
30
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (std::get<1>(GetInput())[(i * number_unknowns_) + i] < sum) {
31 return false;
32 }
33 }
34
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
6 return (static_cast<int>(std::get<0>(GetInput())) > 0) && (static_cast<int>(std::get<1>(GetInput()).size()) > 0) &&
35
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 (static_cast<int>(std::get<2>(GetInput()).size()) > 0);
36 }
37
38 6 bool GonozovLSimpleIterationMethodMPI::PreProcessingImpl() {
39 6 return true;
40 }
41 namespace {
42 328 void CalculatingNewApproximations(int my_first_row, std::vector<double> &local_matrix,
43 std::vector<double> &previous_approximations, std::vector<double> &local_current,
44 int local_size, int number_unknowns, std::vector<double> &local_b) {
45
2/2
✓ Branch 0 taken 643 times.
✓ Branch 1 taken 328 times.
971 for (int i = 0; i < local_size; i++) {
46 643 int global_row = my_first_row + i;
47 double sum = 0.0;
48
49 // Суммируем все недиагональные элементы
50
2/2
✓ Branch 0 taken 2621 times.
✓ Branch 1 taken 643 times.
3264 for (int j = 0; j < number_unknowns; j++) {
51
2/2
✓ Branch 0 taken 1978 times.
✓ Branch 1 taken 643 times.
2621 if (j != global_row) {
52 1978 sum += local_matrix[(i * number_unknowns) + j] * previous_approximations[j];
53 }
54 }
55
56 643 local_current[i] = (local_b[i] - sum) / local_matrix[(i * number_unknowns) + global_row];
57 }
58 328 }
59
60 int CountingMyFirstRow(int proc_rank, int number_processed, int remainder) {
61 int my_first_row = 0;
62
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 6 times.
9 for (int pl = 0; pl < proc_rank; pl++) {
63
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
4 my_first_row += number_processed + (pl < remainder ? 1 : 0);
64 }
65 return my_first_row;
66 }
67
68 int CountingLocalSize(int number_processed, int proc_rank, int remainder) {
69 6 return number_processed + (proc_rank < remainder ? 1 : 0);
70 }
71
72 int ConvergenceCheck(int my_first_row, std::vector<double> current_approximations,
73 std::vector<double> previous_approximations, int local_size) {
74 int local_converged = 0;
75
2/2
✓ Branch 0 taken 643 times.
✓ Branch 1 taken 328 times.
971 for (int i = 0; i < local_size; i++) {
76 643 int global_row = my_first_row + i;
77
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 575 times.
643 double diff = abs(current_approximations[global_row] - previous_approximations[global_row]);
78 double norm = abs(current_approximations[global_row]);
79
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 575 times.
643 if (diff < 0.00001 * (norm + 1e-10)) {
80 68 local_converged++;
81 }
82 }
83 return local_converged;
84 }
85 } // namespace
86
87 6 bool GonozovLSimpleIterationMethodMPI::RunImpl() {
88 int max_number_iteration = 10000;
89 6 int proc_num = 0;
90 6 int proc_rank = 0;
91 6 MPI_Comm_size(MPI_COMM_WORLD, &proc_num);
92 6 MPI_Comm_rank(MPI_COMM_WORLD, &proc_rank);
93
94 6 std::vector<double> matrix;
95 6 std::vector<double> b;
96
97
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (proc_rank == 0) {
98
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 matrix = std::get<1>(GetInput());
99
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 b = std::get<2>(GetInput());
100 3 number_unknowns_ = std::get<0>(GetInput());
101 }
102
103 // Распределение строк по процессам
104 6 int number_processed = number_unknowns_ / proc_num;
105 6 int remainder = number_unknowns_ % proc_num;
106
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 int local_size = CountingLocalSize(number_processed, proc_rank, remainder);
107
108 // Определяем локально, какие строки обрабатывает какой из процессов
109 int my_first_row = CountingMyFirstRow(proc_rank, number_processed, remainder);
110
111 // Данные для Scatterv
112
1/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6 std::vector<int> sendcounts_for_matrix(proc_num, 0);
113
1/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6 std::vector<int> sendcounts_for_b(proc_num, 0);
114
1/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6 std::vector<int> displs_for_matrix(proc_num, 0);
115
1/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6 std::vector<int> displs_for_b(proc_num, 0);
116
117
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (proc_rank == 0) {
118 int offset_matrix = 0;
119 int offset_b = 0;
120
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
9 for (int pl = 0; pl < proc_num; pl++) {
121
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 int p_size = number_processed + (pl < remainder ? 1 : 0);
122 6 sendcounts_for_matrix[pl] = p_size * number_unknowns_;
123 6 sendcounts_for_b[pl] = p_size;
124
125 6 displs_for_matrix[pl] = offset_matrix;
126 6 displs_for_b[pl] = offset_b;
127
128 6 offset_matrix += sendcounts_for_matrix[pl];
129 6 offset_b += sendcounts_for_b[pl];
130 }
131 }
132
133 // Информация требующаяся для работы MPI_Allgatherv
134
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 MPI_Bcast(sendcounts_for_b.data(), proc_num, MPI_INT, 0, MPI_COMM_WORLD);
135
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 MPI_Bcast(displs_for_b.data(), proc_num, MPI_INT, 0, MPI_COMM_WORLD);
136
137
1/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6 std::vector<double> local_matrix(static_cast<size_t>(local_size * number_unknowns_));
138
1/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6 std::vector<double> local_b(local_size);
139
140
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 MPI_Scatterv((proc_rank == 0) ? matrix.data() : nullptr, sendcounts_for_matrix.data(), displs_for_matrix.data(),
141
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 MPI_DOUBLE, local_matrix.data(), local_size * number_unknowns_, MPI_DOUBLE, 0, MPI_COMM_WORLD);
142
143
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
9 MPI_Scatterv((proc_rank == 0) ? b.data() : nullptr, sendcounts_for_b.data(), displs_for_b.data(), MPI_DOUBLE,
144 local_b.data(), local_size, MPI_DOUBLE, 0, MPI_COMM_WORLD);
145
146
1/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6 std::vector<double> previous_approximations(number_unknowns_, 0.0);
147
1/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6 std::vector<double> current_approximations(number_unknowns_, 0.0);
148
1/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6 std::vector<double> local_previous(local_size, 0.0);
149
1/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
6 std::vector<double> local_current(local_size, 0.0);
150
151 // Подсчёт нулевого приближени
152
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
18 for (int i = 0; i < local_size; i++) {
153 12 int global_row = my_first_row + i;
154 12 local_previous[i] = local_b[i] / local_matrix[(i * number_unknowns_) + global_row];
155 }
156
157 // Отправка начальных приближений
158
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 MPI_Allgatherv(local_previous.data(), local_size, MPI_DOUBLE, previous_approximations.data(), sendcounts_for_b.data(),
159 displs_for_b.data(), MPI_DOUBLE, MPI_COMM_WORLD);
160
161 // Основной цикл
162
1/2
✓ Branch 0 taken 328 times.
✗ Branch 1 not taken.
328 for (int iter = 0; iter < max_number_iteration; iter++) {
163 // Каждый процесс вычисляет новые приближения для строк, которые у него имеются
164 328 CalculatingNewApproximations(my_first_row, local_matrix, previous_approximations, local_current, local_size,
165 number_unknowns_, local_b);
166
167
1/2
✓ Branch 1 taken 328 times.
✗ Branch 2 not taken.
328 MPI_Allgatherv(local_current.data(), local_size, MPI_DOUBLE, current_approximations.data(), sendcounts_for_b.data(),
168 displs_for_b.data(), MPI_DOUBLE, MPI_COMM_WORLD);
169
170 // Проверка сходимости
171
4/12
✓ Branch 1 taken 328 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 328 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 328 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 328 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
984 int local_converged = ConvergenceCheck(my_first_row, current_approximations, previous_approximations, local_size);
172
173 328 int global_converged = 0;
174
1/2
✓ Branch 1 taken 328 times.
✗ Branch 2 not taken.
328 MPI_Allreduce(&local_converged, &global_converged, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
175
176
2/2
✓ Branch 0 taken 322 times.
✓ Branch 1 taken 6 times.
328 if (global_converged == number_unknowns_) {
177 break;
178 }
179
180 previous_approximations.swap(current_approximations);
181
1/2
✓ Branch 1 taken 322 times.
✗ Branch 2 not taken.
322 local_previous = local_current;
182 }
183
184
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 GetOutput() = current_approximations;
185
186 6 return true;
187 }
188
189 6 bool GonozovLSimpleIterationMethodMPI::PostProcessingImpl() {
190 6 return true;
191 }
192
193 } // namespace gonozov_l_simple_iteration_method
194