GCC Code Coverage Report


Directory: ./
File: tasks/shvetsova_k_gausse_vert_strip/mpi/src/ops_mpi.cpp
Date: 2026-01-10 02:40:41
Exec Total Coverage
Lines: 95 103 92.2%
Functions: 9 12 75.0%
Branches: 69 98 70.4%

Line Branch Exec Source
1 #include "shvetsova_k_gausse_vert_strip/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <algorithm>
6 #include <cmath>
7 #include <stdexcept>
8 #include <vector>
9
10 #include "shvetsova_k_gausse_vert_strip/common/include/common.hpp"
11
12 namespace shvetsova_k_gausse_vert_strip {
13
14 // вспомогательные функции
15
16 int ShvetsovaKGaussVertStripMPI::GetOwnerOfColumn(int k, int n, int size) {
17 140 int base = n / size;
18 140 int rem = n % size;
19 140 int border = rem * (base + 1);
20
6/8
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 20 times.
✓ Branch 4 taken 30 times.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
140 return (k < border) ? k / (base + 1) : rem + ((k - border) / base);
21 }
22
23 int ShvetsovaKGaussVertStripMPI::GetColumnStartIndex(int rank, int n, int size) {
24 15 int base = n / size;
25 15 int rem = n % size;
26
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
30 return (rank < rem) ? rank * (base + 1) : (rem * (base + 1)) + ((rank - rem) * base);
27 }
28
29 int ShvetsovaKGaussVertStripMPI::GetColumnEndIndex(int rank, int n, int size) {
30
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
15 return GetColumnStartIndex(rank + 1, n, size);
31 }
32
33 5 int ShvetsovaKGaussVertStripMPI::CalculateRibWidth(const std::vector<std::vector<double>> &matrix, int n) {
34 5 int rib_width = 1;
35
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 5 times.
30 for (int i = 0; i < n; ++i) {
36
2/2
✓ Branch 0 taken 125 times.
✓ Branch 1 taken 25 times.
150 for (int j = 0; j < n; ++j) {
37
4/4
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 60 times.
125 if (i != j && std::abs(matrix[i][j]) > 1e-12) {
38 40 rib_width = std::max(rib_width, std::abs(i - j) + 1);
39 }
40 }
41 }
42
43 5 return rib_width;
44 }
45
46 10 void ShvetsovaKGaussVertStripMPI::ForwardElimination(int n, int rank, int size, int c0, int local_cols,
47 std::vector<std::vector<double>> &a_local,
48 std::vector<double> &b) const {
49
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 10 times.
60 for (int k = 0; k < n; ++k) {
50 int owner = GetOwnerOfColumn(k, n, size);
51 50 double pivot = 0.0;
52
53
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 25 times.
50 if (rank == owner) {
54 25 pivot = a_local[k][k - c0];
55 }
56 50 MPI_Bcast(&pivot, 1, MPI_DOUBLE, owner, MPI_COMM_WORLD);
57
58
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 if (std::abs(pivot) < 1e-12) {
59 // единое поведение для всех рангов
60 throw std::runtime_error("Zero pivot encountered");
61 }
62
63
2/2
✓ Branch 0 taken 125 times.
✓ Branch 1 taken 50 times.
175 for (int j = 0; j < local_cols; ++j) {
64 125 a_local[k][j] /= pivot;
65 }
66 50 b[k] /= pivot;
67
68
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 50 times.
90 for (int i = k + 1; i < std::min(n, k + size_of_rib_); ++i) {
69 40 double factor = 0.0;
70
71
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 20 times.
40 if (rank == owner) {
72 20 factor = a_local[i][k - c0];
73 }
74 40 MPI_Bcast(&factor, 1, MPI_DOUBLE, owner, MPI_COMM_WORLD);
75
76
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 40 times.
140 for (int j = 0; j < local_cols; ++j) {
77 100 a_local[i][j] -= factor * a_local[k][j];
78 }
79 40 b[i] -= factor * b[k];
80 }
81 }
82 10 }
83
84 10 std::vector<double> ShvetsovaKGaussVertStripMPI::BackSubstitution(int n, int rank, int size, int c0,
85 const std::vector<std::vector<double>> &a_local,
86 const std::vector<double> &b) const {
87 10 std::vector<double> x(n, 0.0);
88
89
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 10 times.
60 for (int k = n - 1; k >= 0; --k) {
90 50 double sum = b[k];
91
92
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 50 times.
90 for (int j = k + 1; j < std::min(n, k + size_of_rib_); ++j) {
93 int owner = GetOwnerOfColumn(j, n, size);
94 40 double val = 0.0;
95
96
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 20 times.
40 if (rank == owner) {
97 20 val = a_local[k][j - c0];
98 }
99
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 MPI_Bcast(&val, 1, MPI_DOUBLE, owner, MPI_COMM_WORLD);
100
101 40 sum -= val * x[j];
102 }
103
104 int owner = GetOwnerOfColumn(k, n, size);
105
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 25 times.
50 if (rank == owner) {
106 25 x[k] = sum;
107 }
108
1/2
✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
50 MPI_Bcast(&x[k], 1, MPI_DOUBLE, owner, MPI_COMM_WORLD);
109 }
110
111 10 return x;
112 }
113
114 10 void ShvetsovaKGaussVertStripMPI::ScatterColumns(int n, int rank, int size, int c0, int local_cols,
115 const std::vector<std::vector<double>> &matrix,
116 std::vector<std::vector<double>> &a_local) {
117
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 if (rank == 0) {
118 // копируем свои столбцы
119
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 5 times.
30 for (int i = 0; i < n; ++i) {
120
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 25 times.
100 for (int j = 0; j < local_cols; ++j) {
121 75 a_local[i][j] = matrix[i][c0 + j];
122 }
123 }
124
125 // рассылаем остальным
126
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 for (int rr = 1; rr < size; ++rr) {
127 int rs = GetColumnStartIndex(rr, n, size);
128 int re = GetColumnEndIndex(rr, n, size);
129 5 int cols = re - rs;
130
131
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 5 times.
30 for (int i = 0; i < n; ++i) {
132 25 MPI_Send(&matrix[i][rs], cols, MPI_DOUBLE, rr, 0, MPI_COMM_WORLD);
133 }
134 }
135 } else {
136 // принимаем свои столбцы
137
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 5 times.
30 for (int i = 0; i < n; ++i) {
138 25 MPI_Recv(a_local[i].data(), local_cols, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
139 }
140 }
141 10 }
142
143 // основные функции
144
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 ShvetsovaKGaussVertStripMPI::ShvetsovaKGaussVertStripMPI(const InType &in) {
145 SetTypeOfTask(GetStaticTypeOfTask());
146 GetInput() = in;
147 GetOutput().clear();
148 10 }
149
150 10 bool ShvetsovaKGaussVertStripMPI::ValidationImpl() {
151 10 return true;
152 }
153
154 10 bool ShvetsovaKGaussVertStripMPI::PreProcessingImpl() {
155 input_data_ = GetInput();
156 10 return true;
157 }
158
159 10 bool ShvetsovaKGaussVertStripMPI::RunImpl() {
160 10 int rank = 0;
161 10 int size = 0;
162 10 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
163 10 MPI_Comm_size(MPI_COMM_WORLD, &size);
164
165 10 const auto &matrix = input_data_.first;
166 10 const auto &b_in = input_data_.second;
167
168 10 int n = 0;
169
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 if (rank == 0) {
170 5 n = static_cast<int>(matrix.size());
171 }
172 10 MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);
173
174
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (n == 0) {
175 GetOutput().clear();
176 return true;
177 }
178
179 // вычисление размера ленты
180
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 if (rank == 0) {
181 5 size_of_rib_ = CalculateRibWidth(matrix, n);
182 }
183 10 MPI_Bcast(&size_of_rib_, 1, MPI_INT, 0, MPI_COMM_WORLD);
184
185
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 int c0 = GetColumnStartIndex(rank, n, size);
186 int c1 = GetColumnEndIndex(rank, n, size);
187 10 int local_cols = c1 - c0;
188
189
1/2
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
10 std::vector<std::vector<double>> a_local(n, std::vector<double>(local_cols));
190
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 std::vector<double> b = b_in;
191
192 // разделяем столбцы
193
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 ScatterColumns(n, rank, size, c0, local_cols, matrix, a_local);
194
195
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 MPI_Bcast(b.data(), n, MPI_DOUBLE, 0, MPI_COMM_WORLD);
196
197 // прямой ход
198 try {
199
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 ForwardElimination(n, rank, size, c0, local_cols, a_local, b);
200 } catch (...) {
201 GetOutput() = std::vector<double>(n, 0.0);
202 return true;
203 }
204
205 // обратный ход
206
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 std::vector<double> x = BackSubstitution(n, rank, size, c0, a_local, b);
207
208
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 MPI_Barrier(MPI_COMM_WORLD);
209
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 GetOutput() = x;
210
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 MPI_Barrier(MPI_COMM_WORLD);
211
212 return true;
213 10 }
214
215 10 bool ShvetsovaKGaussVertStripMPI::PostProcessingImpl() {
216 10 return true;
217 }
218
219 } // namespace shvetsova_k_gausse_vert_strip
220