GCC Code Coverage Report


Directory: ./
File: tasks/kulik_a_mat_mul_double_ccs/tbb/src/ops_tbb.cpp
Date: 2026-05-11 08:26:31
Exec Total Coverage
Lines: 55 55 100.0%
Functions: 9 9 100.0%
Branches: 30 44 68.2%

Line Branch Exec Source
1 #include "kulik_a_mat_mul_double_ccs/tbb/include/ops_tbb.hpp"
2
3 #include <tbb/blocked_range.h>
4 #include <tbb/enumerable_thread_specific.h>
5 #include <tbb/tbb.h>
6
7 #include <algorithm>
8 #include <cstddef>
9 #include <tuple>
10 #include <vector>
11
12 #include "kulik_a_mat_mul_double_ccs/common/include/common.hpp"
13 #include "tbb/parallel_for.h"
14
15 namespace kulik_a_mat_mul_double_ccs {
16
17 namespace {
18
19 24 inline void ProcessColumn(size_t j, const CCS &a, const CCS &b, std::vector<double> &accum,
20 std::vector<bool> &nz_elem_rows, std::vector<size_t> &nnz_rows,
21 std::vector<std::vector<double>> &local_values,
22 std::vector<std::vector<size_t>> &local_rows) {
23
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 24 times.
60 for (size_t k = b.col_ind[j]; k < b.col_ind[j + 1]; ++k) {
24 36 size_t ind = b.row[k];
25 36 double b_val = b.value[k];
26
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 36 times.
92 for (size_t zc = a.col_ind[ind]; zc < a.col_ind[ind + 1]; ++zc) {
27 56 size_t i = a.row[zc];
28
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
56 double a_val = a.value[zc];
29
30
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
56 accum[i] += a_val * b_val;
31
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 8 times.
56 if (!nz_elem_rows[i]) {
32 nz_elem_rows[i] = true;
33 nnz_rows.push_back(i);
34 }
35 }
36 }
37
38 std::ranges::sort(nnz_rows);
39
40
3/4
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 24 times.
72 for (size_t i : nnz_rows) {
41
1/2
✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
48 if (accum[i] != 0.0) {
42 local_rows[j].push_back(i);
43 local_values[j].push_back(accum[i]);
44 }
45
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 accum[i] = 0.0;
46 nz_elem_rows[i] = false;
47 }
48 nnz_rows.clear();
49 24 }
50
51 24 inline void CopyColumn(size_t j, CCS &c, const std::vector<std::vector<double>> &local_values,
52 const std::vector<std::vector<size_t>> &local_rows) {
53 24 size_t offset = c.col_ind[j];
54 size_t col_nz = local_values[j].size();
55
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 24 times.
72 for (size_t k = 0; k < col_nz; ++k) {
56 48 c.value[offset + k] = local_values[j][k];
57 48 c.row[offset + k] = local_rows[j][k];
58 }
59 24 }
60
61 } // namespace
62
63 struct ThreadLocalData {
64 std::vector<double> accum;
65 std::vector<bool> nz_elem_rows;
66 std::vector<size_t> nnz_rows;
67 };
68
69
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 KulikAMatMulDoubleCcsTBB::KulikAMatMulDoubleCcsTBB(const InType &in) {
70 SetTypeOfTask(GetStaticTypeOfTask());
71 GetInput() = in;
72 4 }
73
74 4 bool KulikAMatMulDoubleCcsTBB::ValidationImpl() {
75 const auto &a = std::get<0>(GetInput());
76 const auto &b = std::get<1>(GetInput());
77 4 return (a.m == b.n);
78 }
79
80 4 bool KulikAMatMulDoubleCcsTBB::PreProcessingImpl() {
81 4 return true;
82 }
83
84 4 bool KulikAMatMulDoubleCcsTBB::RunImpl() {
85 const auto &a = std::get<0>(GetInput());
86 const auto &b = std::get<1>(GetInput());
87 OutType &c = GetOutput();
88
89 4 c.n = a.n;
90 4 c.m = b.m;
91 4 c.col_ind.assign(c.m + 1, 0);
92
93 4 std::vector<std::vector<double>> local_values(b.m);
94
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 std::vector<std::vector<size_t>> local_rows(b.m);
95
96 4 ThreadLocalData exemplar;
97
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 exemplar.accum.assign(a.n, 0.0);
98
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 exemplar.nz_elem_rows.assign(a.n, false);
99
100
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 tbb::enumerable_thread_specific<ThreadLocalData> tls(exemplar);
101
102
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 tbb::parallel_for(tbb::blocked_range<size_t>(0, b.m), [&](const tbb::blocked_range<size_t> &r) {
103 24 auto &t_data = tls.local();
104
105
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 24 times.
48 for (size_t j = r.begin(); j != r.end(); ++j) {
106 24 ProcessColumn(j, a, b, t_data.accum, t_data.nz_elem_rows, t_data.nnz_rows, local_values, local_rows);
107 }
108 24 });
109
110 size_t total_nz = 0;
111
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 4 times.
28 for (size_t j = 0; j < b.m; ++j) {
112 24 c.col_ind[j] = total_nz;
113 24 total_nz += local_values[j].size();
114 }
115 4 c.col_ind[b.m] = total_nz;
116 4 c.nz = total_nz;
117
118
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 c.value.resize(total_nz);
119
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 c.row.resize(total_nz);
120
121
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
28 tbb::parallel_for(tbb::blocked_range<size_t>(0, b.m), [&](const tbb::blocked_range<size_t> &r) {
122
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 24 times.
48 for (size_t j = r.begin(); j != r.end(); ++j) {
123 24 CopyColumn(j, c, local_values, local_rows);
124 }
125 24 });
126
127 4 return true;
128 4 }
129
130 4 bool KulikAMatMulDoubleCcsTBB::PostProcessingImpl() {
131 4 return true;
132 }
133
134 } // namespace kulik_a_mat_mul_double_ccs
135