GCC Code Coverage Report


Directory: ./
File: tasks/kurpiakov_a_sp_comp_mat_mul/tbb/src/ops_tbb.cpp
Date: 2026-06-04 20:25:32
Exec Total Coverage
Lines: 63 64 98.4%
Functions: 11 11 100.0%
Branches: 49 74 66.2%

Line Branch Exec Source
1 #include "kurpiakov_a_sp_comp_mat_mul/tbb/include/ops_tbb.hpp"
2
3 #include <tbb/tbb.h>
4
5 #include <algorithm>
6 #include <cstddef>
7 #include <utility>
8 #include <vector>
9
10 #include "kurpiakov_a_sp_comp_mat_mul/common/include/common.hpp"
11
12 namespace kurpiakov_a_sp_comp_mat_mul {
13
14 namespace {
15
16 80 bool ValidateCSR(const SparseMatrix &m) {
17
2/4
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 80 times.
80 if (m.rows <= 0 || m.cols <= 0) {
18 return false;
19 }
20
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (static_cast<int>(m.row_ptr.size()) != m.rows + 1) {
21 return false;
22 }
23
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (m.row_ptr[0] != 0) {
24 return false;
25 }
26
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (std::cmp_not_equal(m.values.size(), m.row_ptr[m.rows])) {
27 return false;
28 }
29
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 if (m.col_indices.size() != m.values.size()) {
30 return false;
31 }
32
2/2
✓ Branch 0 taken 156 times.
✓ Branch 1 taken 80 times.
236 for (int i = 0; i < m.rows; ++i) {
33
2/2
✓ Branch 0 taken 160 times.
✓ Branch 1 taken 156 times.
316 for (int j = m.row_ptr[i]; j < m.row_ptr[i + 1]; ++j) {
34
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 160 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 160 times.
160 if (m.col_indices[j] < 0 || m.col_indices[j] >= m.cols) {
35 return false;
36 }
37 }
38 }
39 return true;
40 }
41
42 struct ThreadLocalRowBuffers {
43
1/4
✓ Branch 2 taken 46 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
46 explicit ThreadLocalRowBuffers(int cols) : row_acc(cols), row_used(cols, 0) {}
44
45 std::vector<ComplexD> row_acc;
46 std::vector<char> row_used;
47 std::vector<int> used_cols;
48 };
49
50
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 56 times.
72 void ComputeRow(const SparseMatrix &a, const SparseMatrix &b, int row_idx, ThreadLocalRowBuffers &buffers,
51 std::vector<ComplexD> &out_values, std::vector<int> &out_cols) {
52 buffers.used_cols.clear();
53
54
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 72 times.
152 for (int ja = a.row_ptr[row_idx]; ja < a.row_ptr[row_idx + 1]; ++ja) {
55 80 const int ka = a.col_indices[ja];
56 const ComplexD &a_val = a.values[ja];
57
58
2/2
✓ Branch 0 taken 96 times.
✓ Branch 1 taken 80 times.
176 for (int jb = b.row_ptr[ka]; jb < b.row_ptr[ka + 1]; ++jb) {
59
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 28 times.
96 const int cb = b.col_indices[jb];
60 const ComplexD &b_val = b.values[jb];
61
62
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 28 times.
96 if (buffers.row_used[cb] == 0) {
63
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 49 times.
68 buffers.row_used[cb] = 1;
64 68 buffers.row_acc[cb] = ComplexD();
65
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 49 times.
68 buffers.used_cols.push_back(cb);
66 }
67
68 buffers.row_acc[cb] += a_val * b_val;
69 }
70 }
71
72 std::ranges::sort(buffers.used_cols);
73
74 out_values.clear();
75 out_cols.clear();
76 72 out_values.reserve(buffers.used_cols.size());
77 72 out_cols.reserve(buffers.used_cols.size());
78
79
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 72 times.
140 for (int c : buffers.used_cols) {
80
1/2
✓ Branch 0 taken 68 times.
✗ Branch 1 not taken.
68 out_values.push_back(buffers.row_acc[c]);
81 out_cols.push_back(c);
82 68 buffers.row_used[c] = 0;
83 }
84 72 }
85
86 40 SparseMatrix BuildResultFromRows(int rows, int cols, const std::vector<std::vector<ComplexD>> &row_values,
87 const std::vector<std::vector<int>> &row_cols) {
88 40 SparseMatrix result(rows, cols);
89
90
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 40 times.
112 for (int i = 0; i < rows; ++i) {
91 72 result.row_ptr[i + 1] = result.row_ptr[i] + static_cast<int>(row_values[i].size());
92 }
93
94
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 const auto total_nnz = static_cast<std::size_t>(result.row_ptr[rows]);
95
96
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 result.values.resize(total_nnz);
97
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 result.col_indices.resize(total_nnz);
98
99
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
112 tbb::parallel_for(tbb::blocked_range<int>(0, rows), [&](const tbb::blocked_range<int> &range) {
100
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 72 times.
144 for (int i = range.begin(); i < range.end(); ++i) {
101 72 const auto offset = static_cast<std::vector<ComplexD>::difference_type>(result.row_ptr[i]);
102 72 std::copy(row_values[i].begin(), row_values[i].end(), result.values.begin() + offset);
103 72 std::copy(row_cols[i].begin(), row_cols[i].end(), result.col_indices.begin() + offset);
104 }
105 72 });
106
107 40 return result;
108 }
109
110 } // namespace
111
112
1/2
✓ Branch 2 taken 40 times.
✗ Branch 3 not taken.
40 KurpiakovACRSMatMulTBB::KurpiakovACRSMatMulTBB(const InType &in) {
113 SetTypeOfTask(GetStaticTypeOfTask());
114 GetInput() = in;
115
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 GetOutput() = SparseMatrix();
116 40 }
117
118
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 bool KurpiakovACRSMatMulTBB::ValidationImpl() {
119 const auto &[a, b] = GetInput();
120
121
2/4
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
✗ Branch 3 not taken.
40 if (!ValidateCSR(a) || !ValidateCSR(b)) {
122 return false;
123 }
124
125 40 return a.cols == b.rows;
126 }
127
128 40 bool KurpiakovACRSMatMulTBB::PreProcessingImpl() {
129 40 return true;
130 }
131
132 40 bool KurpiakovACRSMatMulTBB::RunImpl() {
133 const auto &[a, b] = GetInput();
134 40 const int rows = a.rows;
135 40 const int cols = b.cols;
136
137 40 std::vector<std::vector<ComplexD>> row_values(rows);
138
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 std::vector<std::vector<int>> row_cols(rows);
139
140
1/2
✓ Branch 2 taken 40 times.
✗ Branch 3 not taken.
86 tbb::enumerable_thread_specific<ThreadLocalRowBuffers> tls_buffers([&] { return ThreadLocalRowBuffers(cols); });
141
142
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 tbb::parallel_for(tbb::blocked_range<int>(0, rows), [&](const tbb::blocked_range<int> &range) {
143 72 auto &buffers = tls_buffers.local();
144
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 72 times.
144 for (int i = range.begin(); i < range.end(); ++i) {
145 72 ComputeRow(a, b, i, buffers, row_values[i], row_cols[i]);
146 }
147 72 });
148
149
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 GetOutput() = BuildResultFromRows(rows, cols, row_values, row_cols);
150 40 return true;
151 40 }
152
153 40 bool KurpiakovACRSMatMulTBB::PostProcessingImpl() {
154 40 return true;
155 }
156
157 } // namespace kurpiakov_a_sp_comp_mat_mul
158