GCC Code Coverage Report


Directory: ./
File: tasks/shvetsova_k_mult_matrix_complex_col/all/src/ops_all.cpp
Date: 2026-05-11 08:26:31
Exec Total Coverage
Lines: 112 112 100.0%
Functions: 11 11 100.0%
Branches: 74 112 66.1%

Line Branch Exec Source
1 #include "../../all/include/ops_all.hpp"
2
3 #include <mpi.h>
4
5 #include <algorithm>
6 #include <complex>
7 #include <utility>
8 #include <vector>
9
10 #include "oneapi/tbb/blocked_range.h"
11 #include "oneapi/tbb/parallel_for.h"
12 #include "shvetsova_k_mult_matrix_complex_col/common/include/common.hpp"
13
14 namespace shvetsova_k_mult_matrix_complex_col {
15
16 struct SparseColumn {
17 std::vector<int> rows;
18 std::vector<std::complex<double>> vals;
19 };
20
21 namespace {
22
23
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 void ComputeColumnTask(int col_idx, const MatrixCCS &matrix_a, const MatrixCCS &matrix_b,
24 std::vector<std::complex<double>> &column_c_local, SparseColumn &out_col) {
25 std::ranges::fill(column_c_local, std::complex<double>{0.0, 0.0});
26
27
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 9 times.
19 for (int j = matrix_b.col_ptr[col_idx]; j < matrix_b.col_ptr[col_idx + 1]; j++) {
28 10 int tmp_ind = matrix_b.row_ind[j];
29 10 std::complex<double> tmp_val = matrix_b.values[j];
30
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 for (int ind = matrix_a.col_ptr[tmp_ind]; ind < matrix_a.col_ptr[tmp_ind + 1]; ind++) {
31 10 int row = matrix_a.row_ind[ind];
32 10 std::complex<double> val_a = matrix_a.values[ind];
33 10 column_c_local[row] += tmp_val * val_a;
34 }
35 }
36
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 for (int index = 0; std::cmp_less(index, column_c_local.size()); ++index) {
37
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 9 times.
17 if (column_c_local[index].real() != 0.0 || column_c_local[index].imag() != 0.0) {
38
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 out_col.rows.push_back(index);
39
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 out_col.vals.push_back(column_c_local[index]);
40 }
41 }
42 9 }
43
44 10 void FlattenLocalColumns(const std::vector<SparseColumn> &local_columns, std::vector<int> &local_rows,
45 std::vector<double> &local_vals_real, std::vector<double> &local_vals_imag) {
46
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 10 times.
19 for (const auto &col : local_columns) {
47 9 local_rows.insert(local_rows.end(), col.rows.begin(), col.rows.end());
48
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 for (const auto &val : col.vals) {
49 9 local_vals_real.push_back(val.real());
50 9 local_vals_imag.push_back(val.imag());
51 }
52 }
53 10 }
54
55 5 void PrepareGatherCounts(int size, int cols_per_rank, int remainder, int cols, std::vector<int> &recv_counts,
56 std::vector<int> &displs_cols, std::vector<int> &all_nnz_per_col) {
57
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 for (int i = 0; i < size; ++i) {
58
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
19 recv_counts[i] = cols_per_rank + (i < remainder ? 1 : 0);
59 10 displs_cols[i] = (i * cols_per_rank) + std::min(i, remainder);
60 }
61 5 all_nnz_per_col.resize(cols);
62 5 }
63
64 5 void PrepareGatherDisplacements(int size, int cols_per_rank, int remainder, const std::vector<int> &all_nnz_per_col,
65 std::vector<int> &recv_counts, std::vector<int> &displs_cols,
66 std::vector<int> &recv_nnz_counts, std::vector<int> &displs_nnz,
67 int &total_global_nnz) {
68
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 for (int i = 0; i < size; ++i) {
69
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
19 recv_counts[i] = cols_per_rank + (i < remainder ? 1 : 0);
70 10 displs_cols[i] = (i * cols_per_rank) + std::min(i, remainder);
71
72 int nnz_sum = 0;
73
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 10 times.
19 for (int j = 0; j < recv_counts[i]; ++j) {
74 9 nnz_sum += all_nnz_per_col[displs_cols[i] + j];
75 }
76 10 recv_nnz_counts[i] = nnz_sum;
77
78
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 if (i > 0) {
79 5 displs_nnz[i] = displs_nnz[i - 1] + recv_nnz_counts[i - 1];
80 }
81 }
82
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (size > 0) {
83 5 total_global_nnz = displs_nnz.back() + recv_nnz_counts.back();
84 }
85 5 }
86
87 // сборка финальной CCS матрицы на 0-м ранге
88
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 void AssembleFinalMatrix(const std::vector<int> &all_nnz_per_col, const std::vector<int> &all_rows,
89 const std::vector<double> &all_vals_real, const std::vector<double> &all_vals_imag, int cols,
90 MatrixCCS &matrix_c) {
91 matrix_c.row_ind.clear();
92 matrix_c.values.clear();
93 matrix_c.col_ptr.clear();
94 5 matrix_c.col_ptr.push_back(0);
95
96 int current_nnz = 0;
97
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 5 times.
14 for (int i = 0; i < cols; ++i) {
98 9 int nnz = all_nnz_per_col[i];
99
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 for (int k = 0; k < nnz; ++k) {
100
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8 times.
9 matrix_c.row_ind.push_back(all_rows[current_nnz + k]);
101 9 matrix_c.values.emplace_back(all_vals_real[current_nnz + k], all_vals_imag[current_nnz + k]);
102 }
103 9 current_nnz += nnz;
104 9 matrix_c.col_ptr.push_back(static_cast<int>(matrix_c.row_ind.size()));
105 }
106 5 }
107
108 } // namespace
109
110
1/2
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
10 ShvetsovaKMultMatrixComplexALL::ShvetsovaKMultMatrixComplexALL(const InType &in) {
111 SetTypeOfTask(GetStaticTypeOfTask());
112 GetInput() = in;
113
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 GetOutput() = MatrixCCS(0, 0, std::vector<int>{0}, std::vector<int>{}, std::vector<std::complex<double>>{});
114 10 }
115
116 10 bool ShvetsovaKMultMatrixComplexALL::ValidationImpl() {
117 10 return true;
118 }
119
120 10 bool ShvetsovaKMultMatrixComplexALL::PreProcessingImpl() {
121 const auto &matrix_a = std::get<0>(GetInput());
122 const auto &matrix_b = std::get<1>(GetInput());
123
124 auto &matrix_c = GetOutput();
125 10 matrix_c.rows = matrix_a.rows;
126
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 matrix_c.cols = matrix_b.cols;
127 matrix_c.row_ind.clear();
128 matrix_c.values.clear();
129 matrix_c.col_ptr.clear();
130 10 matrix_c.col_ptr.push_back(0);
131 10 return true;
132 }
133
134 10 bool ShvetsovaKMultMatrixComplexALL::RunImpl() {
135 const MatrixCCS &matrix_a = std::get<0>(GetInput());
136 const MatrixCCS &matrix_b = std::get<1>(GetInput());
137 auto &matrix_c = GetOutput();
138
139 10 int rank = 0;
140 10 int size = 1;
141 10 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
142 10 MPI_Comm_size(MPI_COMM_WORLD, &size);
143
144 10 int cols_per_rank = matrix_b.cols / size;
145 10 int remainder = matrix_b.cols % size;
146
147
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
10 int local_start = (rank * cols_per_rank) + std::min(rank, remainder);
148
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
10 int local_count = cols_per_rank + (rank < remainder ? 1 : 0);
149
150 10 std::vector<SparseColumn> local_columns(local_count);
151
152
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
19 tbb::parallel_for(tbb::blocked_range<int>(0, local_count), [&](const tbb::blocked_range<int> &r) {
153 9 std::vector<std::complex<double>> column_c_local(matrix_a.rows, {0.0, 0.0});
154
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9 times.
18 for (int i = r.begin(); i != r.end(); ++i) {
155 9 int global_col = local_start + i;
156
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 ComputeColumnTask(global_col, matrix_a, matrix_b, column_c_local, local_columns[i]);
157 }
158 9 });
159
160
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 std::vector<int> local_nnz_per_col(local_count);
161 int total_local_nnz = 0;
162
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 10 times.
19 for (int i = 0; i < local_count; ++i) {
163 9 local_nnz_per_col[i] = static_cast<int>(local_columns[i].rows.size());
164 9 total_local_nnz += local_nnz_per_col[i];
165 }
166
167 10 std::vector<int> local_rows;
168
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 local_rows.reserve(total_local_nnz);
169 10 std::vector<double> local_vals_real;
170
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 local_vals_real.reserve(total_local_nnz);
171 10 std::vector<double> local_vals_imag;
172
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 local_vals_imag.reserve(total_local_nnz);
173
174
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 FlattenLocalColumns(local_columns, local_rows, local_vals_real, local_vals_imag);
175
176
1/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
10 std::vector<int> recv_counts(size, 0);
177
1/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
10 std::vector<int> displs_cols(size, 0);
178 10 std::vector<int> all_nnz_per_col;
179
180
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 if (rank == 0) {
181
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 PrepareGatherCounts(size, cols_per_rank, remainder, matrix_b.cols, recv_counts, displs_cols, all_nnz_per_col);
182 }
183
184
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 MPI_Gatherv(local_nnz_per_col.data(), local_count, MPI_INT, all_nnz_per_col.data(), recv_counts.data(),
185 displs_cols.data(), MPI_INT, 0, MPI_COMM_WORLD);
186
187
1/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
10 std::vector<int> recv_nnz_counts(size, 0);
188
1/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
10 std::vector<int> displs_nnz(size, 0);
189 10 int total_global_nnz = 0;
190
191
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 if (rank == 0) {
192 5 PrepareGatherDisplacements(size, cols_per_rank, remainder, all_nnz_per_col, recv_counts, displs_cols,
193 recv_nnz_counts, displs_nnz, total_global_nnz);
194 }
195
196 10 std::vector<int> all_rows;
197 10 std::vector<double> all_vals_real;
198 10 std::vector<double> all_vals_imag;
199
200
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 if (rank == 0) {
201
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 all_rows.resize(total_global_nnz);
202
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 all_vals_real.resize(total_global_nnz);
203
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 all_vals_imag.resize(total_global_nnz);
204 }
205
206
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 MPI_Gatherv(local_rows.data(), total_local_nnz, MPI_INT, all_rows.data(), recv_nnz_counts.data(), displs_nnz.data(),
207 MPI_INT, 0, MPI_COMM_WORLD);
208
209
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 MPI_Gatherv(local_vals_real.data(), total_local_nnz, MPI_DOUBLE, all_vals_real.data(), recv_nnz_counts.data(),
210 displs_nnz.data(), MPI_DOUBLE, 0, MPI_COMM_WORLD);
211
212
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 MPI_Gatherv(local_vals_imag.data(), total_local_nnz, MPI_DOUBLE, all_vals_imag.data(), recv_nnz_counts.data(),
213 displs_nnz.data(), MPI_DOUBLE, 0, MPI_COMM_WORLD);
214
215
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 if (rank == 0) {
216
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 AssembleFinalMatrix(all_nnz_per_col, all_rows, all_vals_real, all_vals_imag, matrix_b.cols, matrix_c);
217 }
218
219 10 return true;
220 10 }
221
222 10 bool ShvetsovaKMultMatrixComplexALL::PostProcessingImpl() {
223 10 return true;
224 }
225
226 } // namespace shvetsova_k_mult_matrix_complex_col
227