GCC Code Coverage Report


Directory: ./
File: tasks/alekseev_a_mult_matrix_crs/all/src/ops_all.cpp
Date: 2026-06-04 20:25:32
Exec Total Coverage
Lines: 125 125 100.0%
Functions: 8 8 100.0%
Branches: 88 150 58.7%

Line Branch Exec Source
1 #include "alekseev_a_mult_matrix_crs/all/include/ops_all.hpp"
2
3 #include <mpi.h>
4 #include <omp.h>
5
6 #include <algorithm>
7 #include <cmath>
8 #include <cstddef>
9 #include <utility>
10 #include <vector>
11
12 #include "alekseev_a_mult_matrix_crs/common/include/common.hpp"
13
14 #ifdef _MSC_VER
15 # define MPI_SIZE_T MPI_UNSIGNED_LONG_LONG
16 #else
17 # define MPI_SIZE_T MPI_UNSIGNED_LONG
18 #endif
19
20 namespace alekseev_a_mult_matrix_crs {
21
22
1/2
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 AlekseevAMultMatrixCRSALL::AlekseevAMultMatrixCRSALL(const InType &in) {
23 SetTypeOfTask(GetStaticTypeOfTask());
24 GetInput() = in;
25 12 }
26
27 12 bool AlekseevAMultMatrixCRSALL::ValidationImpl() {
28 12 int rank = 0;
29 12 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
30 12 int global_valid = 0;
31
32
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (rank == 0) {
33 const auto &a = std::get<0>(GetInput());
34 const auto &b = std::get<1>(GetInput());
35
3/6
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
6 if (a.cols == b.rows && !a.row_ptr.empty() && !b.row_ptr.empty()) {
36 6 global_valid = 1;
37 }
38 }
39 12 MPI_Bcast(&global_valid, 1, MPI_INT, 0, MPI_COMM_WORLD);
40 12 return global_valid == 1;
41 }
42
43 12 bool AlekseevAMultMatrixCRSALL::PreProcessingImpl() {
44 12 return true;
45 }
46
47 12 void AlekseevAMultMatrixCRSALL::BroadcastData(CRSMatrix &a, CRSMatrix &b, int rank) {
48 12 std::vector<std::size_t> dims(4);
49
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (rank == 0) {
50
1/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
12 dims = {a.rows, a.cols, b.rows, b.cols};
51 }
52
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Bcast(dims.data(), 4, MPI_SIZE_T, 0, MPI_COMM_WORLD);
53
54
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (rank != 0) {
55 6 a.rows = dims[0];
56 6 a.cols = dims[1];
57 6 b.rows = dims[2];
58 6 b.cols = dims[3];
59
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 a.row_ptr.resize(a.rows + 1);
60
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 b.row_ptr.resize(b.rows + 1);
61 }
62
63
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Bcast(a.row_ptr.data(), static_cast<int>(a.rows + 1), MPI_SIZE_T, 0, MPI_COMM_WORLD);
64
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Bcast(b.row_ptr.data(), static_cast<int>(b.rows + 1), MPI_SIZE_T, 0, MPI_COMM_WORLD);
65
66
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (rank != 0) {
67
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 a.values.resize(a.row_ptr.back());
68
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 a.col_indices.resize(a.row_ptr.back());
69
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 b.values.resize(b.row_ptr.back());
70
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 b.col_indices.resize(b.row_ptr.back());
71 }
72
73
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Bcast(a.values.data(), static_cast<int>(a.values.size()), MPI_DOUBLE, 0, MPI_COMM_WORLD);
74
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Bcast(a.col_indices.data(), static_cast<int>(a.col_indices.size()), MPI_SIZE_T, 0, MPI_COMM_WORLD);
75
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Bcast(b.values.data(), static_cast<int>(b.values.size()), MPI_DOUBLE, 0, MPI_COMM_WORLD);
76
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Bcast(b.col_indices.data(), static_cast<int>(b.col_indices.size()), MPI_SIZE_T, 0, MPI_COMM_WORLD);
77 12 }
78
79 12 void AlekseevAMultMatrixCRSALL::GatherData(CRSMatrix &out, const InType &input,
80 const std::vector<std::vector<double>> &local_v,
81 const std::vector<std::vector<std::size_t>> &local_c,
82 const std::vector<int> &send_counts, const std::vector<int> &displs,
83 int rank, int size) {
84 12 int local_n = static_cast<int>(local_v.size());
85 12 std::vector<int> local_row_sizes(local_n);
86 12 std::vector<double> flat_v;
87 12 std::vector<std::size_t> flat_c;
88
89
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int i = 0; i < local_n; ++i) {
90
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 local_row_sizes[i] = static_cast<int>(local_v[i].size());
91
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 flat_v.insert(flat_v.end(), local_v[i].begin(), local_v[i].end());
92 12 flat_c.insert(flat_c.end(), local_c[i].begin(), local_c[i].end());
93 }
94
95 12 std::vector<int> all_row_sizes;
96
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (rank == 0) {
97
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 all_row_sizes.resize(std::get<0>(input).rows);
98 }
99
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Gatherv(local_row_sizes.data(), local_n, MPI_INT, all_row_sizes.data(), send_counts.data(), displs.data(),
100 MPI_INT, 0, MPI_COMM_WORLD);
101
102 12 int local_total = static_cast<int>(flat_v.size());
103
2/6
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
12 std::vector<int> all_total_counts(size);
104
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Gather(&local_total, 1, MPI_INT, all_total_counts.data(), 1, MPI_INT, 0, MPI_COMM_WORLD);
105
106
1/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
12 std::vector<int> v_displs(size, 0);
107 12 std::vector<double> final_v;
108 12 std::vector<std::size_t> final_c;
109 12 int total_elements = 0;
110
111
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (rank == 0) {
112
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
18 for (int i = 0; i < size; ++i) {
113 12 v_displs[i] = total_elements;
114 12 total_elements += all_total_counts[i];
115 }
116
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 final_v.resize(total_elements);
117
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 final_c.resize(total_elements);
118 }
119
120
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Gatherv(flat_v.data(), local_total, MPI_DOUBLE, final_v.data(), all_total_counts.data(), v_displs.data(),
121 MPI_DOUBLE, 0, MPI_COMM_WORLD);
122
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Gatherv(flat_c.data(), local_total, MPI_SIZE_T, final_c.data(), all_total_counts.data(), v_displs.data(),
123 MPI_SIZE_T, 0, MPI_COMM_WORLD);
124
125
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (rank == 0) {
126 6 out.rows = std::get<0>(input).rows;
127 6 out.cols = std::get<1>(input).cols;
128 }
129
130
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Bcast(&out.rows, 1, MPI_SIZE_T, 0, MPI_COMM_WORLD);
131
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Bcast(&out.cols, 1, MPI_SIZE_T, 0, MPI_COMM_WORLD);
132
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Bcast(&total_elements, 1, MPI_INT, 0, MPI_COMM_WORLD);
133
134
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (rank != 0) {
135
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 final_v.resize(total_elements);
136
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 final_c.resize(total_elements);
137
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 all_row_sizes.resize(out.rows);
138 }
139
140
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Bcast(final_v.data(), total_elements, MPI_DOUBLE, 0, MPI_COMM_WORLD);
141
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Bcast(final_c.data(), total_elements, MPI_SIZE_T, 0, MPI_COMM_WORLD);
142
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Bcast(all_row_sizes.data(), static_cast<int>(out.rows), MPI_INT, 0, MPI_COMM_WORLD);
143
144 12 out.values = std::move(final_v);
145 12 out.col_indices = std::move(final_c);
146
1/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
12 out.row_ptr.assign(out.rows + 1, 0);
147
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 12 times.
36 for (std::size_t i = 0; i < out.rows; ++i) {
148 24 out.row_ptr[i + 1] = out.row_ptr[i] + static_cast<std::size_t>(all_row_sizes[i]);
149 }
150 12 }
151
152 12 bool AlekseevAMultMatrixCRSALL::RunImpl() {
153 12 int rank = 0;
154 12 int size = 0;
155 12 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
156 12 MPI_Comm_size(MPI_COMM_WORLD, &size);
157
158 auto &a = std::get<0>(GetInput());
159 auto &b = std::get<1>(GetInput());
160
161 12 BroadcastData(a, b, rank);
162
163 12 std::vector<int> send_counts(size);
164
1/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
12 std::vector<int> displs(size);
165
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (rank == 0) {
166 6 int rows_per_proc = static_cast<int>(a.rows) / size;
167 6 int extra = static_cast<int>(a.rows) % size;
168 int offset = 0;
169
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 6 times.
18 for (int i = 0; i < size; ++i) {
170
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
22 send_counts[i] = rows_per_proc + (i < extra ? 1 : 0);
171 12 displs[i] = offset;
172 12 offset += send_counts[i];
173 }
174 }
175
176 12 int local_n = 0;
177
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 int local_start = 0;
178
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Scatter(send_counts.data(), 1, MPI_INT, &local_n, 1, MPI_INT, 0, MPI_COMM_WORLD);
179
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Scatter(displs.data(), 1, MPI_INT, &local_start, 1, MPI_INT, 0, MPI_COMM_WORLD);
180
181
1/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
12 std::vector<std::vector<double>> local_v(local_n);
182
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 std::vector<std::vector<std::size_t>> local_c(local_n);
183
184 auto *p_a = &a;
185 auto *p_b = &b;
186 auto *p_lv = &local_v;
187 auto *p_lc = &local_c;
188
189 12 #pragma omp parallel default(none) shared(p_a, p_b, p_lv, p_lc, local_n, local_start)
190 {
191 std::vector<double> accum(p_b->cols, 0.0);
192 std::vector<int> touched_flag(p_b->cols, -1);
193 std::vector<std::size_t> touched_cols;
194 touched_cols.reserve(p_b->cols);
195 #pragma omp for schedule(dynamic)
196 for (int i = 0; i < local_n; ++i) {
197 auto g_row = static_cast<std::size_t>(local_start) + static_cast<std::size_t>(i);
198 ProcessRow(g_row, *p_a, *p_b, (*p_lv)[i], (*p_lc)[i], accum, touched_flag, touched_cols);
199 }
200 }
201
202
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 GatherData(GetOutput(), GetInput(), local_v, local_c, send_counts, displs, rank, size);
203 12 return true;
204 12 }
205
206 12 void AlekseevAMultMatrixCRSALL::ProcessRow(std::size_t i, const CRSMatrix &a, const CRSMatrix &b,
207 std::vector<double> &temp_v, std::vector<std::size_t> &temp_c,
208 std::vector<double> &accum, std::vector<int> &touched_flag,
209 std::vector<std::size_t> &touched_cols) {
210
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 12 times.
25 for (std::size_t pos_a = a.row_ptr[i]; pos_a < a.row_ptr[i + 1]; ++pos_a) {
211 13 const std::size_t k = a.col_indices[pos_a];
212 13 const double val_a = a.values[pos_a];
213
214
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 13 times.
33 for (std::size_t pos_b = b.row_ptr[k]; pos_b < b.row_ptr[k + 1]; ++pos_b) {
215
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 15 times.
20 const std::size_t j = b.col_indices[pos_b];
216
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 15 times.
20 if (std::cmp_not_equal(touched_flag[j], i)) {
217
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 touched_flag[j] = static_cast<int>(i);
218 touched_cols.push_back(j);
219 15 accum[j] = 0.0;
220 }
221 20 accum[j] += val_a * b.values[pos_b];
222 }
223 }
224 std::ranges::sort(touched_cols);
225
3/4
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 12 times.
27 for (const auto col : touched_cols) {
226
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if (std::abs(accum[col]) > 1e-15) {
227 temp_v.push_back(accum[col]);
228 temp_c.push_back(col);
229 }
230 }
231 touched_cols.clear();
232 12 }
233
234 12 bool AlekseevAMultMatrixCRSALL::PostProcessingImpl() {
235 12 MPI_Barrier(MPI_COMM_WORLD);
236 12 return true;
237 }
238
239 } // namespace alekseev_a_mult_matrix_crs
240