GCC Code Coverage Report


Directory: ./
File: tasks/luzan_e_double_sparse_matrix_mult/all/src/ops_all.cpp
Date: 2026-06-04 20:25:32
Exec Total Coverage
Lines: 107 107 100.0%
Functions: 11 11 100.0%
Branches: 51 82 62.2%

Line Branch Exec Source
1 #include "luzan_e_double_sparse_matrix_mult/all/include/ops_all.hpp"
2
3 #include <mpi.h>
4 #include <omp.h>
5
6 #include <cmath>
7 #include <utility>
8 #include <vector>
9
10 #include "luzan_e_double_sparse_matrix_mult/common/include/common.hpp"
11
12 namespace luzan_e_double_sparse_matrix_mult {
13
14
1/2
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 LuzanEDoubleSparseMatrixMultALL::LuzanEDoubleSparseMatrixMultALL(const InType &in) {
15 SetTypeOfTask(GetStaticTypeOfTask());
16
17 GetInput() = in;
18 // GetOutput() = 0;
19 12 }
20
21 24 void LuzanEDoubleSparseMatrixMultALL::BroadcastMatrix(SparseMatrix &m, int root) {
22 24 MPI_Bcast(&m.rows, 1, MPI_UNSIGNED, root, MPI_COMM_WORLD);
23 24 MPI_Bcast(&m.cols, 1, MPI_UNSIGNED, root, MPI_COMM_WORLD);
24
25 24 int nnz = static_cast<int>(m.value.size());
26 24 int ci_size = static_cast<int>(m.col_index.size());
27 24 MPI_Bcast(&nnz, 1, MPI_INT, root, MPI_COMM_WORLD);
28 24 MPI_Bcast(&ci_size, 1, MPI_INT, root, MPI_COMM_WORLD);
29
30 24 m.value.resize(nnz);
31 24 m.row.resize(nnz);
32 24 m.col_index.resize(ci_size);
33
34 24 MPI_Bcast(m.value.data(), nnz, MPI_DOUBLE, root, MPI_COMM_WORLD);
35 24 MPI_Bcast(m.row.data(), nnz, MPI_UNSIGNED, root, MPI_COMM_WORLD);
36 24 MPI_Bcast(m.col_index.data(), ci_size, MPI_UNSIGNED, root, MPI_COMM_WORLD);
37 24 }
38
39 12 void LuzanEDoubleSparseMatrixMultALL::BuildColDistribution(int b_cols, int nprocs, std::vector<int> &counts,
40 std::vector<int> &displs) {
41 12 counts.resize(nprocs);
42 12 displs.resize(nprocs, 0);
43
44 12 int base = b_cols / nprocs;
45 12 int rem = b_cols % nprocs;
46
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 12 times.
36 for (int i = 0; i < nprocs; i++) {
47
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
40 counts[i] = base + (i < rem ? 1 : 0);
48 }
49
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 12 times.
24 for (int i = 1; i < nprocs; i++) {
50 12 displs[i] = displs[i - 1] + counts[i - 1];
51 }
52 12 }
53
54 12 void LuzanEDoubleSparseMatrixMultALL::ComputeLocalCols(const SparseMatrix &a, const SparseMatrix &b, int col_start,
55 int col_count, std::vector<std::vector<double>> &values_per_col,
56 std::vector<std::vector<unsigned>> &rows_per_col) {
57 12 values_per_col.resize(col_count);
58 12 rows_per_col.resize(col_count);
59
60 12 #pragma omp parallel for schedule(static) default(none) \
61 shared(a, b, values_per_col, rows_per_col, col_start, col_count, kEPS)
62 for (int lc = 0; lc < col_count; lc++) {
63 int b_col = col_start + lc;
64
65 std::vector<double> tmp_col(a.rows, 0.0);
66
67 unsigned b_rs = b.col_index[b_col];
68 unsigned b_re = b.col_index[b_col + 1];
69
70 for (unsigned bp = b_rs; bp < b_re; bp++) {
71 double b_val = b.value[bp];
72 unsigned b_row = b.row[bp];
73
74 unsigned a_rs = a.col_index[b_row];
75 unsigned a_re = a.col_index[b_row + 1];
76
77 for (unsigned ap = a_rs; ap < a_re; ap++) {
78 tmp_col[a.row[ap]] += a.value[ap] * b_val;
79 }
80 }
81
82 for (unsigned i = 0; i < a.rows; i++) {
83 if (std::fabs(tmp_col[i]) > kEPS) {
84 values_per_col[lc].push_back(tmp_col[i]);
85 rows_per_col[lc].push_back(i);
86 }
87 }
88 }
89 12 }
90
91 12 void LuzanEDoubleSparseMatrixMultALL::FlattenLocalCols(const std::vector<std::vector<double>> &values_per_col,
92 const std::vector<std::vector<unsigned>> &rows_per_col,
93 std::vector<int> &col_nnz, std::vector<double> &flat_vals,
94 std::vector<unsigned> &flat_rows) {
95 12 int col_count = static_cast<int>(values_per_col.size());
96 12 col_nnz.resize(col_count);
97
98
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 12 times.
28 for (int lc = 0; lc < col_count; lc++) {
99 16 col_nnz[lc] = static_cast<int>(values_per_col[lc].size());
100 16 flat_vals.insert(flat_vals.end(), values_per_col[lc].begin(), values_per_col[lc].end());
101 16 flat_rows.insert(flat_rows.end(), rows_per_col[lc].begin(), rows_per_col[lc].end());
102 }
103 12 }
104
105 12 void LuzanEDoubleSparseMatrixMultALL::GatherFlatArrays(int rank, int nprocs, const std::vector<double> &local_vals,
106 const std::vector<unsigned> &local_rows,
107 std::vector<double> &global_vals,
108 std::vector<unsigned> &global_rows) {
109 12 int local_nnz = static_cast<int>(local_vals.size());
110
111 12 std::vector<int> nnz_counts(nprocs, 0);
112
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> nnz_displs(nprocs, 0);
113
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Gather(&local_nnz, 1, MPI_INT, nnz_counts.data(), 1, MPI_INT, 0, MPI_COMM_WORLD);
114
115
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (rank == 0) {
116
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 for (int i = 1; i < nprocs; i++) {
117 6 nnz_displs[i] = nnz_displs[i - 1] + nnz_counts[i - 1];
118 }
119
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 int total_nnz = nnz_displs[nprocs - 1] + nnz_counts[nprocs - 1];
120
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 global_vals.resize(total_nnz);
121
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 global_rows.resize(total_nnz);
122 }
123
124
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Gatherv(local_vals.data(), local_nnz, MPI_DOUBLE, global_vals.data(), nnz_counts.data(), nnz_displs.data(),
125 MPI_DOUBLE, 0, MPI_COMM_WORLD);
126
127
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Gatherv(local_rows.data(), local_nnz, MPI_UNSIGNED, global_rows.data(), nnz_counts.data(), nnz_displs.data(),
128 MPI_UNSIGNED, 0, MPI_COMM_WORLD);
129 12 }
130
131 12 SparseMatrix LuzanEDoubleSparseMatrixMultALL::CalcProdMPIOMP(const SparseMatrix &a_in, const SparseMatrix &b_in) {
132 12 int rank = 0;
133 12 int nprocs = 0;
134 12 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
135 12 MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
136
137
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 SparseMatrix a = (rank == 0) ? a_in : SparseMatrix{};
138
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
12 SparseMatrix b = (rank == 0) ? b_in : SparseMatrix{};
139
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 BroadcastMatrix(a, 0);
140
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 BroadcastMatrix(b, 0);
141
142 12 int b_cols = static_cast<int>(b.cols);
143 12 std::vector<int> counts;
144 12 std::vector<int> displs;
145
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 BuildColDistribution(b_cols, nprocs, counts, displs);
146
147
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 int my_col_start = displs[rank];
148 12 int my_col_count = counts[rank];
149
150 12 std::vector<std::vector<double>> values_per_col;
151 12 std::vector<std::vector<unsigned>> rows_per_col;
152
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 ComputeLocalCols(a, b, my_col_start, my_col_count, values_per_col, rows_per_col);
153
154 12 std::vector<int> col_nnz;
155 12 std::vector<double> flat_vals;
156 12 std::vector<unsigned> flat_rows;
157
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 FlattenLocalCols(values_per_col, rows_per_col, col_nnz, flat_vals, flat_rows);
158
159
4/8
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 12 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
18 std::vector<int> global_col_nnz(rank == 0 ? b_cols : 1);
160
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 MPI_Gatherv(col_nnz.data(), my_col_count, MPI_INT, global_col_nnz.data(), counts.data(), displs.data(), MPI_INT, 0,
161 MPI_COMM_WORLD);
162
163 12 std::vector<double> global_vals;
164 12 std::vector<unsigned> global_rows;
165
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 GatherFlatArrays(rank, nprocs, flat_vals, flat_rows, global_vals, global_rows);
166
167 SparseMatrix c;
168
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (rank == 0) {
169 6 c.rows = a.rows;
170 6 c.cols = b.cols;
171 6 c.value = std::move(global_vals);
172 6 c.row = std::move(global_rows);
173
174
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 c.col_index.reserve(static_cast<unsigned>(b_cols) + 1);
175
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 c.col_index.push_back(0);
176
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 6 times.
22 for (int j = 0; j < b_cols; j++) {
177
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 c.col_index.push_back(c.col_index.back() + static_cast<unsigned>(global_col_nnz[j]));
178 }
179 }
180
181 12 return c;
182 24 }
183
184 12 bool LuzanEDoubleSparseMatrixMultALL::ValidationImpl() {
185 12 int rank = 0;
186 12 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
187
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (rank == 0) {
188 return true;
189 }
190 const auto &a = std::get<0>(GetInput());
191 const auto &b = std::get<1>(GetInput());
192
4/8
✓ 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.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
6 return a.GetCols() == b.GetRows() && a.GetCols() != 0 && a.GetRows() != 0 && b.GetCols() != 0;
193 }
194
195 12 bool LuzanEDoubleSparseMatrixMultALL::PreProcessingImpl() {
196 12 return true;
197 }
198
199 12 bool LuzanEDoubleSparseMatrixMultALL::RunImpl() {
200 12 int rank = 0;
201 12 int size = 0;
202 12 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
203 12 MPI_Comm_size(MPI_COMM_WORLD, &size);
204
205 const auto &a = std::get<0>(GetInput());
206 const auto &b = std::get<1>(GetInput());
207
208 12 GetOutput() = CalcProdMPIOMP(a, b);
209 12 return true;
210 }
211
212 12 bool LuzanEDoubleSparseMatrixMultALL::PostProcessingImpl() {
213 12 return true;
214 }
215
216 } // namespace luzan_e_double_sparse_matrix_mult
217