GCC Code Coverage Report


Directory: ./
File: tasks/egorova_l_find_max_val_col_matrix/mpi/src/ops_mpi.cpp
Date: 2026-01-10 02:40:41
Exec Total Coverage
Lines: 85 86 98.8%
Functions: 11 11 100.0%
Branches: 57 74 77.0%

Line Branch Exec Source
1 #include "egorova_l_find_max_val_col_matrix/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <algorithm>
6 #include <cstddef>
7 #include <limits>
8 #include <vector>
9
10 #include "egorova_l_find_max_val_col_matrix/common/include/common.hpp"
11
12 namespace egorova_l_find_max_val_col_matrix {
13
14 #ifdef __GNUC__
15 # pragma GCC diagnostic push
16 # pragma GCC diagnostic ignored "-Wnull-dereference"
17 #endif
18
19
1/2
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
36 EgorovaLFindMaxValColMatrixMPI::EgorovaLFindMaxValColMatrixMPI(const InType &in) {
20 SetTypeOfTask(GetStaticTypeOfTask());
21
1/2
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
36 GetInput() = in;
22 36 GetOutput() = std::vector<int>(0);
23 36 }
24
25 #ifdef __GNUC__
26 # pragma GCC diagnostic pop
27 #endif
28
29
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 2 times.
36 bool EgorovaLFindMaxValColMatrixMPI::ValidationImpl() {
30 const auto &matrix = GetInput();
31
32
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 2 times.
36 if (matrix.empty()) {
33 return true;
34 }
35
36
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 2 times.
34 if (matrix[0].empty()) {
37 return true;
38 }
39
40 const std::size_t cols = matrix[0].size();
41 return std::ranges::all_of(matrix, [cols](const auto &row) { return row.size() == cols; });
42 }
43
44 36 bool EgorovaLFindMaxValColMatrixMPI::PreProcessingImpl() {
45 36 return true;
46 }
47
48
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 2 times.
36 bool EgorovaLFindMaxValColMatrixMPI::RunImpl() {
49 const auto &matrix = GetInput();
50
51
4/4
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 32 times.
36 if (matrix.empty() || matrix[0].empty()) {
52 4 GetOutput() = std::vector<int>();
53 4 return true;
54 }
55
56 32 return RunMPIAlgorithm();
57 }
58
59 32 bool EgorovaLFindMaxValColMatrixMPI::RunMPIAlgorithm() {
60 32 int rank = 0;
61 32 int size = 0;
62 32 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
63 32 MPI_Comm_size(MPI_COMM_WORLD, &size);
64
65 32 int rows = 0;
66 32 int cols = 0;
67
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
32 if (rank == 0) {
68 16 rows = static_cast<int>(GetInput().size());
69 16 cols = static_cast<int>(GetInput()[0].size());
70 }
71
72 32 MPI_Bcast(&rows, 1, MPI_INT, 0, MPI_COMM_WORLD);
73 32 MPI_Bcast(&cols, 1, MPI_INT, 0, MPI_COMM_WORLD);
74
75 // Распределение столбцов по процессам
76 32 const int cols_per_proc = cols / size;
77 32 const int remainder = cols % size;
78 int start_col = 0;
79 int local_cols_count = 0;
80
81
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 18 times.
32 if (rank < remainder) {
82 14 start_col = rank * (cols_per_proc + 1);
83 local_cols_count = cols_per_proc + 1;
84 } else {
85 18 start_col = (remainder * (cols_per_proc + 1)) + ((rank - remainder) * cols_per_proc);
86 local_cols_count = cols_per_proc;
87 }
88
89 // Получение локальной части матрицы
90 32 std::vector<int> local_matrix_part = GetLocalMatrixPart(rank, size, rows, cols, start_col, local_cols_count);
91
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 std::vector<int> local_max = CalculateLocalMaxima(local_matrix_part, rows, local_cols_count);
92
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 std::vector<int> all_max = GatherResults(local_max, size, cols);
93
94
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 GetOutput() = all_max;
95
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 MPI_Barrier(MPI_COMM_WORLD);
96 32 return true;
97 }
98
99 32 std::vector<int> EgorovaLFindMaxValColMatrixMPI::GetLocalMatrixPart(int rank, int size, int rows, int cols,
100 int start_col, int local_cols_count) {
101 32 std::vector<int> local_part(static_cast<std::size_t>(rows) * static_cast<std::size_t>(local_cols_count));
102
103
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
32 if (rank == 0) {
104 const auto &matrix = GetInput();
105
106 // Процесс 0 заполняет свою локальную часть
107
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 16 times.
67 for (int ii = 0; ii < rows; ++ii) {
108
2/2
✓ Branch 0 taken 99 times.
✓ Branch 1 taken 51 times.
150 for (int local_idx = 0; local_idx < local_cols_count; ++local_idx) {
109 99 const int global_col = start_col + local_idx;
110 99 local_part[(static_cast<std::size_t>(ii) * static_cast<std::size_t>(local_cols_count)) + local_idx] =
111 99 matrix[ii][global_col];
112 }
113 }
114
115 // Отправка частей матрицы другим процессам
116
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 SendMatrixPartsToOtherRanks(size, rows, cols);
117 } else {
118 // Получение данных от процесса 0
119
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 MPI_Recv(local_part.data(), static_cast<int>(local_part.size()), MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
120 }
121
122 32 return local_part;
123 }
124
125 16 void EgorovaLFindMaxValColMatrixMPI::SendMatrixPartsToOtherRanks(int size, int rows, int cols) {
126
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
32 for (int dest_rank = 1; dest_rank < size; ++dest_rank) {
127 16 std::vector<int> dest_part = PrepareMatrixPartForRank(dest_rank, size, rows, cols);
128
129 // Отправка данных процессу-получателю
130
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 MPI_Send(dest_part.data(), static_cast<int>(dest_part.size()), MPI_INT, dest_rank, 0, MPI_COMM_WORLD);
131 }
132 16 }
133
134 16 std::vector<int> EgorovaLFindMaxValColMatrixMPI::PrepareMatrixPartForRank(int dest_rank, int size, int rows, int cols) {
135 // Вычисление диапазона столбцов для процесса-получателя
136 16 const int cols_per_proc = cols / size;
137 16 const int remainder = cols % size;
138
139 int dest_start_col = 0;
140 int dest_cols_count = 0;
141
142
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (dest_rank < remainder) {
143 dest_start_col = dest_rank * (cols_per_proc + 1);
144 dest_cols_count = cols_per_proc + 1;
145 } else {
146 16 dest_start_col = (remainder * (cols_per_proc + 1)) + ((dest_rank - remainder) * cols_per_proc);
147 dest_cols_count = cols_per_proc;
148 }
149
150 // Подготовка данных для отправки
151 const auto &matrix = GetInput();
152 16 std::vector<int> dest_part(static_cast<std::size_t>(rows) * static_cast<std::size_t>(dest_cols_count));
153
154
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 16 times.
67 for (int ii = 0; ii < rows; ++ii) {
155
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 51 times.
102 for (int jj = 0; jj < dest_cols_count; ++jj) {
156 51 const int global_col = dest_start_col + jj;
157 51 dest_part[(static_cast<std::size_t>(ii) * static_cast<std::size_t>(dest_cols_count)) + jj] =
158 51 matrix[ii][global_col];
159 }
160 }
161
162 16 return dest_part;
163 }
164
165 32 std::vector<int> EgorovaLFindMaxValColMatrixMPI::CalculateLocalMaxima(const std::vector<int> &local_matrix_part,
166 int rows, int local_cols_count) {
167 32 std::vector<int> local_max(local_cols_count, std::numeric_limits<int>::min());
168
169
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 32 times.
88 for (int local_idx = 0; local_idx < local_cols_count; ++local_idx) {
170
2/2
✓ Branch 0 taken 150 times.
✓ Branch 1 taken 56 times.
206 for (int row = 0; row < rows; ++row) {
171
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 118 times.
150 const int value = local_matrix_part[(row * local_cols_count) + local_idx];
172
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 118 times.
182 local_max[local_idx] = std::max(value, local_max[local_idx]);
173 }
174 }
175
176 32 return local_max;
177 }
178
179 32 std::vector<int> EgorovaLFindMaxValColMatrixMPI::GatherResults(const std::vector<int> &local_max, int size, int cols) {
180 32 const int cols_per_proc = cols / size;
181 32 const int remainder = cols % size;
182
183 32 std::vector<int> all_max(cols, std::numeric_limits<int>::min());
184
1/4
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
32 std::vector<int> recv_counts(size);
185
1/4
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
32 std::vector<int> displs(size);
186
187
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 32 times.
96 for (int ii = 0; ii < size; ++ii) {
188
4/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 32 times.
✓ Branch 3 taken 32 times.
64 recv_counts[ii] = (ii < remainder) ? (cols_per_proc + 1) : cols_per_proc;
189
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 32 times.
64 displs[ii] = (ii == 0) ? 0 : displs[ii - 1] + recv_counts[ii - 1];
190 }
191
192
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 MPI_Allgatherv(local_max.data(), static_cast<int>(local_max.size()), MPI_INT, all_max.data(), recv_counts.data(),
193 displs.data(), MPI_INT, MPI_COMM_WORLD);
194
195 32 return all_max;
196 }
197
198 36 bool EgorovaLFindMaxValColMatrixMPI::PostProcessingImpl() {
199 36 return true;
200 }
201
202 } // namespace egorova_l_find_max_val_col_matrix
203