GCC Code Coverage Report


Directory: ./
File: tasks/rychkova_d_sum_matrix_columns/mpi/src/ops_mpi.cpp
Date: 2026-01-10 02:40:41
Exec Total Coverage
Lines: 80 84 95.2%
Functions: 7 7 100.0%
Branches: 48 74 64.9%

Line Branch Exec Source
1 #include "rychkova_d_sum_matrix_columns/mpi/include/ops_mpi.hpp"
2
3 #include <mpi.h>
4
5 #include <cstddef>
6 #include <utility>
7 #include <vector>
8
9 #include "rychkova_d_sum_matrix_columns/common/include/common.hpp"
10
11 namespace rychkova_d_sum_matrix_columns {
12
13
1/2
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
26 RychkovaDSumMatrixColumnsMPI::RychkovaDSumMatrixColumnsMPI(const InType &in) {
14 SetTypeOfTask(GetStaticTypeOfTask());
15
1/2
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
26 GetInput().resize(in.size());
16
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 26 times.
86 for (size_t i = 0; i < in.size(); ++i) {
17
1/2
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
60 GetInput()[i] = in[i];
18 }
19 26 GetOutput() = OutType{};
20 26 }
21
22 26 bool RychkovaDSumMatrixColumnsMPI::ValidationImpl() {
23 26 int rank = 0;
24 26 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
25
26 26 bool is_valid = true;
27
28
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 13 times.
26 if (rank == 0) {
29 const auto &input = GetInput();
30
31
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 if (!input.empty()) {
32 size_t cols = input[0].size();
33
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 13 times.
43 for (const auto &row : input) {
34
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (row.size() != cols) {
35 is_valid = false;
36 break;
37 }
38 }
39 }
40
41
2/4
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
13 is_valid = is_valid && GetOutput().empty();
42 }
43
44 26 MPI_Bcast(&is_valid, 1, MPI_C_BOOL, 0, MPI_COMM_WORLD);
45
46 26 return is_valid;
47 }
48
49 26 bool RychkovaDSumMatrixColumnsMPI::PreProcessingImpl() {
50 26 int rank = 0;
51 26 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
52
53 26 bool has_data = false;
54 26 size_t num_cols = 0;
55
56
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 13 times.
26 if (rank == 0) {
57 const auto &input = GetInput();
58 13 has_data = !input.empty();
59
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 if (has_data) {
60 13 num_cols = input[0].size();
61 }
62 }
63
64 26 MPI_Bcast(&has_data, 1, MPI_C_BOOL, 0, MPI_COMM_WORLD);
65 26 MPI_Bcast(&num_cols, 1, MPI_UNSIGNED_LONG_LONG, 0, MPI_COMM_WORLD);
66
67
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (has_data) {
68 52 GetOutput() = std::vector<int>(num_cols, 0);
69 } else {
70 GetOutput() = std::vector<int>{};
71 }
72
73 26 return true;
74 }
75
76 namespace {
77
78 void CalculateDistribution(int size, size_t num_rows, size_t num_cols, std::vector<int> &send_counts,
79 std::vector<int> &displacements) {
80 13 size_t rows_per_process = num_rows / static_cast<size_t>(size);
81 13 size_t remainder = num_rows % static_cast<size_t>(size);
82
83 size_t current_displacement = 0;
84
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 13 times.
39 for (int i = 0; i < size; ++i) {
85 26 auto process_index = static_cast<size_t>(i);
86
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 6 times.
26 size_t rows_for_process_i = rows_per_process + (process_index < remainder ? 1 : 0);
87 26 send_counts[i] = static_cast<int>(rows_for_process_i * num_cols);
88 26 displacements[i] = static_cast<int>(current_displacement);
89 26 current_displacement += rows_for_process_i * num_cols;
90 }
91 }
92
93 13 std::vector<int> FlattenMatrix(const InType &matrix) {
94
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 std::vector<int> flat_matrix;
95
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 if (!matrix.empty()) {
96 size_t num_rows = matrix.size();
97 size_t num_cols = matrix[0].size();
98
1/2
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
13 flat_matrix.reserve(num_rows * num_cols);
99
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 13 times.
43 for (const auto &row : matrix) {
100 30 flat_matrix.insert(flat_matrix.end(), row.begin(), row.end());
101 }
102 }
103 13 return flat_matrix;
104 }
105
106 26 std::vector<int> ComputeLocalSums(const std::vector<int> &local_data, size_t local_rows, size_t num_cols) {
107 26 std::vector<int> local_sums(num_cols, 0);
108
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 26 times.
56 for (size_t i = 0; i < local_rows; ++i) {
109
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 30 times.
94 for (size_t j = 0; j < num_cols; ++j) {
110 64 local_sums[j] += local_data[(i * num_cols) + j];
111 }
112 }
113 26 return local_sums;
114 }
115
116 } // namespace
117
118 26 bool RychkovaDSumMatrixColumnsMPI::RunImpl() {
119 26 int rank = 0;
120 26 int size = 0;
121 26 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
122 26 MPI_Comm_size(MPI_COMM_WORLD, &size);
123
124 const auto &output = GetOutput();
125 bool has_data = !output.empty();
126 size_t num_cols = output.size();
127
128
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 if (!has_data) {
129 std::vector<int> empty_sums(0);
130 MPI_Allreduce(MPI_IN_PLACE, empty_sums.data(), 0, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
131 return true;
132 }
133
134 26 size_t num_rows = 0;
135
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 13 times.
26 if (rank == 0) {
136 const auto &input = GetInput();
137 13 num_rows = input.size();
138 }
139 26 MPI_Bcast(&num_rows, 1, MPI_UNSIGNED_LONG_LONG, 0, MPI_COMM_WORLD);
140
141 26 std::vector<int> send_counts(size);
142
1/4
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
26 std::vector<int> displacements(size);
143
144
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 13 times.
26 if (rank == 0) {
145 13 CalculateDistribution(size, num_rows, num_cols, send_counts, displacements);
146 }
147
148
1/2
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
26 MPI_Bcast(send_counts.data(), size, MPI_INT, 0, MPI_COMM_WORLD);
149
1/2
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
26 MPI_Bcast(displacements.data(), size, MPI_INT, 0, MPI_COMM_WORLD);
150
151 26 size_t rows_per_process = num_rows / static_cast<size_t>(size);
152 26 size_t remainder = num_rows % static_cast<size_t>(size);
153
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 size_t local_rows = rows_per_process + (std::cmp_less(rank, remainder) ? 1 : 0);
154
155 26 std::vector<int> flat_matrix;
156
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 13 times.
26 if (rank == 0) {
157
1/2
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
26 flat_matrix = FlattenMatrix(GetInput());
158 }
159
160
1/4
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
26 std::vector<int> local_data(local_rows * num_cols);
161
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 13 times.
✓ Branch 3 taken 26 times.
✗ Branch 4 not taken.
39 MPI_Scatterv(rank == 0 ? flat_matrix.data() : nullptr, send_counts.data(), displacements.data(), MPI_INT,
162 local_data.data(), static_cast<int>(local_rows * num_cols), MPI_INT, 0, MPI_COMM_WORLD);
163
164
1/2
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
26 std::vector<int> local_sums = ComputeLocalSums(local_data, local_rows, num_cols);
165
166
1/2
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
26 MPI_Allreduce(local_sums.data(), GetOutput().data(), static_cast<int>(num_cols), MPI_INT, MPI_SUM, MPI_COMM_WORLD);
167
168 return true;
169 }
170
171 26 bool RychkovaDSumMatrixColumnsMPI::PostProcessingImpl() {
172 26 return true;
173 }
174
175 } // namespace rychkova_d_sum_matrix_columns
176